This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | namespace morphos\Russian; |
||
3 | |||
4 | use morphos\S; |
||
5 | |||
6 | /** |
||
7 | * Rules are from: https://ru.wikipedia.org/wiki/%D0%A1%D0%BA%D0%BB%D0%BE%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D0%B5%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D1%85_%D0%BD%D0%B0%D0%B7%D0%B2%D0%B0%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D1%83%D1%81%D1%81%D0%BA%D0%BE%D0%BC_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B5 |
||
8 | */ |
||
9 | class GeographicalNamesInflection extends \morphos\BaseInflection implements Cases |
||
10 | { |
||
11 | use RussianLanguage, CasesHelper; |
||
12 | |||
13 | /** @var bool Настройка склоняемости славянских топонимов на -ов(о), -ев(о), -ин(о), -ын(о) */ |
||
14 | public static $inflectSlavicNames = true; |
||
15 | |||
16 | /** @var string[] */ |
||
17 | protected static $abbreviations = [ |
||
18 | 'сша', |
||
19 | 'оаэ', |
||
20 | 'ссср', |
||
21 | 'юар', |
||
22 | ]; |
||
23 | |||
24 | /** @var string[] */ |
||
25 | protected static $delimiters = [ |
||
26 | ' ', |
||
27 | '-на-', |
||
28 | '-эль-', |
||
29 | '-де-', |
||
30 | '-сюр-', |
||
31 | '-ан-', |
||
32 | '-ла-', |
||
33 | '-', |
||
34 | ]; |
||
35 | |||
36 | /** @var string[] */ |
||
37 | protected static $ovAbnormalExceptions = [ |
||
38 | 'осташков', |
||
39 | ]; |
||
40 | |||
41 | /** |
||
42 | * @var string[] Immutable names or name parts |
||
43 | */ |
||
44 | protected static $immutableNames = [ |
||
45 | 'алматы', |
||
46 | 'сочи', |
||
47 | 'гоа', |
||
48 | 'домодедово', |
||
49 | 'внуково', |
||
50 | 'шереметьево', |
||
51 | 'остафьево', |
||
52 | 'пулково', |
||
53 | |||
54 | // фикс для Марий Эл |
||
55 | 'марий', |
||
56 | 'эл', |
||
57 | |||
58 | // части |
||
59 | 'алма', |
||
60 | 'буда', |
||
61 | 'йошкар', |
||
62 | 'кабардино', |
||
63 | 'карачаево', |
||
64 | 'рублёво', |
||
65 | 'санкт', |
||
66 | 'улан', |
||
67 | 'ханты', |
||
68 | 'орехово', |
||
69 | 'лосино', |
||
70 | 'юрьево', |
||
71 | 'наро', |
||
72 | |||
73 | // Зарубежные названия |
||
74 | 'пунта', |
||
75 | 'куала', |
||
76 | 'рас', |
||
77 | 'шарм', |
||
78 | 'гран', |
||
79 | 'гранд', |
||
80 | 'вильфранш', |
||
81 | 'льорет', |
||
82 | 'андорра', |
||
83 | 'экс', |
||
84 | 'эс', |
||
85 | 'сен', |
||
86 | 'ла', |
||
87 | ]; |
||
88 | |||
89 | /** @var string[] */ |
||
90 | protected static $immutableTriggerPrefixes = [ |
||
91 | 'спас', |
||
92 | 'усть', |
||
93 | 'соль', |
||
94 | ]; |
||
95 | |||
96 | /** @var string[] */ |
||
97 | protected static $runawayVowelsExceptions = [ |
||
98 | 'торжо*к', |
||
99 | 'волоче*к', |
||
100 | 'орё*л', |
||
101 | 'египе*т', |
||
102 | 'лунине*ц', |
||
103 | 'городо*к', |
||
104 | 'новогрудо*к', |
||
105 | 'острове*ц', |
||
106 | 'черепове*ц', |
||
107 | ]; |
||
108 | |||
109 | /** |
||
110 | * @var string[] |
||
111 | * @phpstan-var array<string, string> |
||
112 | */ |
||
113 | protected static $misspellings = [ |
||
114 | 'орел' => 'орёл', |
||
115 | 'рублево' => 'рублёво', |
||
116 | ]; |
||
117 | |||
118 | /** |
||
119 | * @return int[]|false[] |
||
120 | */ |
||
121 | 13 | View Code Duplication | protected static function getRunAwayVowelsList() |
0 ignored issues
–
show
|
|||
122 | { |
||
123 | 13 | $runawayVowelsNormalized = []; |
|
124 | 13 | foreach (static::$runawayVowelsExceptions as $word) { |
|
125 | 13 | $runawayVowelsNormalized[str_replace('*', '', $word)] = S::indexOf($word, '*') - 1; |
|
126 | } |
||
127 | 13 | return $runawayVowelsNormalized; |
|
128 | } |
||
129 | |||
130 | /** |
||
131 | * Проверяет, склоняемо ли название |
||
132 | * @param string $name Название |
||
133 | * @return bool |
||
134 | */ |
||
135 | 2 | public static function isMutable($name) |
|
136 | { |
||
137 | 2 | $name = S::lower($name); |
|
138 | |||
139 | // // ends with 'ы' or 'и': plural form |
||
140 | // if (in_array(S::slice($name, -1), array('и', 'ы'))) |
||
141 | // return false; |
||
142 | |||
143 | 2 | if (in_array($name, static::$abbreviations, true) || in_array($name, static::$immutableNames, true)) { |
|
144 | 2 | return false; |
|
145 | } |
||
146 | |||
147 | if (strpos($name, ' ') !== false) { |
||
148 | // explode() is not applicable because Geographical unit may have few words |
||
149 | $first_part = S::slice($name, 0, S::findFirstPosition($name, ' ')); |
||
150 | $last_part = S::slice($name, |
||
151 | S::findLastPosition($name, ' ') + 1); |
||
152 | |||
153 | // город N, село N, хутор N, район N, поселок N, округ N, республика N |
||
154 | // N область, N край, N район, N волость |
||
155 | if (in_array($first_part, ['город', 'село', 'хутор', 'район', 'поселок', 'округ', 'республика'], true) |
||
156 | || in_array($last_part, ['край', 'область', 'район', 'волость'], true)) { |
||
157 | return true; |
||
158 | } |
||
159 | |||
160 | // пгт N |
||
161 | if ($first_part === 'пгт') |
||
162 | return false; |
||
163 | } |
||
164 | |||
165 | if (strpos($name, '-') !== false && S::stringContains($name, static::$immutableTriggerPrefixes)) { |
||
166 | return false; |
||
167 | } |
||
168 | |||
169 | // ends with 'е' or 'о', but not with 'ово/ёво/ево/ино/ыно' |
||
170 | if (in_array(S::slice($name, -1), ['е', 'о'], true) |
||
171 | && !in_array(S::slice($name, -3, -1), ['ов', 'ёв', 'ев', 'ин', 'ын'], true)) { |
||
172 | return (bool)static::$inflectSlavicNames; |
||
173 | } |
||
174 | return true; |
||
175 | } |
||
176 | |||
177 | /** |
||
178 | * Получение всех форм названия |
||
179 | * @param string $name |
||
180 | * @return string[] |
||
181 | * @phpstan-return array<string, string> |
||
182 | * @throws \Exception |
||
183 | */ |
||
184 | 48 | public static function getCases($name) |
|
185 | { |
||
186 | 48 | $name = S::lower($name); |
|
187 | |||
188 | // Проверка на неизменяемость |
||
189 | 48 | if (in_array($name, static::$immutableNames, true) |
|
190 | 48 | || (strpos($name, '-') !== false && S::stringContains($name, static::$immutableTriggerPrefixes)) |
|
191 | ) { |
||
192 | 2 | return array_fill_keys( |
|
193 | 2 | [static::IMENIT, static::RODIT, static::DAT, static::VINIT, static::TVORIT, static::PREDLOJ, static::LOCATIVE] |
|
194 | 2 | , S::name($name)); |
|
195 | } |
||
196 | |||
197 | // Проверка на сложное название |
||
198 | 48 | if (strpos($name, ' ') !== false) { |
|
199 | 9 | $first_part = S::slice($name, 0, S::findFirstPosition($name, ' ')); |
|
200 | // город N, село N, хутор N, пгт N |
||
201 | 9 | if (in_array($first_part, ['город', 'село', 'хутор', 'пгт', 'район', 'поселок', 'округ', 'республика'], true)) { |
|
202 | 3 | if ($first_part === 'пгт') |
|
203 | return array_fill_keys( |
||
204 | [static::IMENIT, static::RODIT, static::DAT, static::VINIT, static::TVORIT, static::PREDLOJ, static::LOCATIVE], |
||
205 | 'пгт '.S::name(S::slice($name, 4))); |
||
206 | |||
207 | 3 | if ($first_part === 'республика') { |
|
208 | 1 | $prefix = array_map(['\\morphos\\S', 'name'], NounDeclension::getCases($first_part)); |
|
209 | } else { |
||
210 | 2 | $prefix = NounDeclension::getCases($first_part); |
|
211 | } |
||
212 | 3 | $prefix[Cases::LOCATIVE] = $prefix[Cases::PREDLOJ]; |
|
213 | |||
214 | 3 | return static::composeCasesFromWords([$prefix, |
|
215 | 3 | array_fill_keys( |
|
216 | 3 | array_merge(static::getAllCases(), [\morphos\Russian\Cases::LOCATIVE]), |
|
217 | 3 | S::name(S::slice($name, S::length($first_part) + 1))) |
|
218 | ]); |
||
219 | } |
||
220 | |||
221 | 6 | $last_part = S::slice($name, |
|
222 | 6 | S::findLastPosition($name, ' ') + 1); |
|
223 | // N область, N край |
||
224 | 6 | if (in_array($last_part, ['край', 'область', 'район', 'волость'], true)) { |
|
225 | 2 | $last_part_cases = NounDeclension::getCases($last_part); |
|
226 | 2 | $last_part_cases[Cases::LOCATIVE] = $last_part_cases[Cases::PREDLOJ]; |
|
227 | 2 | return static::composeCasesFromWords( |
|
228 | [ |
||
229 | 2 | static::getCases(S::slice($name, 0, S::findLastPosition($name, ' '))), |
|
230 | 2 | $last_part_cases, |
|
231 | ]); |
||
232 | } |
||
233 | } |
||
234 | |||
235 | // Сложное название с разделителем |
||
236 | 45 | foreach (static::$delimiters as $delimiter) { |
|
237 | 45 | if (strpos($name, $delimiter) !== false) { |
|
238 | 7 | $parts = explode($delimiter, $name); |
|
239 | 7 | $result = []; |
|
240 | 7 | foreach ($parts as $i => $part) { |
|
241 | 7 | $result[$i] = static::getCases($part); |
|
242 | } |
||
243 | 45 | return static::composeCasesFromWords($result, $delimiter); |
|
244 | } |
||
245 | } |
||
246 | |||
247 | // Исправление ошибок |
||
248 | 45 | if (array_key_exists($name, static::$misspellings)) { |
|
249 | $name = static::$misspellings[$name]; |
||
250 | } |
||
251 | |||
252 | // Само склонение |
||
253 | 45 | if (!in_array($name, static::$abbreviations, true)) { |
|
254 | 43 | switch (S::slice($name, -2)) { |
|
255 | // Нижний, Русский |
||
256 | 43 | case 'ий': |
|
257 | 3 | $prefix = S::name(S::slice($name, 0, -2)); |
|
258 | return [ |
||
259 | 3 | static::IMENIT => $prefix.'ий', |
|
260 | 3 | static::RODIT => $prefix.(static::isVelarConsonant(S::slice($name, -3, -2)) ? 'ого' : 'его'), |
|
261 | 3 | static::DAT => $prefix.(static::isVelarConsonant(S::slice($name, -3, -2)) ? 'ому' : 'ему'), |
|
262 | 3 | static::VINIT => $prefix.'ий', |
|
263 | 3 | static::TVORIT => $prefix.'им', |
|
264 | 3 | static::PREDLOJ => $prefix.(static::chooseEndingBySonority($prefix, 'ем', 'ом')), |
|
265 | 3 | static::LOCATIVE => $prefix.(static::chooseEndingBySonority($prefix, 'ем', 'ом')), |
|
266 | ]; |
||
267 | |||
268 | // Ростовская |
||
269 | 42 | case 'ая': |
|
270 | 1 | $prefix = S::name(S::slice($name, 0, -2)); |
|
271 | return [ |
||
272 | 1 | static::IMENIT => $prefix.'ая', |
|
273 | 1 | static::RODIT => $prefix.'ой', |
|
274 | 1 | static::DAT => $prefix.'ой', |
|
275 | 1 | static::VINIT => $prefix.'ую', |
|
276 | 1 | static::TVORIT => $prefix.'ой', |
|
277 | 1 | static::PREDLOJ => $prefix.'ой', |
|
278 | 1 | static::LOCATIVE => $prefix.'ой', |
|
279 | ]; |
||
280 | |||
281 | // Нижняя, Верхняя, Средняя |
||
282 | 41 | case 'яя': |
|
283 | $prefix = S::name(S::slice($name, 0, -2)); |
||
284 | return [ |
||
285 | static::IMENIT => $prefix.'яя', |
||
286 | static::RODIT => $prefix.'ей', |
||
287 | static::DAT => $prefix.'ей', |
||
288 | static::VINIT => $prefix.'юю', |
||
289 | static::TVORIT => $prefix.'ей', |
||
290 | static::PREDLOJ => $prefix.'ей', |
||
291 | static::LOCATIVE => $prefix.'ей', |
||
292 | ]; |
||
293 | |||
294 | // Россошь |
||
295 | 41 | case 'шь': |
|
296 | // Пермь, Кемь |
||
297 | 40 | case 'мь': |
|
298 | // Рязань, Назрань |
||
299 | 39 | case 'нь': |
|
300 | // Сысерть |
||
301 | 38 | case 'ть': |
|
302 | // Керчь |
||
303 | 38 | case 'чь': |
|
304 | 4 | $prefix = S::name(S::slice($name, 0, -1)); |
|
305 | return [ |
||
306 | 4 | static::IMENIT => $prefix.'ь', |
|
307 | 4 | static::RODIT => $prefix.'и', |
|
308 | 4 | static::DAT => $prefix.'и', |
|
309 | 4 | static::VINIT => $prefix.'ь', |
|
310 | 4 | static::TVORIT => $prefix.'ью', |
|
311 | 4 | static::PREDLOJ => $prefix.'и', |
|
312 | 4 | static::LOCATIVE => $prefix.'и', |
|
313 | ]; |
||
314 | |||
315 | // Грозный, Благодарный |
||
316 | 37 | case 'ый': |
|
317 | 2 | $prefix = S::name(S::slice($name, 0, -2)); |
|
318 | return [ |
||
319 | 2 | static::IMENIT => $prefix.'ый', |
|
320 | 2 | static::RODIT => $prefix.'ого', |
|
321 | 2 | static::DAT => $prefix.'ому', |
|
322 | 2 | static::VINIT => $prefix.'ый', |
|
323 | 2 | static::TVORIT => $prefix.'ым', |
|
324 | 2 | static::PREDLOJ => $prefix.'ом', |
|
325 | 2 | static::LOCATIVE => $prefix.'ом', |
|
326 | ]; |
||
327 | |||
328 | // Ставрополь, Ярославль, Электросталь |
||
329 | 35 | case 'ль': |
|
330 | 2 | $prefix = S::name(S::slice($name, 0, -1)); |
|
331 | |||
332 | 2 | if ($name === 'электросталь') |
|
333 | return [ |
||
334 | 1 | static::IMENIT => $prefix.'ь', |
|
335 | 1 | static::RODIT => $prefix.'и', |
|
336 | 1 | static::DAT => $prefix.'и', |
|
337 | 1 | static::VINIT => $prefix.'ь', |
|
338 | 1 | static::TVORIT => $prefix.'ью', |
|
339 | 1 | static::PREDLOJ => $prefix.'и', |
|
340 | 1 | static::LOCATIVE => $prefix.'и', |
|
341 | ]; |
||
342 | |||
343 | return [ |
||
344 | 1 | static::IMENIT => $prefix.'ь', |
|
345 | 1 | static::RODIT => $prefix.'я', |
|
346 | 1 | static::DAT => $prefix.'ю', |
|
347 | 1 | static::VINIT => $prefix.'ь', |
|
348 | 1 | static::TVORIT => $prefix.'ем', |
|
349 | 1 | static::PREDLOJ => $prefix.'е', |
|
350 | 1 | static::LOCATIVE => $prefix.'е', |
|
351 | ]; |
||
352 | |||
353 | // Адыгея, Чечня |
||
354 | 33 | case 'ея': |
|
355 | 32 | case 'ня': |
|
356 | 1 | $prefix = S::name(S::slice($name, 0, -1)); |
|
357 | return [ |
||
358 | 1 | static::IMENIT => S::name($name), |
|
359 | 1 | static::RODIT => $prefix.'е', |
|
360 | 1 | static::DAT => $prefix.'е', |
|
361 | 1 | static::VINIT => $prefix.'я', |
|
362 | 1 | static::TVORIT => $prefix.'ей', |
|
363 | 1 | static::PREDLOJ => $prefix.'е', |
|
364 | 1 | static::LOCATIVE => $prefix.'е', |
|
365 | ]; |
||
366 | |||
367 | // Тверь, Анадырь |
||
368 | 32 | case 'рь': |
|
369 | 2 | $prefix = S::name(S::slice($name, 0, -1)); |
|
370 | 2 | $last_vowel = S::slice($prefix, -2, -1); |
|
371 | return [ |
||
372 | 2 | static::IMENIT => $prefix . 'ь', |
|
373 | 2 | static::RODIT => $prefix . (static::isBinaryVowel($last_vowel) ? 'и' : 'я'), |
|
374 | 2 | static::DAT => $prefix . (static::isBinaryVowel($last_vowel) ? 'и' : 'ю'), |
|
375 | 2 | static::VINIT => $prefix . 'ь', |
|
376 | 2 | static::TVORIT => $prefix . (static::isBinaryVowel($last_vowel) ? 'ью' : 'ем'), |
|
377 | 2 | static::PREDLOJ => $prefix . (static::isBinaryVowel($last_vowel) ? 'и' : 'е'), |
|
378 | 2 | static::LOCATIVE => $prefix . (static::isBinaryVowel($last_vowel) ? 'и' : 'е'), |
|
379 | ]; |
||
380 | |||
381 | // Березники, Ессентуки |
||
382 | 30 | case 'ки': |
|
383 | // Старые Дороги |
||
384 | 29 | case 'ги': |
|
385 | // Ушачи, Ивацевичи |
||
386 | 29 | case 'чи': |
|
387 | 3 | $prefix = S::name(S::slice($name, 0, -1)); |
|
388 | return [ |
||
389 | 3 | static::IMENIT => $prefix . 'и', |
|
390 | 3 | static::RODIT => ($name === 'луки' |
|
391 | 1 | ? $prefix |
|
392 | 2 | : (S::slice($name, -2) === 'чи' |
|
393 | 1 | ? $prefix . 'ей' |
|
394 | 3 | : $prefix . 'ов')), |
|
395 | 3 | static::DAT => $prefix . 'ам', |
|
396 | 3 | static::VINIT => $prefix . 'и', |
|
397 | 3 | static::TVORIT => $prefix . 'ами', |
|
398 | 3 | static::PREDLOJ => $prefix . 'ах', |
|
399 | 3 | static::LOCATIVE => $prefix . 'ах', |
|
400 | ]; |
||
401 | |||
402 | // Набережные |
||
403 | 28 | case 'ые': |
|
404 | // Великие |
||
405 | 28 | case 'ие': |
|
406 | 2 | $prefix = S::name(S::slice($name, 0, -1)); |
|
407 | return [ |
||
408 | 2 | static::IMENIT => $prefix . 'е', |
|
409 | 2 | static::RODIT => $prefix . 'х', |
|
410 | 2 | static::DAT => $prefix . 'м', |
|
411 | 2 | static::VINIT => $prefix . 'е', |
|
412 | 2 | static::TVORIT => $prefix . 'ми', |
|
413 | 2 | static::PREDLOJ => $prefix . 'х', |
|
414 | 2 | static::LOCATIVE => $prefix . 'х', |
|
415 | ]; |
||
416 | |||
417 | // Челны |
||
418 | 27 | case 'ны': |
|
419 | // Мосты |
||
420 | 26 | case 'ты': |
|
421 | // Столбцы |
||
422 | 26 | case 'цы': |
|
423 | 2 | $prefix = S::name(S::slice($name, 0, -1)); |
|
424 | return [ |
||
425 | 2 | static::IMENIT => $prefix . 'ы', |
|
426 | 2 | static::RODIT => $prefix . 'ов', |
|
427 | 2 | static::DAT => $prefix . 'ам', |
|
428 | 2 | static::VINIT => $prefix . 'ы', |
|
429 | 2 | static::TVORIT => $prefix . 'ами', |
|
430 | 2 | static::PREDLOJ => $prefix . 'ах', |
|
431 | 2 | static::LOCATIVE => $prefix . 'ах', |
|
432 | ]; |
||
433 | |||
434 | // Глубокое |
||
435 | 25 | case 'ое': |
|
436 | 1 | $prefix = S::name(S::slice($name, 0, -2)); |
|
437 | return [ |
||
438 | 1 | static::IMENIT => $prefix.'ое', |
|
439 | 1 | static::RODIT => $prefix.'ого', |
|
440 | 1 | static::DAT => $prefix.'ому', |
|
441 | 1 | static::VINIT => $prefix.'ое', |
|
442 | 1 | static::TVORIT => $prefix.'им', |
|
443 | 1 | static::PREDLOJ => $prefix.'ом', |
|
444 | 1 | static::LOCATIVE => $prefix.'ом', |
|
445 | ]; |
||
446 | } |
||
447 | |||
448 | 24 | switch (S::slice($name, -1)) { |
|
449 | 24 | case 'р': |
|
450 | // Бор |
||
451 | $prefix = S::name(S::slice($name, 0, -1)); |
||
452 | return [ |
||
453 | static::IMENIT => $prefix.'р', |
||
454 | static::RODIT => $prefix.'ра', |
||
455 | static::DAT => $prefix.'ру', |
||
456 | static::VINIT => $prefix.'р', |
||
457 | static::TVORIT => $prefix.'ром', |
||
458 | static::PREDLOJ => $prefix.'ре', |
||
459 | static::LOCATIVE => $prefix.'ру', |
||
460 | ]; |
||
461 | |||
462 | 24 | case 'ы': |
|
463 | // Чебоксары, Шахты |
||
464 | 1 | $prefix = S::name(S::slice($name, 0, -1)); |
|
465 | return [ |
||
466 | 1 | static::IMENIT => $prefix.'ы', |
|
467 | 1 | static::RODIT => $prefix, |
|
468 | 1 | static::DAT => $prefix.'ам', |
|
469 | 1 | static::VINIT => $prefix.'ы', |
|
470 | 1 | static::TVORIT => $prefix.'ами', |
|
471 | 1 | static::PREDLOJ => $prefix.'ах', |
|
472 | 1 | static::LOCATIVE => $prefix.'ах', |
|
473 | ]; |
||
474 | |||
475 | 23 | case 'я': |
|
476 | // Азия |
||
477 | 1 | $prefix = S::name(S::slice($name, 0, -1)); |
|
478 | return [ |
||
479 | 1 | static::IMENIT => S::name($name), |
|
480 | 1 | static::RODIT => $prefix.'и', |
|
481 | 1 | static::DAT => $prefix.'и', |
|
482 | 1 | static::VINIT => $prefix.'ю', |
|
483 | 1 | static::TVORIT => $prefix.'ей', |
|
484 | 1 | static::PREDLOJ => $prefix.'и', |
|
485 | 1 | static::LOCATIVE => $prefix.'и', |
|
486 | ]; |
||
487 | |||
488 | 22 | case 'а': |
|
489 | // Москва, Рига |
||
490 | 5 | $prefix = S::name(S::slice($name, 0, -1)); |
|
491 | return [ |
||
492 | 5 | static::IMENIT => $prefix.'а', |
|
493 | 5 | static::RODIT => $prefix.(static::isVelarConsonant(S::slice($name, -2, -1)) || static::isHissingConsonant(S::slice($name, -2, -1)) ? 'и' : 'ы'), |
|
494 | 5 | static::DAT => $prefix.'е', |
|
495 | 5 | static::VINIT => $prefix.'у', |
|
496 | 5 | static::TVORIT => $prefix.'ой', |
|
497 | 5 | static::PREDLOJ => $prefix.'е', |
|
498 | 5 | static::LOCATIVE => $prefix.'е', |
|
499 | ]; |
||
500 | |||
501 | 17 | case 'й': |
|
502 | // Ишимбай |
||
503 | 2 | $prefix = S::name(S::slice($name, 0, -1)); |
|
504 | return [ |
||
505 | 2 | static::IMENIT => $prefix . 'й', |
|
506 | 2 | static::RODIT => $prefix . 'я', |
|
507 | 2 | static::DAT => $prefix . 'ю', |
|
508 | 2 | static::VINIT => $prefix . 'й', |
|
509 | 2 | static::TVORIT => $prefix . 'ем', |
|
510 | 2 | static::PREDLOJ => $prefix . 'е', |
|
511 | 2 | static::LOCATIVE => $prefix . 'е', |
|
512 | ]; |
||
513 | } |
||
514 | |||
515 | 15 | if (static::isConsonant($last_char = S::slice($name, -1)) && !in_array($name, static::$ovAbnormalExceptions, true)) { |
|
516 | 13 | $runaway_vowels_list = static::getRunAwayVowelsList(); |
|
517 | |||
518 | // if run-away vowel in name |
||
519 | 13 | if (isset($runaway_vowels_list[$name])) { |
|
520 | 4 | $runaway_vowel_offset = $runaway_vowels_list[$name]; |
|
521 | 4 | $prefix = S::name(S::slice($name, 0, $runaway_vowel_offset) . S::slice($name, $runaway_vowel_offset + 1)); |
|
522 | } else { |
||
523 | 9 | $prefix = S::name($name); |
|
524 | } |
||
525 | |||
526 | // Париж, Валаам, Киев |
||
527 | return [ |
||
528 | 13 | static::IMENIT => S::name($name), |
|
529 | 13 | static::RODIT => $prefix . 'а', |
|
530 | 13 | static::DAT => $prefix . 'у', |
|
531 | 13 | static::VINIT => S::name($name), |
|
532 | 13 | static::TVORIT => $prefix . ( |
|
533 | 13 | static::isVelarConsonant(S::slice($name, -2, -1)) |
|
534 | 13 | || static::isHissingConsonant($last_char) |
|
535 | 13 | ? 'ем' : 'ом'), |
|
536 | 13 | static::PREDLOJ => $prefix . 'е', |
|
537 | 13 | static::LOCATIVE => $prefix.($name === 'крым' ? 'у' : 'е'), |
|
538 | ]; |
||
539 | } |
||
540 | |||
541 | // ов, ово, ёв, ёво, ев, ево, ... |
||
542 | 3 | $suffixes = ['ов', 'ёв', 'ев', 'ин', 'ын']; |
|
543 | 3 | if (static::$inflectSlavicNames && ( |
|
544 | 3 | (in_array(S::slice($name, -1), ['е', 'о'], true) && in_array(S::slice($name, -3, -1), $suffixes, true)) |
|
545 | 3 | || in_array(S::slice($name, -2), $suffixes, true) |
|
546 | )) { |
||
547 | // ово, ёво, ... |
||
548 | 2 | if (in_array(S::slice($name, -3, -1), $suffixes, true)) { |
|
549 | 1 | $prefix = S::name(S::slice($name, 0, -1)); |
|
550 | } |
||
551 | // ов, её, ... |
||
552 | 1 | elseif (in_array(S::slice($name, -2), $suffixes, true)) { |
|
553 | 1 | $prefix = S::name($name); |
|
554 | } else { |
||
555 | $prefix = ''; |
||
556 | } |
||
557 | |||
558 | return [ |
||
559 | 2 | static::IMENIT => S::name($name), |
|
560 | 2 | static::RODIT => $prefix.'а', |
|
561 | 2 | static::DAT => $prefix.'у', |
|
562 | 2 | static::VINIT => S::name($name), |
|
563 | 2 | static::TVORIT => $name !== 'осташков' ? $prefix.'ом' : $prefix.'ым', |
|
564 | 2 | static::PREDLOJ => $prefix.'е', |
|
565 | 2 | static::LOCATIVE => $prefix.'е', |
|
566 | ]; |
||
567 | } |
||
568 | } |
||
569 | |||
570 | // if no rules matches or name is immutable |
||
571 | 3 | $name = in_array($name, static::$abbreviations, true) ? S::upper($name) : S::name($name); |
|
572 | 3 | return array_fill_keys( |
|
573 | 3 | [static::IMENIT, static::RODIT, static::DAT, static::VINIT, static::TVORIT, static::PREDLOJ, static::LOCATIVE], |
|
574 | 3 | $name); |
|
575 | } |
||
576 | |||
577 | /** |
||
578 | * Получение одной формы (падежа) названия. |
||
579 | * @param string $name Название |
||
580 | * @param string $case Падеж. Одна из констант {@see \morphos\Russian\Cases} или {@see \morphos\Cases}. |
||
581 | * @see \morphos\Russian\Cases |
||
582 | * @return string |
||
583 | * @throws \Exception |
||
584 | */ |
||
585 | public static function getCase($name, $case) |
||
586 | { |
||
587 | $case = static::canonizeCase($case); |
||
588 | $forms = static::getCases($name); |
||
589 | return $forms[$case]; |
||
590 | } |
||
591 | } |
||
592 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.