Completed
Push — master ( fdfd1e...8db8fb )
by f
01:38
created

GeographicalNamesInflection   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 232
Duplicated Lines 15.09 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 35
loc 232
rs 8.8
c 0
b 0
f 0
wmc 36
lcom 1
cbo 4

3 Methods

Rating   Name   Duplication   Size   Complexity  
A isMutable() 0 15 4
D getCases() 35 197 31
A getCase() 0 6 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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
    protected static $abbreviations = array(
14
        'сша',
15
        'оаэ',
16
        'ссср',
17
        'юар',
18
    );
19
20
    public static function isMutable($name)
21
    {
22
        $name = S::lower($name);
23
        // // ends with 'ы' or 'и': plural form
24
        // if (in_array(S::slice($name, -1), array('и', 'ы')))
25
        //     return false;
26
        if (in_array($name, self::$abbreviations)) {
27
            return false;
28
        }
29
        // ends with 'е' or 'о', but not with 'ово/ёво/ево/ино/ыно'
30
        if (in_array(S::slice($name, -1), array('е', 'о')) && !in_array(S::slice($name, -3, -1), array('ов', 'ёв', 'ев', 'ин', 'ын'))) {
31
            return false;
32
        }
33
        return true;
34
    }
35
36
    public static function getCases($name)
