|
1
|
|
|
<?php |
|
2
|
|
|
namespace morphos\Russian; |
|
3
|
|
|
|
|
4
|
|
|
use morphos\S; |
|
5
|
|
|
|
|
6
|
|
|
/** |
|
7
|
|
|
* Rules are from: http://www.imena.org/decl_mn.html / http://www.imena.org/decl_fn.html |
|
8
|
|
|
* and http://rus.omgpu.ru/2016/04/18/%D1%81%D0%BA%D0%BB%D0%BE%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BB%D0%B8%D1%87%D0%BD%D1%8B%D1%85-%D0%B8%D0%BC%D1%91%D0%BD/ |
|
9
|
|
|
*/ |
|
10
|
|
|
class FirstNamesInflection extends \morphos\NamesInflection implements Cases |
|
11
|
|
|
{ |
|
12
|
|
|
use RussianLanguage, CasesHelper; |
|
13
|
|
|
|
|
14
|
|
|
protected static $exceptions = [ |
|
15
|
|
|
'лев' => [ |
|
16
|
|
|
self::IMENIT => 'Лев', |
|
17
|
|
|
self::RODIT => 'Льва', |
|
18
|
|
|
self::DAT => 'Льву', |
|
19
|
|
|
self::VINIT => 'Льва', |
|
20
|
|
|
self::TVORIT => 'Львом', |
|
21
|
|
|
self::PREDLOJ => 'Льве', |
|
22
|
|
|
], |
|
23
|
|
|
'павел' => [ |
|
24
|
|
|
self::IMENIT => 'Павел', |
|
25
|
|
|
self::RODIT => 'Павла', |
|
26
|
|
|
self::DAT => 'Павлу', |
|
27
|
|
|
self::VINIT => 'Павла', |
|
28
|
|
|
self::TVORIT => 'Павлом', |
|
29
|
|
|
self::PREDLOJ => 'Павле', |
|
30
|
|
|
] |
|
31
|
|
|
]; |
|
32
|
|
|
|
|
33
|
|
|
protected static $menNames = [ |
|
34
|
|
|
'абрам', 'аверьян', 'авраам', 'агафон', 'адам', 'азар', 'акакий', 'аким', 'аксён', 'александр', 'алексей', |
|
35
|
|
|
'альберт', 'анатолий', 'андрей', 'андрон', 'антип', 'антон', 'аполлон', 'аристарх', 'аркадий', 'арнольд', |
|
36
|
|
|
'арсений', 'арсентий', 'артем', 'артём', 'артемий', 'артур', 'аскольд', 'афанасий', 'богдан', 'борис', |
|
37
|
|
|
'борислав', 'бронислав', 'вадим', 'валентин', 'валерий', 'варлам', 'василий', 'венедикт', 'вениамин', |
|
38
|
|
|
'веньямин', 'венцеслав', 'виктор', 'виген', 'вилен', 'виталий', 'владилен', 'владимир', 'владислав', 'владлен', |
|
39
|
|
|
'вова', 'всеволод', 'всеслав', 'вячеслав', 'гавриил', 'геннадий', 'георгий', 'герман', 'глеб', 'григорий', |
|
40
|
|
|
'давид', 'даниил', 'данил', 'данила', 'демьян', 'денис', 'димитрий', 'дмитрий', 'добрыня', 'евгений', 'евдоким', |
|
41
|
|
|
'евсей', 'егор', 'емельян', 'еремей', 'ермолай', 'ерофей', 'ефим', 'захар', 'иван', 'игнат', 'игорь', |
|
42
|
|
|
'илларион', 'иларион', 'илья', 'иосиф', 'казимир', 'касьян', 'кирилл', 'кондрат', 'константин', 'кузьма', |
|
43
|
|
|
'лавр', 'лаврентий', 'лазарь', 'ларион', 'лев', 'леонард', 'леонид', 'лука', 'максим', 'марат', 'мартын', |
|
44
|
|
|
'матвей', 'мефодий', 'мирон', 'михаил', 'моисей', 'назар', 'никита', 'николай', 'олег', 'осип', 'остап', |
|
45
|
|
|
'павел', 'панкрат', 'пантелей', 'парамон', 'пётр', 'петр', 'платон', 'потап', 'прохор', 'роберт', 'ростислав', |
|
46
|
|
|
'савва', 'савелий', 'семён', 'семен', 'сергей', 'сидор', 'спартак', 'тарас', 'терентий', 'тимофей', 'тимур', |
|
47
|
|
|
'тихон', 'ульян', 'фёдор', 'федор', 'федот', 'феликс', 'фирс', 'фома', 'харитон', 'харлам', 'эдуард', |
|
48
|
|
|
'эммануил', 'эраст', 'юлиан', 'юлий', 'юрий', 'яков', 'ян', 'ярослав', |
|
49
|
|
|
]; |
|
50
|
|
|
|
|
51
|
|
|
protected static $womenNames = [ |
|
52
|
|
|
'авдотья', 'аврора', 'агата', 'агния', 'агриппина', 'ада', 'аксинья', 'алевтина', 'александра', 'алёна', |
|
53
|
|
|
'алена', 'алина', 'алиса', 'алла', 'альбина', 'амалия', 'анастасия', 'ангелина', 'анжела', 'анжелика', 'анна', |
|
54
|
|
|
'антонина', 'анфиса', 'арина', 'белла', 'божена', 'валентина', 'валерия', 'ванда', 'варвара', 'василина', |
|
55
|
|
|
'василиса', 'вера', 'вероника', 'виктория', 'виола', 'виолетта', 'вита', 'виталия', 'владислава', 'власта', |
|
56
|
|
|
'галина', 'глафира', 'дарья', 'диана', 'дина', 'ева', 'евгения', 'евдокия', 'евлампия', 'екатерина', 'елена', |
|
57
|
|
|
'елизавета', 'ефросиния', 'ефросинья', 'жанна', 'зиновия', 'злата', 'зоя', 'ивонна', 'изольда', 'илона', 'инга', |
|
58
|
|
|
'инесса', 'инна', 'ирина', 'ия', 'капитолина', 'карина', 'каролина', 'кира', 'клавдия', 'клара', 'клеопатра', |
|
59
|
|
|
'кристина', 'ксения', 'лада', 'лариса', 'лиана', 'лидия', 'лилия', 'лина', 'лия', 'лора', 'любава', 'любовь', |
|
60
|
|
|
'людмила', 'майя', 'маргарита', 'марианна', 'мариетта', 'марина', 'мария', 'марья', 'марта', 'марфа', 'марьяна', |
|
61
|
|
|
'матрёна', 'матрена', 'матрона', 'милена', 'милослава', 'мирослава', 'муза', 'надежда', 'настасия', 'настасья', |
|
62
|
|
|
'наталия', 'наталья', 'нелли', 'ника', 'нина', 'нинель', 'нонна', 'оксана', 'олимпиада', 'ольга', 'пелагея', |
|
63
|
|
|
'полина', 'прасковья', 'раиса', 'рената', 'римма', 'роза', 'роксана', 'руфь', 'сарра', 'светлана', 'серафима', |
|
64
|
|
|
'снежана', 'софья', 'софия', 'стелла', 'степанида', 'стефания', 'таисия', 'таисья', 'тамара', 'татьяна', |
|
65
|
|
|
'ульяна', 'устиния', 'устинья', 'фаина', 'фёкла', 'фекла', 'феодора', 'хаврония', 'христина', 'эвелина', |
|
66
|
|
|
'эдита', 'элеонора', 'элла', 'эльвира', 'эмилия', 'эмма', 'юдифь', 'юлиана', 'юлия', 'ядвига', 'яна', |
|
67
|
|
|
'ярослава', |
|
68
|
|
|
]; |
|
69
|
|
|
|
|
70
|
|
|
protected static $immutableNames = [ |
|
71
|
|
|
'николя', |
|
72
|
|
|
]; |
|
73
|
|
|
|
|
74
|
|
|
/** |
|
75
|
|
|
* Checks if name is mutable |
|
76
|
|
|
* @param string $name |
|
77
|
|
|
* @param null|string $gender |
|
78
|
|
|
* @return bool |
|
79
|
|
|
*/ |
|
80
|
716 |
|
public static function isMutable($name, $gender = null) |
|
81
|
|
|
{ |
|
82
|
716 |
|
$name = S::lower($name); |
|
83
|
|
|
|
|
84
|
716 |
|
if (in_array($name, self::$immutableNames, true)) { |
|
85
|
|
|
return false; |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
716 |
|
if ($gender === null) { |
|
89
|
|
|
$gender = self::detectGender($name); |
|
90
|
|
|
} |
|
91
|
|
|
|
|
92
|
|
|
// man rules |
|
93
|
716 |
|
if ($gender === self::MALE) { |
|
94
|
|
|
// soft consonant |
|
95
|
451 |
|
if (S::lower(S::slice($name, -1)) == 'ь' && self::isConsonant(S::slice($name, -2, -1))) { |
|
|
|
|
|
|
96
|
14 |
|
return true; |
|
97
|
437 |
|
} elseif (in_array(S::slice($name, -1), array_diff(self::$consonants, ['й', /*'Ч', 'Щ'*/]), true)) { // hard consonant |
|
|
|
|
|
|
98
|
259 |
|
return true; |
|
99
|
178 |
|
} elseif (S::slice($name, -1) == 'й') { |
|
|
|
|
|
|
100
|
104 |
|
return true; |
|
101
|
74 |
View Code Duplication |
} else if (in_array(S::slice($name, -2), ['ло', 'ко'], true)) { |
|
|
|
|
|
|
102
|
74 |
|
return true; |
|
103
|
|
|
} |
|
104
|
265 |
|
} else if ($gender === self::FEMALE) { |
|
105
|
|
|
// soft consonant |
|
106
|
265 |
|
if (S::lower(S::slice($name, -1)) == 'ь' && self::isConsonant(S::slice($name, -2, -1))) { |
|
|
|
|
|
|
107
|
4 |
|
return true; |
|
108
|
261 |
|
} else if (self::isHissingConsonant(S::slice($name, -1))) { |
|
|
|
|
|
|
109
|
5 |
|
return true; |
|
110
|
|
|
} |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
// common rules |
|
114
|
326 |
|
if ((in_array(S::slice($name, -1), ['а', 'я']) && !self::isVowel(S::slice($name, -2, -1))) || in_array(S::slice($name, -2), ['ия', 'ья', 'ея', 'оя'], true)) { |
|
|
|
|
|
|
115
|
275 |
|
return true; |
|
116
|
|
|
} |
|
117
|
|
|
|
|
118
|
51 |
|
return false; |
|
119
|
|
|
} |
|
120
|
|
|
|
|
121
|
|
|
/** |
|
122
|
|
|
* @param $name |
|
123
|
|
|
* @return string |
|
124
|
|
|
*/ |
|
125
|
510 |
|
public static function detectGender($name) |
|
126
|
|
|
{ |
|
127
|
510 |
|
$name = S::lower($name); |
|
128
|
510 |
|
if (in_array($name, self::$menNames, true)) { |
|
129
|
121 |
|
return self::MALE; |
|
130
|
390 |
|
} elseif (in_array($name, self::$womenNames, true)) { |
|
131
|
111 |
|
return self::FEMALE; |
|
132
|
|
|
} |
|
133
|
|
|
|
|
134
|
279 |
|
$man = $woman = 0; |
|
135
|
279 |
|
$last1 = S::slice($name, -1); |
|
|
|
|
|
|
136
|
279 |
|
$last2 = S::slice($name, -2); |
|
|
|
|
|
|
137
|
279 |
|
$last3 = S::slice($name, -3); |
|
|
|
|
|
|
138
|
|
|
|
|
139
|
|
|
// try to detect gender by some statistical rules |
|
140
|
|
|
// |
|
141
|
279 |
|
if ($last1 == 'й') { |
|
142
|
48 |
|
$man += 0.9; |
|
143
|
|
|
} |
|
144
|
279 |
|
if ($last1 == 'ь') { |
|
145
|
|
|
$man += 0.02; |
|
146
|
|
|
} |
|
147
|
279 |
|
if (in_array($last1, self::$consonants, true)) { |
|
148
|
199 |
|
$man += 0.01; |
|
149
|
|
|
} |
|
150
|
279 |
|
if (in_array($last2, ['он', 'ов', 'ав', 'ам', 'ол', 'ан', 'рд', 'мп'], true)) { |
|
151
|
47 |
|
$man += 0.3; |
|
152
|
|
|
} |
|
153
|
279 |
|
if (in_array($last2, ['вь', 'фь', 'ль'], true)) { |
|
154
|
|
|
$woman += 0.1; |
|
155
|
|
|
} |
|
156
|
279 |
|
if (in_array($last2, ['ла'], true)) { |
|
157
|
4 |
|
$woman += 0.04; |
|
158
|
|
|
} |
|
159
|
279 |
|
if (in_array($last2, ['то', 'ма'], true)) { |
|
160
|
|
|
$man += 0.01; |
|
161
|
|
|
} |
|
162
|
279 |
View Code Duplication |
if (in_array($last3, ['лья', 'вва', 'ока', 'ука', 'ита'], true)) { |
|
|
|
|
|
|
163
|
2 |
|
$man += 0.2; |
|
164
|
|
|
} |
|
165
|
279 |
|
if (in_array($last3, ['има'], true)) { |
|
166
|
|
|
$woman += 0.15; |
|
167
|
|
|
} |
|
168
|
279 |
View Code Duplication |
if (in_array($last3, ['лия', 'ния', 'сия', 'дра', 'лла', 'кла', 'опа'], true)) { |
|
|
|
|
|
|
169
|
3 |
|
$woman += 0.5; |
|
170
|
|
|
} |
|
171
|
279 |
|
if (in_array(S::slice($name, -4), ['льда', 'фира', 'нина', 'лита', 'алья'], true)) { |
|
|
|
|
|
|
172
|
|
|
$woman += 0.5; |
|
173
|
|
|
} |
|
174
|
|
|
|
|
175
|
279 |
|
return $man === $woman ? null |
|
176
|
279 |
|
: ($man > $woman ? self::MALE : self::FEMALE); |
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
/** |
|
180
|
|
|
* @param string $name |
|
181
|
|
|
* @param null|string $gender |
|
182
|
|
|
* @return array |
|
183
|
|
|
*/ |
|
184
|
140 |
|
public static function getCases($name, $gender = null) |
|
185
|
|
|
{ |
|
186
|
140 |
|
$name = S::lower($name); |
|
187
|
|
|
|
|
188
|
140 |
|
if (self::isMutable($name, $gender)) { |
|
|
|
|
|
|
189
|
|
|
// common rules for ия and я |
|
190
|
140 |
|
if (S::slice($name, -2) == 'ия') { |
|
|
|
|
|
|
191
|
20 |
|
$prefix = S::name(S::slice($name, 0, -1)); |
|
|
|
|
|
|
192
|
|
|
return [ |
|
193
|
20 |
|
self::IMENIT => $prefix.'я', |
|
194
|
20 |
|
self::RODIT => $prefix.'и', |
|
195
|
20 |
|
self::DAT => $prefix.'и', |
|
196
|
20 |
|
self::VINIT => $prefix.'ю', |
|
197
|
20 |
|
self::TVORIT => $prefix.'ей', |
|
198
|
20 |
|
self::PREDLOJ => $prefix.'и', |
|
199
|
|
|
]; |
|
200
|
120 |
View Code Duplication |
} elseif (S::slice($name, -1) == 'я') { |
|
|
|
|
|
|
201
|
10 |
|
$prefix = S::name(S::slice($name, 0, -1)); |
|
|
|
|
|
|
202
|
|
|
return [ |
|
203
|
10 |
|
self::IMENIT => $prefix.'я', |
|
204
|
10 |
|
self::RODIT => $prefix.'и', |
|
205
|
10 |
|
self::DAT => $prefix.'е', |
|
206
|
10 |
|
self::VINIT => $prefix.'ю', |
|
207
|
10 |
|
self::TVORIT => $prefix.'ей', |
|
208
|
10 |
|
self::PREDLOJ => $prefix.'е', |
|
209
|
|
|
]; |
|
210
|
|
|
} |
|
211
|
|
|
|
|
212
|
110 |
|
if (!in_array($name, self::$immutableNames, true)) { |
|
213
|
110 |
|
if ($gender === null) { |
|
214
|
|
|
$gender = self::detectGender($name); |
|
215
|
|
|
} |
|
216
|
110 |
|
if ($gender === self::MALE || $name === 'саша') { |
|
217
|
84 |
|
if (($result = self::getCasesMan($name)) !== null) { |
|
|
|
|
|
|
218
|
84 |
|
return $result; |
|
219
|
|
|
} |
|
220
|
26 |
|
} elseif ($gender === self::FEMALE) { |
|
221
|
26 |
|
if (($result = self::getCasesWoman($name)) !== null) { |
|
|
|
|
|
|
222
|
26 |
|
return $result; |
|
223
|
|
|
} |
|
224
|
|
|
} |
|
225
|
|
|
} |
|
226
|
|
|
} |
|
227
|
|
|
|
|
228
|
|
|
$name = S::name($name); |
|
229
|
|
|
return array_fill_keys(array(self::IMENIT, self::RODIT, self::DAT, self::VINIT, self::TVORIT, self::PREDLOJ), $name); |
|
230
|
|
|
} |
|
231
|
|
|
|
|
232
|
|
|
/** |
|
233
|
|
|
* @param string $name |
|
234
|
|
|
* @return array|null |
|
235
|
|
|
*/ |
|
236
|
84 |
|
protected static function getCasesMan($name) |
|
237
|
|
|
{ |
|
238
|
|
|
// special cases for Лев, Павел |
|
239
|
84 |
|
if (isset(self::$exceptions[$name])) { |
|
240
|
|
|
return self::$exceptions[$name]; |
|
241
|
84 |
|
} elseif (in_array(S::slice($name, -1), array_diff(self::$consonants, ['й', /*'Ч', 'Щ'*/]), true)) { // hard consonant |
|
242
|
24 |
|
if (in_array(S::slice($name, -2), ['ек', 'ёк'], true)) { // Витек, Санек |
|
243
|
|
|
// case for foreign names like Салмонбек |
|
244
|
6 |
|
if (self::isConsonant(S::slice($name, -4, -3))) |
|
245
|
2 |
|
$prefix = S::name(S::slice($name, 0, -2)).'ек'; |
|
246
|
|
|
else |
|
247
|
6 |
|
$prefix = S::name(S::slice($name, 0, -2)).'ьк'; |
|
248
|
|
|
} else { |
|
249
|
18 |
|
if ($name === 'пётр') |
|
250
|
|
|
$prefix = S::name(str_replace('ё', 'е', $name)); |
|
251
|
|
|
else |
|
252
|
18 |
|
$prefix = S::name($name); |
|
253
|
|
|
} |
|
254
|
|
|
return [ |
|
255
|
24 |
|
self::IMENIT => S::name($name), |
|
256
|
24 |
|
self::RODIT => $prefix.'а', |
|
257
|
24 |
|
self::DAT => $prefix.'у', |
|
258
|
24 |
|
self::VINIT => $prefix.'а', |
|
259
|
24 |
|
self::TVORIT => RussianLanguage::isHissingConsonant(S::slice($name, -1)) || S::slice($name, -1) == 'ц' ? $prefix.'ем' : $prefix.'ом', |
|
260
|
24 |
|
self::PREDLOJ => $prefix.'е', |
|
261
|
|
|
]; |
|
262
|
60 |
View Code Duplication |
} elseif (S::slice($name, -1) == 'ь' && self::isConsonant(S::slice($name, -2, -1))) { // soft consonant |
|
|
|
|
|
|
263
|
10 |
|
$prefix = S::name(S::slice($name, 0, -1)); |
|
264
|
|
|
return [ |
|
265
|
10 |
|
self::IMENIT => $prefix.'ь', |
|
266
|
10 |
|
self::RODIT => $prefix.'я', |
|
267
|
10 |
|
self::DAT => $prefix.'ю', |
|
268
|
10 |
|
self::VINIT => $prefix.'я', |
|
269
|
10 |
|
self::TVORIT => $prefix.'ем', |
|
270
|
10 |
|
self::PREDLOJ => $prefix.'е', |
|
271
|
|
|
]; |
|
272
|
50 |
|
} elseif (in_array(S::slice($name, -2), ['ай', 'ей', 'ой', 'уй', 'яй', 'юй', 'ий'], true)) { |
|
273
|
24 |
|
$prefix = S::name(S::slice($name, 0, -1)); |
|
274
|
24 |
|
$postfix = S::slice($name, -2) == 'ий' ? 'и' : 'е'; |
|
275
|
|
|
return [ |
|
276
|
24 |
|
self::IMENIT => $prefix.'й', |
|
277
|
24 |
|
self::RODIT => $prefix.'я', |
|
278
|
24 |
|
self::DAT => $prefix.'ю', |
|
279
|
24 |
|
self::VINIT => $prefix.'я', |
|
280
|
24 |
|
self::TVORIT => $prefix.'ем', |
|
281
|
24 |
|
self::PREDLOJ => $prefix.$postfix, |
|
282
|
|
|
]; |
|
283
|
26 |
|
} elseif (S::slice($name, -1) == 'а' && self::isConsonant($before = S::slice($name, -2, -1)) && !in_array($before, [/*'г', 'к', 'х', */'ц'], true)) { |
|
284
|
22 |
|
$prefix = S::name(S::slice($name, 0, -1)); |
|
285
|
22 |
|
$postfix = (RussianLanguage::isHissingConsonant($before) || in_array($before, ['г', 'к', 'х'], true)) ? 'и' : 'ы'; |
|
286
|
|
|
return [ |
|
287
|
22 |
|
self::IMENIT => $prefix.'а', |
|
288
|
22 |
|
self::RODIT => $prefix.$postfix, |
|
289
|
22 |
|
self::DAT => $prefix.'е', |
|
290
|
22 |
|
self::VINIT => $prefix.'у', |
|
291
|
22 |
|
self::TVORIT => $prefix.($before === 'ш' ? 'е' : 'о').'й', |
|
292
|
22 |
|
self::PREDLOJ => $prefix.'е', |
|
293
|
|
|
]; |
|
294
|
4 |
|
} elseif (S::slice($name, -2) == 'ло' || S::slice($name, -2) == 'ко') { |
|
295
|
4 |
|
$prefix = S::name(S::slice($name, 0, -1)); |
|
296
|
4 |
|
$postfix = S::slice($name, -2, -1) == 'к' ? 'и' : 'ы'; |
|
297
|
|
|
return [ |
|
298
|
4 |
|
self::IMENIT => $prefix.'о', |
|
299
|
4 |
|
self::RODIT => $prefix.$postfix, |
|
300
|
4 |
|
self::DAT => $prefix.'е', |
|
301
|
4 |
|
self::VINIT => $prefix.'у', |
|
302
|
4 |
|
self::TVORIT => $prefix.'ой', |
|
303
|
4 |
|
self::PREDLOJ => $prefix.'е', |
|
304
|
|
|
]; |
|
305
|
|
|
} |
|
306
|
|
|
|
|
307
|
|
|
return null; |
|
308
|
|
|
} |
|
309
|
|
|
|
|
310
|
|
|
/** |
|
311
|
|
|
* @param string $name |
|
312
|
|
|
* @return array|null |
|
313
|
|
|
*/ |
|
314
|
26 |
|
protected static function getCasesWoman($name) |
|
315
|
|
|
{ |
|
316
|
26 |
|
if (S::slice($name, -1) == 'а' && !self::isVowel($before = (S::slice($name, -2, -1)))) { |
|
317
|
17 |
|
$prefix = S::name(S::slice($name, 0, -1)); |
|
318
|
17 |
|
if ($before != 'ц') { |
|
319
|
14 |
|
$postfix = (RussianLanguage::isHissingConsonant($before) || in_array($before, ['г', 'к', 'х'], true)) ? 'и' : 'ы'; |
|
320
|
|
|
return [ |
|
321
|
14 |
|
self::IMENIT => $prefix.'а', |
|
322
|
14 |
|
self::RODIT => $prefix.$postfix, |
|
323
|
14 |
|
self::DAT => $prefix.'е', |
|
324
|
14 |
|
self::VINIT => $prefix.'у', |
|
325
|
14 |
|
self::TVORIT => $prefix.'ой', |
|
326
|
14 |
|
self::PREDLOJ => $prefix.'е', |
|
327
|
|
|
]; |
|
328
|
|
View Code Duplication |
} else { |
|
|
|
|
|
|
329
|
|
|
return [ |
|
330
|
3 |
|
self::IMENIT => $prefix.'а', |
|
331
|
3 |
|
self::RODIT => $prefix.'ы', |
|
332
|
3 |
|
self::DAT => $prefix.'е', |
|
333
|
3 |
|
self::VINIT => $prefix.'у', |
|
334
|
3 |
|
self::TVORIT => $prefix.'ей', |
|
335
|
3 |
|
self::PREDLOJ => $prefix.'е', |
|
336
|
|
|
]; |
|
337
|
|
|
} |
|
338
|
9 |
View Code Duplication |
} elseif (S::slice($name, -1) == 'ь' && self::isConsonant(S::slice($name, -2, -1))) { |
|
|
|
|
|
|
339
|
4 |
|
$prefix = S::name(S::slice($name, 0, -1)); |
|
340
|
|
|
return [ |
|
341
|
4 |
|
self::IMENIT => $prefix.'ь', |
|
342
|
4 |
|
self::RODIT => $prefix.'и', |
|
343
|
4 |
|
self::DAT => $prefix.'и', |
|
344
|
4 |
|
self::VINIT => $prefix.'ь', |
|
345
|
4 |
|
self::TVORIT => $prefix.'ью', |
|
346
|
4 |
|
self::PREDLOJ => $prefix.'и', |
|
347
|
|
|
]; |
|
348
|
5 |
|
} elseif (RussianLanguage::isHissingConsonant(S::slice($name, -1))) { |
|
349
|
5 |
|
$prefix = S::name($name); |
|
350
|
|
|
return [ |
|
351
|
5 |
|
self::IMENIT => $prefix, |
|
352
|
5 |
|
self::RODIT => $prefix.'и', |
|
353
|
5 |
|
self::DAT => $prefix.'и', |
|
354
|
5 |
|
self::VINIT => $prefix, |
|
355
|
5 |
|
self::TVORIT => $prefix.'ью', |
|
356
|
5 |
|
self::PREDLOJ => $prefix.'и', |
|
357
|
|
|
]; |
|
358
|
|
|
} |
|
359
|
|
|
return null; |
|
360
|
|
|
} |
|
361
|
|
|
|
|
362
|
|
|
/** |
|
363
|
|
|
* @param string $name |
|
364
|
|
|
* @param string $case |
|
365
|
|
|
* @param null|string $gender |
|
366
|
|
|
* @return string |
|
367
|
|
|
* @throws \Exception |
|
368
|
|
|
*/ |
|
369
|
52 |
|
public static function getCase($name, $case, $gender = null) |
|
370
|
|
|
{ |
|
371
|
52 |
|
$case = self::canonizeCase($case); |
|
372
|
52 |
|
$forms = self::getCases($name, $gender); |
|
373
|
52 |
|
return $forms[$case]; |
|
374
|
|
|
} |
|
375
|
|
|
} |
|
376
|
|
|
|
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:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.