diff --git a/src/Russian/GeographicalNamesInflection.php b/src/Russian/GeographicalNamesInflection.php index b0aa12b..b25e6c0 100644 --- a/src/Russian/GeographicalNamesInflection.php +++ b/src/Russian/GeographicalNamesInflection.php @@ -17,6 +17,11 @@ class GeographicalNamesInflection extends \morphos\BaseInflection implements Cas 'юар', ); + /** + * Проверяет, склоняемо ли название + * @param string $name Название + * @return bool + */ public static function isMutable($name) { $name = S::lower($name); @@ -51,6 +56,11 @@ public static function isMutable($name) return true; } + /** + * Получение всех форм названия + * @param string $name + * @return array + */ public static function getCases($name) { $name = S::lower($name); @@ -73,10 +83,10 @@ public static function getCases($name) ]); } - // check for name of few words + // Сложное название города из нескольких слов через пробел. + // Нижний Новгород, Набережные Челны if (strpos($name, ' ') !== false) { $parts = explode(' ', $name); - $cases = array(); $result = array(); foreach ($parts as $i => $part) { $result[$i] = static::getCases($part); @@ -84,6 +94,30 @@ public static function getCases($name) return self::composeCasesFromWords($result); } + // Сложное название города из нескольких слов через тире. + // Ростов-на-Дону, Переславль-Залесский + if (strpos($name, '-') !== false) { + // грязный хак, но подобных случаев как с Ростовом-на-Дону нету + if ($name == 'ростов-на-дону') { + return [ + self::IMENIT => 'Ростов-на-Дону', + self::RODIT => 'Ростова-на-Дону', + self::DAT => 'Ростову-на-Дону', + self::VINIT => 'Ростов-на-Дону', + self::TVORIT => 'Ростовом-на-Дону', + self::PREDLOJ => 'Ростове-на-Дону' + ]; + } else { + $parts = explode('-', $name); + $result = array( + array_fill_keys([self::IMENIT, self::RODIT, self::DAT, self::VINIT, self::TVORIT, self::PREDLOJ], S::name($parts[0])), + ); + for ($i = 1, $total_parts = count($parts); $i < $total_parts; $i++) + $result[] = static::getCases($parts[$i]); // вторая часть, склоняемая + } + return self::composeCasesFromWords($result, '-'); + } + if (!in_array($name, self::$abbreviations)) { if (S::slice($name, -2) == 'ий') { // Нижний, Русский @@ -267,6 +301,13 @@ public static function getCases($name) return array_fill_keys(array(self::IMENIT, self::RODIT, self::DAT, self::VINIT, self::TVORIT, self::PREDLOJ), $name); } + /** + * Получение одной формы (падежа) названия. + * @param string $name Название + * @param integer $case Падеж. Одна из констант \morphos\Russian\Cases или \morphos\Cases. + * @see \morphos\Russian\Cases + * @return mixed + */ public static function getCase($name, $case) { $case = self::canonizeCase($case); diff --git a/tests/Russian/GeographicalNamesInflectionTest.php b/tests/Russian/GeographicalNamesInflectionTest.php index 3812ea7..07d3582 100644 --- a/tests/Russian/GeographicalNamesInflectionTest.php +++ b/tests/Russian/GeographicalNamesInflectionTest.php @@ -48,6 +48,7 @@ public function wordsProvider() ['Санкт-Петербург', 'Санкт-Петербурга', 'Санкт-Петербургу', 'Санкт-Петербург', 'Санкт-Петербургом', 'Санкт-Петербурге'], ['Нижний Новгород', 'Нижнего Новгорода', 'Нижнему Новгороду', 'Нижний Новгород', 'Нижним Новгородом', 'Нижнем Новгороде'], ['Набережные Челны', 'Набережных Челнов', 'Набережным Челнам', 'Набережные Челны', 'Набережными Челнами', 'Набережных Челнах'], + ['Ростов-на-Дону', 'Ростова-на-Дону', 'Ростову-на-Дону', 'Ростов-на-Дону', 'Ростовом-на-Дону', 'Ростове-на-Дону'], // N край ['Краснодарский край', 'Краснодарского края', 'Краснодарскому краю', 'Краснодарский край', 'Краснодарским краем', 'Краснодарском крае'],