37
    {
38
        $name = S::lower($name);
39
40
        // check for name of two words
41
        if (strpos($name, ' ') !== false) {
42
            $parts = explode(' ', $name);
43
            $cases = array();
0 ignored issues
show
Unused Code introduced by
$cases is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
44
            $result = array();
45
            foreach ($parts as $i => $part) {
46
                $result[$i] = static::getCases($part);
47
                if ($i > 0) {
48
                    $result[$i][self::PREDLOJ] = substr(strstr($result[$i][self::PREDLOJ], ' '), 1);
49
                }
50
            }
51
52
            $cases = array();
53
            foreach (array(self::IMENIT, self::RODIT, self::DAT, self::VINIT, self::TVORIT, self::PREDLOJ) as $case) {
54
                foreach ($parts as $i => $part) {
55
                    $cases[$case][] = $result[$i][$case];
56
                }
57
                $cases[$case] = implode(' ', $cases[$case]);
58
            }
59
            return $cases;
60
        }
61
62
        if (!in_array($name, self::$abbreviations)) {
63
            if (S::slice($name, -2) == 'ий') {
64
                // Нижний, Русский
65
                $prefix = S::name(S::slice($name, 0, -2));
66
                return array(
67
                    self::IMENIT => $prefix.'ий',
68
                    self::RODIT => $prefix.(self::isVelarConsonant(S::slice($name, -3, -2)) ? 'ого' : 'его'),
69
                    self::DAT => $prefix.(self::isVelarConsonant(S::slice($name, -3, -2)) ? 'ому' : 'ему'),
70
                    self::VINIT => $prefix.'ий',
71
                    self::TVORIT => $prefix.'им',
72
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'ем',
73
                );
74
            } else if (S::slice($name, -2) == 'ый') {
75
                // Грозный, Благодарный
76
                $prefix = S::name(S::slice($name, 0, -2));
77
                return array(
78
                    self::IMENIT => $prefix.'ый',
79
                    self::RODIT => $prefix.'ого',
80
                    self::DAT => $prefix.'ому',
81
                    self::VINIT => $prefix.'ый',
82
                    self::TVORIT => $prefix.'ым',
83
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'ом',
84
                );
85
            } elseif (S::slice($name, -1) == 'а') {
86
                // Москва, Рига
87
                $prefix = S::name(S::slice($name, 0, -1));
88
                return array(
89
                    self::IMENIT => $prefix.'а',
90
                    self::RODIT => $prefix.(self::isVelarConsonant(S::slice($name, -2, -1)) ? 'и' : 'ы'),
91
                    self::DAT => $prefix.'е',
92
                    self::VINIT => $prefix.'у',
93
                    self::TVORIT => $prefix.'ой',
94
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е',
95
                );
96
            } elseif (S::slice($name, -1) == 'я') {
97
                // Азия
98
                $prefix = S::name(S::slice($name, 0, -1));
99
                return array(
100
                    self::IMENIT => S::name($name),
101
                    self::RODIT => $prefix.'и',
102
                    self::DAT => $prefix.'и',
103
                    self::VINIT => $prefix.'ю',
104
                    self::TVORIT => $prefix.'ей',
105
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'и',
106
                );
107
            } elseif (S::slice($name, -1) == 'й') {
108
                // Ишимбай
109
                $prefix = S::name(S::slice($name, 0, -1));
110
                return array(
111
                    self::IMENIT => $prefix.'й',
112
                    self::RODIT => $prefix.'я',
113
                    self::DAT => $prefix.'ю',
114
                    self::VINIT => $prefix.'й',
115
                    self::TVORIT => $prefix.'ем',
116
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е',
117
                );
118 View Code Duplication
            } elseif (self::isConsonant(S::slice($name, -1)) && S::slice($name, -2) != 'ов') {
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...
119
                // Париж, Валаам, Киев
120
                $prefix = S::name($name);
121
                return array(
122
                    self::IMENIT => $prefix,
123
                    self::RODIT => $prefix.'а',
124
                    self::DAT => $prefix.'у',
125
                    self::VINIT => $prefix,
126
                    self::TVORIT => $prefix.(self::isVelarConsonant(S::slice($name, -2, -1)) ? 'ем' : 'ом'),
127
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е',
128
                );
129
            } elseif (S::slice($name, -2) == 'ль') {
130
                // Ставрополь, Ярославль
131
                $prefix = S::name(S::slice($name, 0, -1));
132
                return array(
133
                    self::IMENIT => $prefix.'ь',
134
                    self::RODIT => $prefix.'я',
135
                    self::DAT => $prefix.'ю',
136
                    self::VINIT => $prefix.'ь',
137
                    self::TVORIT => $prefix.'ем',
138
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е',
139
                );
140
            } elseif (S::slice($name, -2) == 'рь') {
141
                // Тверь
142
                $prefix = S::name(S::slice($name, 0, -1));
143
                return array(
144
                    self::IMENIT => $prefix.'ь',
145
                    self::RODIT => $prefix.'и',
146
                    self::DAT => $prefix.'и',
147
                    self::VINIT => $prefix.'ь',
148
                    self::TVORIT => $prefix.'ью',
149
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'и',
150
                );
151
            } elseif (S::slice($name, -2) == 'ки') {
152
                // Березники, Ессентуки
153
                $prefix = S::name(S::slice($name, 0, -1));
154
                return array(
155
                    self::IMENIT => $prefix.'и',
156
                    self::RODIT => $prefix.'ов',
157
                    self::DAT => $prefix.'ам',
158
                    self::VINIT => $prefix.'и',
159
                    self::TVORIT => $prefix.'ами',
160
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'ах',
161
                );
162
            } elseif (S::slice($name, -2) == 'мь') {
163
                // Пермь, Кемь
164
                $prefix = S::name(S::slice($name, 0, -1));
165
                return array(
166
                    self::IMENIT => $prefix.'ь',
167
                    self::RODIT => $prefix.'и',
168
                    self::DAT => $prefix.'и',
169
                    self::VINIT => $prefix.'ь',
170
                    self::TVORIT => $prefix.'ью',
171
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'и',
172
                );
173
            } elseif (S::slice($name, -2) == 'нь') {
174
                // Рязань, Назрань
175
                $prefix = S::name(S::slice($name, 0, -1));
176
                return array(
177
                    self::IMENIT => $prefix.'ь',
178
                    self::RODIT => $prefix.'и',
179
                    self::DAT => $prefix.'и',
180
                    self::VINIT => $prefix.'ь',
181
                    self::TVORIT => $prefix.'ью',
182
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'и',
183
                );
184 View Code Duplication
            } else if (S::slice($name, -2) == 'ые') {
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...
185
                // Набережные
186
                $prefix = S::name(S::slice($name, 0, -1));
187
                return array(
188
                    self::IMENIT => $prefix.'е',
189
                    self::RODIT => $prefix.'х',
190
                    self::DAT => $prefix.'м',
191
                    self::VINIT => $prefix.'е',
192
                    self::TVORIT => $prefix.'ми',
193
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'х',
194
                );
195
            } else if (S::slice($name, -2) == 'ны') {
196
                // Челны
197
                $prefix = S::name(S::slice($name, 0, -1));
198
                return array(
199
                    self::IMENIT => $prefix.'ы',
200
                    self::RODIT => $prefix.'ов',
201
                    self::DAT => $prefix.'ам',
202
                    self::VINIT => $prefix.'ы',
203
                    self::TVORIT => $prefix.'ами',
204
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'ах',
205
                );
206
            }
207
208
            $suffixes = array('ов', 'ёв', 'ев', 'ин', 'ын');
209
            if ((in_array(S::slice($name, -1), array('е', 'о')) && in_array(S::slice($name, -3, -1), $suffixes)) || in_array(S::slice($name, -2), $suffixes)) {
210
                // ово, ёво, ...
211
                if (in_array(S::slice($name, -3, -1), $suffixes)) {
212
                    $prefix = S::name(S::slice($name, 0, -1));
213
                }
214
                // ов, её, ...
215
                elseif (in_array(S::slice($name, -2), $suffixes)) {
216
                    $prefix = S::name($name);
217
                }
218
                return array(
219
                    self::IMENIT => S::name($name),
220
                    self::RODIT => $prefix.'а',
221
                    self::DAT => $prefix.'у',
222
                    self::VINIT => S::name($name),
223
                    self::TVORIT => $prefix.'ым',
224
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'е',
225
                );
226
            }
227
        }
228
229
        // if no rules matches or name is immutable
230
        $name = in_array($name, self::$abbreviations) ? S::upper($name) : S::name($name);
231
        return array_fill_keys(array(self::IMENIT, self::RODIT, self::DAT, self::VINIT, self::TVORIT), $name) + array(self::PREDLOJ => self::choosePrepositionByFirstLetter($name, 'об', 'о').' '.$name);
232
    }
233
234
    public static function getCase($name, $case)
235
    {
236
        $case = self::canonizeCase($case);
237
        $forms = self::getCases($name);
238
        return $forms[$case];
239
    }
240
}
241