1
|
|
|
<?php |
2
|
|
|
namespace morphos\Russian; |
3
|
|
|
|
4
|
|
|
use morphos\S; |
5
|
|
|
|
6
|
|
|
/** |
7
|
|
|
* Rules are from http://gramma.ru/SPR/?id=2.8 |
8
|
|
|
*/ |
9
|
|
|
class LastNamesInflection extends \morphos\NamesInflection implements Cases |
10
|
|
|
{ |
11
|
|
|
use RussianLanguage, CasesHelper; |
12
|
|
|
|
13
|
|
|
protected static $menPostfixes = array('ов', 'ев' ,'ин' ,'ын', 'ой', 'ий'); |
14
|
|
|
protected static $womenPostfixes = array('ва', 'на', 'ая', 'яя'); |
15
|
|
|
|
16
|
|
|
public static function isMutable($name, $gender = null) |
17
|
|
|
{ |
18
|
|
|
$name = S::lower($name); |
19
|
|
|
if ($gender === null) { |
20
|
|
|
$gender = self::detectGender($name); |
21
|
|
|
} |
22
|
|
|
|
23
|
|
View Code Duplication |
if (in_array(S::slice($name, -1), array('а', 'я'))) { |
|
|
|
|
24
|
|
|
return true; |
25
|
|
|
} |
26
|
|
|
|
27
|
|
|
if ($gender == self::MALE) { |
28
|
|
|
if (in_array(S::slice($name, -2), array('ов', 'ев', 'ин', 'ын', 'ий', 'ой'))) { |
29
|
|
|
return true; |
30
|
|
|
} |
31
|
|
|
if (self::isConsonant(S::slice($name, -1))) { |
32
|
|
|
return true; |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
if (S::slice($name, -1) == 'ь') { |
36
|
|
|
return true; |
37
|
|
|
} |
38
|
|
|
} else { |
39
|
|
View Code Duplication |
if (in_array(S::slice($name, -2), array('ва', 'на')) || in_array(S::slice($name, -4), array('ская'))) { |
|
|
|
|
40
|
|
|
return true; |
41
|
|
|
} |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
return false; |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
public static function detectGender($name) |
48
|
|
|
{ |
49
|
|
|
$name = S::lower($name); |
50
|
|
|
if (in_array(S::slice($name, -2), self::$menPostfixes)) { |
51
|
|
|
return self::MALE; |
52
|
|
|
} |
53
|
|
|
if (in_array(S::slice($name, -2), self::$womenPostfixes)) { |
54
|
|
|
return self::FEMALE; |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
return null; |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
public static function getCases($name, $gender = null) |
61
|
|
|
{ |
62
|
|
|
$name = S::lower($name); |
63
|
|
|
if ($gender === null) { |
64
|
|
|
$gender = self::detectGender($name); |
65
|
|
|
} |
66
|
|
|
if ($gender == self::MALE) { |
67
|
|
|
if (in_array(S::slice($name, -2), array('ов', 'ев', 'ин', 'ын'))) { |
68
|
|
|
$prefix = S::name($name); |
69
|
|
|
return array( |
70
|
|
|
self::IMENIT => $prefix, |
71
|
|
|
self::RODIT => $prefix.'а', |
72
|
|
|
self::DAT => $prefix.'у', |
73
|
|
|
self::VINIT => $prefix.'а', |
74
|
|
|
self::TVORIT => $prefix.'ым', |
75
|
|
|
self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е' |
76
|
|
|
); |
77
|
|
View Code Duplication |
} elseif (in_array(S::slice($name, -4), array('ский', 'ской', 'цкий', 'цкой'))) { |
|
|
|
|
78
|
|
|
$prefix = S::name(S::slice($name, 0, -2)); |
79
|
|
|
return array( |
80
|
|
|
self::IMENIT => S::name($name), |
81
|
|
|
self::RODIT => $prefix.'ого', |
82
|
|
|
self::DAT => $prefix.'ому', |
83
|
|
|
self::VINIT => $prefix.'ого', |
84
|
|
|
self::TVORIT => $prefix.'им', |
85
|
|
|
self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'ом' |
86
|
|
|
); |
87
|
|
|
} |
88
|
|
|
} else { |
89
|
|
View Code Duplication |
if (in_array(S::slice($name, -3), array('ова', 'ева', 'ина', 'ына'))) { |
|
|
|
|
90
|
|
|
$prefix = S::name(S::slice($name, 0, -1)); |
91
|
|
|
return array( |
92
|
|
|
self::IMENIT => S::name($name), |
93
|
|
|
self::RODIT => $prefix.'ой', |
94
|
|
|
self::DAT => $prefix.'ой', |
95
|
|
|
self::VINIT => $prefix.'у', |
96
|
|
|
self::TVORIT => $prefix.'ой', |
97
|
|
|
self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'ой' |
98
|
|
|
); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
if (in_array(S::slice($name, -2), array('ая'))) { |
102
|
|
|
$prefix = S::name(S::slice($name, 0, -2)); |
103
|
|
|
return array( |
104
|
|
|
self::IMENIT => S::name($name), |
105
|
|
|
self::RODIT => $prefix.'ой', |
106
|
|
|
self::DAT => $prefix.'ой', |
107
|
|
|
self::VINIT => $prefix.'ую', |
108
|
|
|
self::TVORIT => $prefix.'ой', |
109
|
|
|
self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'ой' |
110
|
|
|
); |
111
|
|
|
} |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
if (S::slice($name, -1) == 'я') { |
115
|
|
|
$prefix = S::name(S::slice($name, 0, -1)); |
116
|
|
|
return array( |
117
|
|
|
self::IMENIT => S::name($name), |
118
|
|
|
self::RODIT => $prefix.'и', |
119
|
|
|
self::DAT => $prefix.'е', |
120
|
|
|
self::VINIT => $prefix.'ю', |
121
|
|
|
self::TVORIT => $prefix.'ей', |
122
|
|
|
self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е' |
123
|
|
|
); |
124
|
|
View Code Duplication |
} elseif (S::slice($name, -1) == 'а') { |
|
|
|
|
125
|
|
|
$prefix = S::name(S::slice($name, 0, -1)); |
126
|
|
|
return array( |
127
|
|
|
self::IMENIT => S::name($name), |
128
|
|
|
self::RODIT => $prefix.(self::isDeafConsonant(S::slice($name, -2, -1)) ? 'и' : 'ы'), |
129
|
|
|
self::DAT => $prefix.'е', |
130
|
|
|
self::VINIT => $prefix.'у', |
131
|
|
|
self::TVORIT => $prefix.'ой', |
132
|
|
|
self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е' |
133
|
|
|
); |
134
|
|
|
} elseif (self::isConsonant(S::slice($name, -1)) && $gender == self::MALE) { |
135
|
|
|
$prefix = S::name($name); |
136
|
|
|
return array( |
137
|
|
|
self::IMENIT => S::name($name), |
138
|
|
|
self::RODIT => $prefix.'а', |
139
|
|
|
self::DAT => $prefix.'у', |
140
|
|
|
self::VINIT => $prefix.'а', |
141
|
|
|
self::TVORIT => $prefix.'ом', |
142
|
|
|
self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е' |
143
|
|
|
); |
144
|
|
|
} elseif (S::slice($name, -1) == 'ь' && $gender == self::MALE) { |
145
|
|
|
$prefix = S::name(S::slice($name, 0, -1)); |
146
|
|
|
return array( |
147
|
|
|
self::IMENIT => S::name($name), |
148
|
|
|
self::RODIT => $prefix.'я', |
149
|
|
|
self::DAT => $prefix.'ю', |
150
|
|
|
self::VINIT => $prefix.'я', |
151
|
|
|
self::TVORIT => $prefix.'ем', |
152
|
|
|
self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е' |
153
|
|
|
); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
$name = S::name($name); |
157
|
|
|
return array_fill_keys(array(self::IMENIT, self::RODIT, self::DAT, self::VINIT, self::TVORIT), $name) + array(self::PREDLOJ => self::choosePrepositionByFirstLetter($name, 'об', 'о').' '.$name); |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
public static function getCase($name, $case, $gender = null) |
161
|
|
|
{ |
162
|
|
|
$case = self::canonizeCase($case); |
163
|
|
|
$forms = self::getCases($name, $gender); |
164
|
|
|
return $forms[$case]; |
165
|
|
|
} |
166
|
|
|
} |
167
|
|
|
|
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.