Completed
Push — master ( fdb727...0387e6 )
by f
01:30
created

NounDeclension::getPrefixOfSecondDeclension()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 20

Duplication

Lines 6
Ratio 30 %

Code Coverage

Tests 11
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
nc 5
nop 2
dl 6
loc 20
ccs 11
cts 11
cp 1
crap 7
rs 8.6666
c 0
b 0
f 0
1
<?php
2
namespace morphos\Russian;
3
4
use morphos\BaseInflection;
5
use morphos\Gender;
6
use morphos\S;
7
8
/**
9
 * Rules are from http://morpher.ru/Russian/Noun.aspx
10
 */
11
class NounDeclension extends BaseInflection implements Cases, Gender
12
{
13
    use RussianLanguage, CasesHelper;
14
15
    const FIRST_DECLENSION = 1;
16
    const SECOND_DECLENSION = 2;
17
    const THIRD_DECLENSION = 3;
18
19
    public static $immutableWords = [
20
        // валюты
21
        'евро', 'пенни', 'песо', 'сентаво',
22
23
        // на а
24
        'боа', 'бра', 'фейхоа', 'амплуа', 'буржуа',
25
        // на о
26
        'манго', 'какао', 'кино', 'трюмо', 'пальто', 'бюро', 'танго', 'вето', 'бунгало', 'сабо', 'авокадо', 'депо',
27
        // на у
28
        'зебу', 'кенгуру', 'рагу', 'какаду', 'шоу',
29
        // на е
30
        'шимпанзе', 'конферансье', 'атташе', 'колье', 'резюме', 'пенсне', 'кашне', 'протеже', 'коммюнике', 'драже', 'суфле', 'пюре', 'купе', 'фойе', 'шоссе', 'крупье',
31
        // на и
32
        'такси', 'жалюзи', 'шасси', 'алиби', 'киви', 'иваси', 'регби', 'конфетти', 'колибри', 'жюри', 'пенальти', 'рефери', 'кольраби',
33
        // на э
34
        'каноэ', 'алоэ',
35
        // на ю
36
        'меню', 'парвеню', 'авеню', 'дежавю', 'инженю', 'барбекю', 'интервью',
37
    ];
38
39
    /**
40
     * These words has 2 declension type.
41
     */
42
    protected static $abnormalExceptions = [
43
        'бремя',
44
        'вымя',
45
        'темя',
46
        'пламя',
47
        'стремя',
48
        'пламя',
49
        'время',
50
        'знамя',
51
        'имя',
52
        'племя',
53
        'семя',
54
        'путь' => ['путь', 'пути', 'пути', 'путь', 'путем', 'пути'],
55
        'дитя' => ['дитя', 'дитяти', 'дитяти', 'дитя', 'дитятей', 'дитяти'],
56
    ];
57
58
    protected static $masculineWithSoft = [
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
    ];
90
91
    protected static $masculineWithSoftAndRunAwayVowels = [
92
        'день',
93
        'пень',
94
        'парень',
95
        'камень',
96
        'корень',
97
        'трутень',
98
    ];
99
100
    /**
101
     * Проверка, изменяемое ли слово.
102
     * @param string $word Слово для проверки
103
     * @param bool $animateness Признак одушевленности
104
     * @return bool
105
     */
106 43
    public static function isMutable($word, $animateness = false)
0 ignored issues
show
Unused Code introduced by
The parameter $animateness is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
107
    {
108 43
        $word = S::lower($word);
109 43
        if (in_array(S::slice($word, -1), ['у', 'и', 'е', 'о', 'ю'], true) || in_array($word, static::$immutableWords, true)) {
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 108 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...
110 43
            return false;
111
        }
112
        return true;
113
    }
114
115
    /**
116
     * Определение рода существительного.
117
     * @param string $word
118
     * @return string
119
     */
120 8
    public static function detectGender($word)
121
    {
122 8
    	$word = S::lower($word);
123 8
    	$last = S::slice($word, -1);
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 122 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...
124
		// пытаемся угадать род объекта, хотя бы примерно, чтобы правильно склонять
125 8
		if (S::slice($word, -2) == 'мя' || in_array($last, ['о', 'е', 'и', 'у'], true))
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 122 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...
126 2
			return static::NEUTER;
127
128 6
		if (in_array($last, ['а', 'я'], true) ||
129 6
			($last == 'ь' && !in_array($word, static::$masculineWithSoft, true) && !in_array($word, static::$masculineWithSoftAndRunAwayVowels, true)))
130 3
			return static::FEMALE;
131
132 3
		return static::MALE;
133
    }
134
135
    /**
136
     * Определение склонения (по школьной программе) существительного.
137
     * @param $word
138
     * @param bool $animateness
139
     * @return int
140
     */
141 183
    public static function getDeclension($word, $animateness = false)
0 ignored issues
show
Unused Code introduced by
The parameter $animateness is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
142
    {
143 183
        $word = S::lower($word);
144 183
        $last = S::slice($word, -1);
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 143 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...
145 183
        if (isset(static::$abnormalExceptions[$word]) || in_array($word, static::$abnormalExceptions, true)) {
146 3
            return 2;
147
        }
148
149 180
        if (in_array($last, ['а', 'я'], true) && S::slice($word, -2) != 'мя') {
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 143 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...
150 56
            return 1;
151 133
        } elseif (static::isConsonant($last) || in_array($last, ['о', 'е', 'ё'], true)
152 35
            || ($last == 'ь' && static::isConsonant(S::slice($word, -2, -1)) && !static::isHissingConsonant(S::slice($word, -2, -1))
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 143 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...
153 133
                && (in_array($word, static::$masculineWithSoft, true)) || in_array($word, static::$masculineWithSoftAndRunAwayVowels, true))) {
154 124
            return 2;
155
        } else {
156 9
            return 3;
157
        }
158
    }
159
160
    /**
161
     * Получение слова во всех 6 падежах.
162
     * @param string $word
163
     * @param bool $animateness Признак одушевлённости
164
     * @return array
165
     */
166 103
    public static function getCases($word, $animateness = false)
167
    {
168 103
        $word = S::lower($word);
169
170
        // Адъективное склонение (Сущ, образованные от прилагательных и причастий) - прохожий, существительное
171 103
        if (static::isAdjectiveNoun($word)) {
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 168 can also be of type boolean; however, morphos\Russian\RussianLanguage::isAdjectiveNoun() 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...
172 8
            return static::declinateAdjective($word, $animateness);
173
        }
174
175
        // Субстантивное склонение (существительные)
176 95
        if (in_array($word, static::$immutableWords, true)) {
177
            return [
178 3
                static::IMENIT => $word,
179 3
                static::RODIT => $word,
180 3
                static::DAT => $word,
181 3
                static::VINIT => $word,
182 3
                static::TVORIT => $word,
183 3
                static::PREDLOJ => $word,
184
            ];
185 92
        } elseif (isset(static::$abnormalExceptions[$word])) {
186 2
            return array_combine([static::IMENIT, static::RODIT, static::DAT, static::VINIT, static::TVORIT, static::PREDLOJ], static::$abnormalExceptions[$word]);
187 90
        } elseif (in_array($word, static::$abnormalExceptions, true)) {
188 1
            $prefix = S::slice($word, 0, -1);
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 168 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...
189
            return [
190 1
                static::IMENIT => $word,
191 1
                static::RODIT => $prefix.'ени',
192 1
                static::DAT => $prefix.'ени',
193 1
                static::VINIT => $word,
194 1
                static::TVORIT => $prefix.'енем',
195 1
                static::PREDLOJ => $prefix.'ени',
196
            ];
197
        }
198
199 89
        switch (static::getDeclension($word)) {
200 89
            case static::FIRST_DECLENSION:
201 25
                return static::declinateFirstDeclension($word);
202 66
            case static::SECOND_DECLENSION:
203 62
                return static::declinateSecondDeclension($word, $animateness);
204 4
            case static::THIRD_DECLENSION:
205 4
                return static::declinateThirdDeclension($word);
206
        }
207
    }
208
209
    /**
210
     * Получение всех форм слова первого склонения.
211
     * @param $word
212
     * @return array
213
     */
214 25
    public static function declinateFirstDeclension($word)
215
    {
216 25
        $word = S::lower($word);
217 25
        $prefix = S::slice($word, 0, -1);
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 216 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...
218 25
        $last = S::slice($word, -1);
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 216 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...
219 25
        $soft_last = static::checkLastConsonantSoftness($word);
220
        $forms =  [
221 25
            Cases::IMENIT => $word,
222
        ];
223
224
        // RODIT
225 25
        $forms[Cases::RODIT] = static::chooseVowelAfterConsonant($last, $soft_last || (in_array(S::slice($word, -2, -1), ['г', 'к', 'х'], true)), $prefix.'и', $prefix.'ы');
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 216 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...
226
227
        // DAT
228 25
        $forms[Cases::DAT] = static::getPredCaseOf12Declensions($word, $last, $prefix);
229
230
        // VINIT
231 25
        $forms[Cases::VINIT] = static::chooseVowelAfterConsonant($last, $soft_last && S::slice($word, -2, -1) !== 'ч', $prefix.'ю', $prefix.'у');
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 216 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...
232
233
        // TVORIT
234 25
        if ($last === 'ь') {
235
            $forms[Cases::TVORIT] = $prefix.'ой';
236 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...
237 25
            $forms[Cases::TVORIT] = static::chooseVowelAfterConsonant($last, $soft_last, $prefix.'ей', $prefix.'ой');
238
        }
239
240
        // 	if ($last == 'й' || (static::isConsonant($last) && !static::isHissingConsonant($last)) || static::checkLastConsonantSoftness($word))
241
        // 	$forms[Cases::TVORIT] = $prefix.'ей';
242
        // else
243
        // 	$forms[Cases::TVORIT] = $prefix.'ой'; # http://morpher.ru/Russian/Spelling.aspx#sibilant
244
245
        // PREDLOJ the same as DAT
246 25
        $forms[Cases::PREDLOJ] = $forms[Cases::DAT];
247 25
        return $forms;
248
    }
249
250
    /**
251
     * Получение всех форм слова второго склонения.
252
     * @param $word
253
     * @param bool $animateness
254
     * @return array
255
     */
256 62
    public static function declinateSecondDeclension($word, $animateness = false)
257
    {
258 62
        $word = S::lower($word);
259 62
        $last = S::slice($word, -1);
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 258 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...
260 62
        $soft_last = $last === 'й' || (in_array($last, ['ь', 'е', 'ё', 'ю', 'я'], true)
261
            && ((
262 23
                static::isConsonant(S::slice($word, -2, -1)) && !static::isHissingConsonant(S::slice($word, -2, -1)))
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 258 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...
263 62
                    || S::slice($word, -2, -1) === 'и'));
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 258 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...
264 62
        $prefix = static::getPrefixOfSecondDeclension($word, $last);
265
        $forms =  [
266 62
            Cases::IMENIT => $word,
267
        ];
268
269
        // RODIT
270 62
        $forms[Cases::RODIT] = static::chooseVowelAfterConsonant($last, $soft_last, $prefix.'я', $prefix.'а');
271
272
        // DAT
273 62
        $forms[Cases::DAT] = static::chooseVowelAfterConsonant($last, $soft_last, $prefix.'ю', $prefix.'у');
274
275
        // VINIT
276 62
        if (in_array($last, ['о', 'е', 'ё'], true)) {
277 13
            $forms[Cases::VINIT] = $word;
278
        } else {
279 49
            $forms[Cases::VINIT] = static::getVinitCaseByAnimateness($forms, $animateness);
280
        }
281
282
        // TVORIT
283
        // if ($last == 'ь')
284
        // 	$forms[Cases::TVORIT] = $prefix.'ом';
285
        // else if ($last == 'й' || (static::isConsonant($last) && !static::isHissingConsonant($last)))
286
        // 	$forms[Cases::TVORIT] = $prefix.'ем';
287
        // else
288
        // 	$forms[Cases::TVORIT] = $prefix.'ом'; # http://morpher.ru/Russian/Spelling.aspx#sibilant
289 62
        if (static::isHissingConsonant($last)
290 60
            || (in_array($last, ['ь', 'е', 'ё', 'ю', 'я'], true) && static::isHissingConsonant(S::slice($word, -2, -1)))
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 258 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...
291 62
            || ($last === 'ц' && S::slice($word, -2) !== 'ец')) {
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 258 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...
292 5
            $forms[Cases::TVORIT] = $prefix.'ем';
293 57 View Code Duplication
        } elseif (in_array($last, ['й'/*, 'ч', 'щ'*/], true) || $soft_last) {
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...
294 24
            $forms[Cases::TVORIT] = $prefix.'ем';
295
        } else {
296 33
            $forms[Cases::TVORIT] = $prefix.'ом';
297
        }
298
299
        // PREDLOJ
300 62
        $forms[Cases::PREDLOJ] = static::getPredCaseOf12Declensions($word, $last, $prefix);
301
302 62
        return $forms;
303
    }
304
305
    /**
306
     * Получение всех форм слова третьего склонения.
307
     * @param $word
308
     * @return array
309
     */
310 4
    public static function declinateThirdDeclension($word)
311
    {
312 4
        $word = S::lower($word);
313 4
        $prefix = S::slice($word, 0, -1);
0 ignored issues
show
Bug introduced by
It seems like $word defined by \morphos\S::lower($word) on line 312 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...
314
        return [
315 4
            Cases::IMENIT => $word,
316 4
            Cases::RODIT => $prefix.'и',
317 4
            Cases::DAT => $prefix.'и',
318 4
            Cases::VINIT => $word,
319 4
            Cases::TVORIT => $prefix.'ью',
320 4
            Cases::PREDLOJ => $prefix.'и',
321
        ];
322
    }
323
324
    /**
325
     * Склонение существительных, образованных от прилагательных и причастий.
326
     * Rules are from http://rusgram.narod.ru/1216-1231.html
327
     * @param $word
328
     * @param $animateness
329
     * @return array
330
     */
331 8
    public static function declinateAdjective($word, $animateness)
0 ignored issues
show
Unused Code introduced by
The parameter $animateness is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
332
    {
333 8
        $prefix = S::slice($word, 0, -2);
334
335 8
        switch (S::slice($word, -2)) {
336
            // Male adjectives
337 8
            case 'ой':
338 7 View Code Duplication
            case 'ый':
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...
339
                return [
340 2
                    Cases::IMENIT => $word,
341 2
                    Cases::RODIT => $prefix.'ого',
342 2
                    Cases::DAT => $prefix.'ому',
343 2
                    Cases::VINIT => $word,
344 2
                    Cases::TVORIT => $prefix.'ым',
345 2
                    Cases::PREDLOJ => $prefix.'ом',
346
                ];
347
348 6 View Code Duplication
            case 'ий':
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...
349
                return [
350 1
                    Cases::IMENIT => $word,
351 1
                    Cases::RODIT => $prefix.'его',
352 1
                    Cases::DAT => $prefix.'ему',
353 1
                    Cases::VINIT => $prefix.'его',
354 1
                    Cases::TVORIT => $prefix.'им',
355 1
                    Cases::PREDLOJ => $prefix.'ем',
356
                ];
357
358
            // Neuter adjectives
359 5
            case 'ое':
360 4 View Code Duplication
            case 'ее':
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...
361 2
                $prefix = S::slice($word, 0, -1);
362
                return [
363 2
                    Cases::IMENIT => $word,
364 2
                    Cases::RODIT => $prefix.'го',
365 2
                    Cases::DAT => $prefix.'му',
366 2
                    Cases::VINIT => $word,
367 2
                    Cases::TVORIT => S::slice($word, 0, -2).(S::slice($word, -2, -1) == 'о' ? 'ы' : 'и').'м',
368 2
                    Cases::PREDLOJ => $prefix.'м',
369
                ];
370
371
            // Female adjectives
372 3
            case 'ая':
373 3
                $ending = static::isHissingConsonant(S::slice($prefix, -1)) ? 'ей' : 'ой';
0 ignored issues
show
Security Bug introduced by
It seems like $prefix defined by \morphos\S::slice($word, 0, -2) on line 333 can also be of type false; however, morphos\S::slice() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
374
                return [
375 3
                    Cases::IMENIT => $word,
376 3
                    Cases::RODIT => $prefix.$ending,
377 3
                    Cases::DAT => $prefix.$ending,
378 3
                    Cases::VINIT => $prefix.'ую',
379 3
                    Cases::TVORIT => $prefix.$ending,
380 3
                    Cases::PREDLOJ => $prefix.$ending,
381
                ];
382
        }
383
    }
384
385
    /**
386
     * Получение одной формы слова (падежа).
387
     * @param string $word Слово
388
     * @param integer $case Падеж
389
     * @param bool $animateness Признак одушевленности
390
     * @return string
391
     * @throws \Exception
392
     */
393 40
    public static function getCase($word, $case, $animateness = false)
394
    {
395 40
        $case = static::canonizeCase($case);
396 40
        $forms = static::getCases($word, $animateness);
397 40
        return $forms[$case];
398
    }
399
400
    /**
401
     * @param $word
402
     * @param $last
403
     * @return bool
404
     */
405 92
    public static function getPrefixOfSecondDeclension($word, $last)
406
    {
407
        // слова с бегающей гласной в корне
408 92
        if (in_array($word, static::$masculineWithSoftAndRunAwayVowels, true)) {
409 7
            $prefix = S::slice($word, 0, -3).S::slice($word, -2, -1);
410 87
        } elseif (in_array($last, ['о', 'е', 'ё', 'ь', 'й'], true)) {
411 34
            $prefix = S::slice($word, 0, -1);
412
        }
413
        // уменьшительные формы слов (котенок) и слова с суффиксом ок
414 53 View Code Duplication
        elseif (S::slice($word, -2) === 'ок' && S::length($word) > 3) {
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...
415 4
            $prefix = S::slice($word, 0, -2) . 'к';
416
        }
417
        // слова с суффиксом бец
418 49 View Code Duplication
        elseif (S::slice($word, -3) === 'бец' && S::length($word) > 4) {
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...
419 1
            $prefix = S::slice($word, 0, -3).'бц';
420
        } else {
421 48
            $prefix = $word;
422
        }
423 92
        return $prefix;
424
    }
425
426
    /**
427
     * @param $word
428
     * @param $last
429
     * @param $prefix
430
     * @return string
431
     */
432 85
    public static function getPredCaseOf12Declensions($word, $last, $prefix)
433
    {
434 85
        if (in_array(S::slice($word, -2), ['ий', 'ие'], true)) {
435 6
            if ($last == 'ё') {
436
                return $prefix.'е';
437
            } else {
438 6
                return $prefix.'и';
439
            }
440
        } else {
441 79
            return $prefix.'е';
442
        }
443
    }
444
}
445