Completed
Push — master ( 073072...702dd1 )
by f
01:24
created

LastNamesInflection::detectGender()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 1
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
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
        if (strpos($name, '-') !== false) {
24
            foreach (explode('-', $name) as $part) {
25
                if (static::isMutable($part, $gender))
26
                    return true;
27
            }
28
            return false;
29
        }
30
31 View Code Duplication
        if (in_array(S::slice($name, -1), array('а', 'я'))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
32
            return true;
33
        }
34
35
        if ($gender == self::MALE) {
36
            // Несклоняемые фамилии (Фоминых, Седых / Стецко, Писаренко)
37
            if (in_array(S::slice($name, -2), ['ых', 'ко']))
38
                return false;
39
40
            // Несклоняемые, образованные из родительного падежа личного или прозвищного имени главы семьи
41
            // суффиксы: ово, аго
42
            if (in_array(S::slice($name, -3), ['ово', 'аго']))
43
                return false;
44
45
            // Типичные суффикс мужских фамилий
46
            if (in_array(S::slice($name, -2), array('ов', 'ев', 'ин', 'ын', 'ий', 'ой'))) {
47
                return true;
48
            }
49
50
            // Согласная на конце
51
            if (self::isConsonant(S::slice($name, -1))) {
52
                return true;
53
            }
54
55
            // Мягкий знак на конце
56
            if (S::slice($name, -1) == 'ь') {
57
                return true;
58
            }
59
60 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
61
            // Типичные суффиксы женских фамилий
62
            if (in_array(S::slice($name, -2), ['ва', 'на', 'ая'])) {
63
                return true;
64
            }
65
        }
66
67
        return false;
68
    }
69
70
    public static function detectGender($name)
71
    {
72
        $name = S::lower($name);
73
        if (in_array(S::slice($name, -2), self::$menPostfixes)) {
74
            return self::MALE;
75
        }
76
        if (in_array(S::slice($name, -2), self::$womenPostfixes)) {
77
            return self::FEMALE;
78
        }
79
80
        return null;
81
    }
82
83
    public static function getCases($name, $gender = null)
