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, ' ')); |
||
0 ignored issues
–
show
|
|||
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, ' ')); |
|
0 ignored issues
–
show
|
|||
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, ' '))), |
|
0 ignored issues
–
show
|
|||
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, 'ем', 'ом')), |
|
0 ignored issues
–
show
It seems like
$prefix defined by \morphos\S::name(\morphos\S::slice($name, 0, -2)) on line 257 can also be of type boolean ; however, morphos\Russian\RussianL...hooseEndingBySonority() does only seem to accept string , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.
Loading history...
|
|||
265 | 3 | static::LOCATIVE => $prefix.(static::chooseEndingBySonority($prefix, 'ем', 'ом')), |
|
0 ignored issues
–
show
It seems like
$prefix defined by \morphos\S::name(\morphos\S::slice($name, 0, -2)) on line 257 can also be of type boolean ; however, morphos\Russian\RussianL...hooseEndingBySonority() does only seem to accept string , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.
Loading history...
|
|||
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); |
|
0 ignored issues
–
show
It seems like
$prefix defined by \morphos\S::name(\morphos\S::slice($name, 0, -1)) on line 369 can also be of type boolean ; however, morphos\S::slice() does only seem to accept string , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.
Loading history...
|
|||
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)); |
|
0 ignored issues
–
show
It seems like
$runaway_vowel_offset defined by $runaway_vowels_list[$name] on line 520 can also be of type false ; however, morphos\S::slice() does only seem to accept integer|null , did you maybe forget to handle an error condition?
This check looks for type mismatches where the missing type is Consider the follow example <?php
function getDate($date)
{
if ($date !== null) {
return new DateTime($date);
}
return false;
}
This function either returns a new
Loading history...
|
|||
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.