84
    {
85
        $name = S::lower($name);
86
        if ($gender === null) {
87
            $gender = self::detectGender($name);
88
        }
89
90
        // составная фамилия - разбить на части и склонять по отдельности
91
        if (strpos($name, '-') !== false) {
92
            $parts = explode('-', $name);
93
            $cases = [];
94
            foreach ($parts as $i => $part) {
95
                $part_cases = static::getCases($part, $gender);
96
                foreach ($part_cases as $case => $part_case) {
97
                    if ($case == self::PREDLOJ && $i > 0)
98
                        list(, $cases[$case][]) = explode(' ', $part_case);
99
                    else
100
                        $cases[$case][] = $part_case;
101
                }
102
            }
103
104
            foreach ($cases as $i => $case)
105
                $cases[$i] = implode('-', $case);
106
            return $cases;
107
        }
108
109
        if ($gender == self::MALE) {
110
            if (in_array(S::slice($name, -2), array('ов', 'ев', 'ин', 'ын'))) {
111
                $prefix = S::name($name);
112
                return array(
113
                    self::IMENIT => $prefix,
114
                    self::RODIT => $prefix.'а',
115
                    self::DAT => $prefix.'у',
116
                    self::VINIT => $prefix.'а',
117
                    self::TVORIT => $prefix.'ым',
118
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е'
119
                );
120 View Code Duplication
            } elseif (in_array(S::slice($name, -4), array('ский', 'ской', 'цкий', 'цкой'))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
121
                $prefix = S::name(S::slice($name, 0, -2));
122
                return array(
123
                    self::IMENIT => S::name($name),
124
                    self::RODIT => $prefix.'ого',
125
                    self::DAT => $prefix.'ому',
126
                    self::VINIT => $prefix.'ого',
127
                    self::TVORIT => $prefix.'им',
128
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'ом'
129
                );
130
            // Верхний / Убогий / Толстой
131
            // Верхнего / Убогого / Толстого
132
            // Верхнему / Убогому / Толстому
133
            // Верхним / Убогим / Толстым
134
            // О Верхнем / Об Убогом / О Толстом
135
            } else if (in_array(S::slice($name, -2), ['ой', 'ый', 'ий'])) {
136
                $prefix = S::name(S::slice($name, 0, -2));
137
                return array(
138
                    self::IMENIT => S::name($name),
139
                    self::RODIT => $prefix.'ого',
140
                    self::DAT => $prefix.'ому',
141
                    self::VINIT => $prefix.'ого',
142
                    self::TVORIT => $prefix.'ым',
143
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'ом'
144
                );
145
            }
146
147
        } else {
148 View Code Duplication
            if (in_array(S::slice($name, -3), array('ова', 'ева', 'ина', 'ына'))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
149
                $prefix = S::name(S::slice($name, 0, -1));
150
                return array(
151
                    self::IMENIT => S::name($name),
152
                    self::RODIT => $prefix.'ой',
153
                    self::DAT => $prefix.'ой',
154
                    self::VINIT => $prefix.'у',
155
                    self::TVORIT => $prefix.'ой',
156
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'ой'
157
                );
158
            }
159
160
            if (in_array(S::slice($name, -2), array('ая'))) {
161
                $prefix = S::name(S::slice($name, 0, -2));
162
                return array(
163
                    self::IMENIT => S::name($name),
164
                    self::RODIT => $prefix.'ой',
165
                    self::DAT => $prefix.'ой',
166
                    self::VINIT => $prefix.'ую',
167
                    self::TVORIT => $prefix.'ой',
168
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'ой'
169
                );
170
            }
171
        }
172
173
        if (S::slice($name, -1) == 'я') {
174
            $prefix = S::name(S::slice($name, 0, -1));
175
            return array(
176
                self::IMENIT => S::name($name),
177
                self::RODIT => $prefix.'и',
178
                self::DAT => $prefix.'е',
179
                self::VINIT => $prefix.'ю',
180
                self::TVORIT => $prefix.'ей',
181
                self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е'
182
            );
183 View Code Duplication
        } elseif (S::slice($name, -1) == 'а') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
184
            $prefix = S::name(S::slice($name, 0, -1));
185
            return array(
186
                self::IMENIT => S::name($name),
187
                self::RODIT => $prefix.(self::isDeafConsonant(S::slice($name, -2, -1)) ? 'и' : 'ы'),
188
                self::DAT => $prefix.'е',
189
                self::VINIT => $prefix.'у',
190
                self::TVORIT => $prefix.'ой',
191
                self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е'
192
            );
193
        } elseif (self::isConsonant(S::slice($name, -1)) && S::slice($name, -2) != 'ых') {
194
            $prefix = S::name($name);
195
            return array(
196
                self::IMENIT => S::name($name),
197
                self::RODIT => $prefix.'а',
198
                self::DAT => $prefix.'у',
199
                self::VINIT => $prefix.'а',
200
                self::TVORIT => $prefix.'ом',
201
                self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е'
202
            );
203
        } elseif (S::slice($name, -1) == 'ь' && $gender == self::MALE) {
204
            $prefix = S::name(S::slice($name, 0, -1));
205
            return array(
206
                self::IMENIT => S::name($name),
207
                self::RODIT => $prefix.'я',
208
                self::DAT => $prefix.'ю',
209
                self::VINIT => $prefix.'я',
210
                self::TVORIT => $prefix.'ем',
211
                self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е'
212
            );
213
        }
214
215
        $name = S::name($name);
216
        return array_fill_keys(array(self::IMENIT, self::RODIT, self::DAT, self::VINIT, self::TVORIT), $name) + array(self::PREDLOJ => self::choosePrepositionByFirstLetter($name, 'об', 'о').' '.$name);
217
    }
218
219
    public static function getCase($name, $case, $gender = null)
220
    {
221
        $case = self::canonizeCase($case);
222
        $forms = self::getCases($name, $gender);
223
        return $forms[$case];
224
    }
225
}
226