Completed
Push — master ( b5bb9d...38f7c0 )
by f
02:02
created

src/Russian/NounDeclension.php (17 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace morphos\Russian;
3
4
use morphos\Gender;
5
use morphos\S;
6
7
/**
8
 * Rules are from http://morpher.ru/Russian/Noun.aspx
9
 */
10
class NounDeclension extends \morphos\BaseInflection implements Cases, Gender
11
{
12
    use RussianLanguage, CasesHelper;
13
14
    const FIRST_DECLENSION = 1;
15
    const SECOND_DECLENSION = 2;
16
    const THIRD_DECLENSION = 3;
17
18
    /**
19
     * These words has 2 declension type.
20
     */
21
    protected static $abnormalExceptions = [
22
        'бремя',
23
        'вымя',
24
        'темя',
25
        'пламя',
26
        'стремя',
27
        'пламя',
28
        'время',
29
        'знамя',
30
        'имя',
31
        'племя',
32
        'семя',
33
        'путь' => ['путь', 'пути', 'пути', 'путь', 'путем', 'пути'],
34
        'дитя' => ['дитя', 'дитяти', 'дитяти', 'дитя', 'дитятей', 'дитяти'],
35
    ];
36
37
    protected static $masculineWithSoft = [
38
        'олень',
39
        'конь',
40
        'ячмень',
41
        'путь',
42
        'зверь',
43
        'шкворень',
44
        'пельмень',
45
        'тюлень',
46
        'выхухоль',
47
        'табель',
48
        'рояль',
49
        'шампунь',
50
        'конь',
51
        'лось',
52
        'гвоздь',
53
        'медведь',
54
        'рубль',
55
        'дождь',
56
        'юань',
57
    ];
58
59
    protected static $masculineWithSoftAndRunAwayVowels = [
60
        'день',
61
        'пень',
62
        'парень',
63
        'камень',
64
        'корень',
65
        'трутень',
66
    ];
67
68
    protected static $immutableWords = [
69
        // валюты
70
        'евро', 'пенни', 'песо', 'сентаво',
71
72
        // на а
73
        'боа', 'бра', 'фейхоа', 'амплуа', 'буржуа',
74
        // на о
75
        'манго', 'какао', 'кино', 'трюмо', 'пальто', 'бюро', 'танго', 'вето', 'бунгало', 'сабо', 'авокадо', 'депо',
76
        // на у
77
        'зебу', 'кенгуру', 'рагу', 'какаду', 'шоу',
78
        // на е
79
        'шимпанзе', 'конферансье', 'атташе', 'колье', 'резюме', 'пенсне', 'кашне', 'протеже', 'коммюнике', 'драже', 'суфле', 'пюре', 'купе', 'фойе', 'шоссе',
80
        // на и
81
        'такси', 'жалюзи', 'шасси', 'алиби', 'киви', 'иваси', 'регби', 'конфетти', 'колибри', 'жюри', 'пенальти', 'рефери', 'кольраби',
82
        // на э
83
        'каноэ', 'алоэ',
84
        // на ю
85
        'меню', 'парвеню', 'авеню', 'дежавю', 'инженю', 'барбекю', 'интервью',
86
    ];
87
88
    /**
89
     * Проверка, изменяемое ли слово.
90
     * @param string $word Слово для проверки
91
     * @param bool $animateness Признак одушевленности
92
     * @return bool
93
     */
94 43
    public static function isMutable($word, $animateness = false)
95
    {
96 43
        $word = S::lower($word);
97 43
        if (in_array(S::slice($word, -1), ['у', 'и', 'е', 'о', 'ю'], true) || in_array($word, self::$immutableWords, true)) {
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 96 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...
98 43
            return false;
99
        }
100
        return true;
101
    }
102
103
    /**
104
     * Определение рода существительного.
105
     * @param string $word
106
     * @return string
107
     */
108 8
    public static function detectGender($word)
109
    {
110 8
    	$word = S::lower($word);
111 8
    	$last = S::slice($word, -1);
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 110 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...
112
		// пытаемся угадать род объекта, хотя бы примерно, чтобы правильно склонять
113 8
		if (S::slice($word, -2) == 'мя' || in_array($last, ['о', 'е', 'и', 'у'], true))
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 110 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...
114 2
			return self::NEUTER;
115
116 6
		if (in_array($last, ['а', 'я'], true) ||
117 6
			($last == 'ь' && !in_array($word, self::$masculineWithSoft, true) && !in_array($word, self::$masculineWithSoftAndRunAwayVowels, true)))
118 3
			return self::FEMALE;
119
120 3
		return self::MALE;
121
    }
122
123
    /**
124
     * Определение склонения (по школьной программе) существительного.
125
     * @param $word
126
     * @return int
127
     */
128 169
    public static function getDeclension($word)
129
    {
130 169
        $word = S::lower($word);
131 169
        $last = S::slice($word, -1);
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 130 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...
132 169
        if (isset(self::$abnormalExceptions[$word]) || in_array($word, self::$abnormalExceptions, true)) {
133 3
            return 2;
134
        }
135
136 166
        if (in_array($last, ['а', 'я'], true) && S::slice($word, -2) != 'мя') {
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 130 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...
137 56
            return 1;
138 119
        } elseif (self::isConsonant($last) || in_array($last, ['о', 'е', 'ё'], true)
139 27
            || ($last == 'ь' && self::isConsonant(S::slice($word, -2, -1)) && !self::isHissingConsonant(S::slice($word, -2, -1))
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 130 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...
140 119
                && (in_array($word, self::$masculineWithSoft, true)) || in_array($word, self::$masculineWithSoftAndRunAwayVowels, true))) {
141 110
            return 2;
142
        } else {
143 9
            return 3;
144
        }
145
    }
146
147
    /**
148
     * Получение слова во всех 6 падежах.
149
     * @param string $word
150
     * @param bool $animateness Признак одушевлённости
151
     * @return array
152
     */
153 96
    public static function getCases($word, $animateness = false)
154
    {
155 96
        $word = S::lower($word);
156
157
        // Адъективное склонение (Сущ, образованные от прилагательных и причастий) - прохожий, существительное
158 96
        if (self::isAdjectiveNoun($word)) {
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 155 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...
159 8
            return self::declinateAdjective($word, $animateness);
160
        }
161
162
        // Субстантивное склонение (существительные)
163 88
        if (in_array($word, self::$immutableWords, true)) {
164
            return [
165 3
                self::IMENIT => $word,
166 3
                self::RODIT => $word,
167 3
                self::DAT => $word,
168 3
                self::VINIT => $word,
169 3
                self::TVORIT => $word,
170 3
                self::PREDLOJ => $word,
171
            ];
172 85
        } elseif (isset(self::$abnormalExceptions[$word])) {
173 2
            return array_combine([self::IMENIT, self::RODIT, self::DAT, self::VINIT, self::TVORIT, self::PREDLOJ], self::$abnormalExceptions[$word]);
174 83
        } elseif (in_array($word, self::$abnormalExceptions, true)) {
175 1
            $prefix = S::slice($word, 0, -1);
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 155 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...
176
            return [
177 1
                self::IMENIT => $word,
178 1
                self::RODIT => $prefix.'ени',
179 1
                self::DAT => $prefix.'ени',
180 1
                self::VINIT => $word,
181 1
                self::TVORIT => $prefix.'енем',
182 1
                self::PREDLOJ => $prefix.'ени',
183
            ];
184
        }
185
186 82
        switch (self::getDeclension($word)) {
187 82
            case self::FIRST_DECLENSION:
188 25
                return self::declinateFirstDeclension($word);
189 59
            case self::SECOND_DECLENSION:
190 55
                return self::declinateSecondDeclension($word, $animateness);
191 4
            case self::THIRD_DECLENSION:
192 4
                return self::declinateThirdDeclension($word);
193
        }
194
    }
195
196
    /**
197
     * Получение всех форм слова первого склонения.
198
     * @param $word
199
     * @return array
200
     */
201 25
    public static function declinateFirstDeclension($word)
202
    {
203 25
        $word = S::lower($word);
204 25
        $prefix = S::slice($word, 0, -1);
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 203 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...
205 25
        $last = S::slice($word, -1);
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 203 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...
206 25
        $soft_last = self::checkLastConsonantSoftness($word);
207
        $forms =  [
208 25
            Cases::IMENIT => $word,
209
        ];
210
211
        // RODIT
212 25
        $forms[Cases::RODIT] = self::chooseVowelAfterConsonant($last, $soft_last || (in_array(S::slice($word, -2, -1), ['г', 'к', 'х'], true)), $prefix.'и', $prefix.'ы');
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 203 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...
213
214
        // DAT
215 25
        $forms[Cases::DAT] = self::getPredCaseOf12Declensions($word, $last, $prefix);
216
217
        // VINIT
218 25
        $forms[Cases::VINIT] = self::chooseVowelAfterConsonant($last, $soft_last && S::slice($word, -2, -1) != 'ч', $prefix.'ю', $prefix.'у');
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 203 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
220
        // TVORIT
221 25
        if ($last == 'ь') {
222
            $forms[Cases::TVORIT] = $prefix.'ой';
223 View Code Duplication
        } else {
224 25
            $forms[Cases::TVORIT] = self::chooseVowelAfterConsonant($last, $soft_last, $prefix.'ей', $prefix.'ой');
225
        }
226
227
        // 	if ($last == 'й' || (self::isConsonant($last) && !self::isHissingConsonant($last)) || self::checkLastConsonantSoftness($word))
228
        // 	$forms[Cases::TVORIT] = $prefix.'ей';
229
        // else
230
        // 	$forms[Cases::TVORIT] = $prefix.'ой'; # http://morpher.ru/Russian/Spelling.aspx#sibilant
231
232
        // PREDLOJ the same as DAT
233 25
        $forms[Cases::PREDLOJ] = $forms[Cases::DAT];
234 25
        return $forms;
235
    }
236
237
    /**
238
     * Получение всех форм слова второго склонения.
239
     * @param $word
240
     * @param bool $animateness
241
     * @return array
242
     */
243 55
    public static function declinateSecondDeclension($word, $animateness = false)
244
    {
245 55
        $word = S::lower($word);
246 55
        $last = S::slice($word, -1);
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 245 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...
247 55
        $soft_last = $last == 'й' || (in_array($last, ['ь', 'е', 'ё', 'ю', 'я'], true)
248
            && ((
249 19
                self::isConsonant(S::slice($word, -2, -1)) && !self::isHissingConsonant(S::slice($word, -2, -1)))
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 245 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...
250 55
                    || S::slice($word, -2, -1) == 'и'));
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 245 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...
251 55
        $prefix = self::getPrefixOfSecondDeclension($word, $last);
252
        $forms =  [
253 55
            Cases::IMENIT => $word,
254
        ];
255
256
        // RODIT
257 55
        $forms[Cases::RODIT] = self::chooseVowelAfterConsonant($last, $soft_last, $prefix.'я', $prefix.'а');
258
259
        // DAT
260 55
        $forms[Cases::DAT] = self::chooseVowelAfterConsonant($last, $soft_last, $prefix.'ю', $prefix.'у');
261
262
        // VINIT
263 55
        if (in_array($last, ['о', 'е', 'ё'], true)) {
264 12
            $forms[Cases::VINIT] = $word;
265
        } else {
266 43
            $forms[Cases::VINIT] = self::getVinitCaseByAnimateness($forms, $animateness);
267
        }
268
269
        // TVORIT
270
        // if ($last == 'ь')
271
        // 	$forms[Cases::TVORIT] = $prefix.'ом';
272
        // else if ($last == 'й' || (self::isConsonant($last) && !self::isHissingConsonant($last)))
273
        // 	$forms[Cases::TVORIT] = $prefix.'ем';
274
        // else
275
        // 	$forms[Cases::TVORIT] = $prefix.'ом'; # http://morpher.ru/Russian/Spelling.aspx#sibilant
276 55
        if (self::isHissingConsonant($last) || (in_array($last, ['ь', 'е', 'ё', 'ю', 'я'], true) && self::isHissingConsonant(S::slice($word, -2, -1))) || $last == 'ц') {
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 245 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...
277 5
            $forms[Cases::TVORIT] = $prefix.'ем';
278 50 View Code Duplication
        } elseif (in_array($last, ['й'/*, 'ч', 'щ'*/], true) || $soft_last) {
279 20
            $forms[Cases::TVORIT] = $prefix.'ем';
280
        } else {
281 30
            $forms[Cases::TVORIT] = $prefix.'ом';
282
        }
283
284
        // PREDLOJ
285 55
        $forms[Cases::PREDLOJ] = self::getPredCaseOf12Declensions($word, $last, $prefix);
286
287 55
        return $forms;
288
    }
289
290
    /**
291
     * Получение всех форм слова третьего склонения.
292
     * @param $word
293
     * @return array
294
     */
295 4
    public static function declinateThirdDeclension($word)
296
    {
297 4
        $word = S::lower($word);
298 4
        $prefix = S::slice($word, 0, -1);
0 ignored issues
show
It seems like $word defined by \morphos\S::lower($word) on line 297 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...
299
        return [
300 4
            Cases::IMENIT => $word,
301 4
            Cases::RODIT => $prefix.'и',
302 4
            Cases::DAT => $prefix.'и',
303 4
            Cases::VINIT => $word,
304 4
            Cases::TVORIT => $prefix.'ью',
305 4
            Cases::PREDLOJ => $prefix.'и',
306
        ];
307
    }
308
309
    /**
310
     * Склонение существительных, образованных от прилагательных и причастий.
311
     * Rules are from http://rusgram.narod.ru/1216-1231.html
312
     * @param $word
313
     * @param $animateness
314
     * @return array
315
     */
316 8
    public static function declinateAdjective($word, $animateness)
317
    {
318 8
        $prefix = S::slice($word, 0, -2);
319
320 8
        switch (S::slice($word, -2)) {
321
            // Male adjectives
322 8
            case 'ой':
323 7 View Code Duplication
            case 'ый':
324
                return [
325 2
                    Cases::IMENIT => $word,
326 2
                    Cases::RODIT => $prefix.'ого',
327 2
                    Cases::DAT => $prefix.'ому',
328 2
                    Cases::VINIT => $word,
329 2
                    Cases::TVORIT => $prefix.'ым',
330 2
                    Cases::PREDLOJ => $prefix.'ом',
331
                ];
332
333 6 View Code Duplication
            case 'ий':
334
                return [
335 1
                    Cases::IMENIT => $word,
336 1
                    Cases::RODIT => $prefix.'его',
337 1
                    Cases::DAT => $prefix.'ему',
338 1
                    Cases::VINIT => $prefix.'его',
339 1
                    Cases::TVORIT => $prefix.'им',
340 1
                    Cases::PREDLOJ => $prefix.'ем',
341
                ];
342
343
            // Neuter adjectives
344 5
            case 'ое':
345 4 View Code Duplication
            case 'ее':
346 2
                $prefix = S::slice($word, 0, -1);
347
                return [
348 2
                    Cases::IMENIT => $word,
349 2
                    Cases::RODIT => $prefix.'го',
350 2
                    Cases::DAT => $prefix.'му',
351 2
                    Cases::VINIT => $word,
352 2
                    Cases::TVORIT => S::slice($word, 0, -2).(S::slice($word, -2, -1) == 'о' ? 'ы' : 'и').'м',
353 2
                    Cases::PREDLOJ => $prefix.'м',
354
                ];
355
356
            // Female adjectives
357 3
            case 'ая':
358 3
                $ending = self::isHissingConsonant(S::slice($prefix, -1)) ? 'ей' : 'ой';
359
                return [
360 3
                    Cases::IMENIT => $word,
361 3
                    Cases::RODIT => $prefix.$ending,
362 3
                    Cases::DAT => $prefix.$ending,
363 3
                    Cases::VINIT => $prefix.'ую',
364 3
                    Cases::TVORIT => $prefix.$ending,
365 3
                    Cases::PREDLOJ => $prefix.$ending,
366
                ];
367
        }
368
    }
369
370
    /**
371
     * Получение одной формы слова (падежа).
372
     * @param string $word Слово
373
     * @param integer $case Падеж
374
     * @param bool $animateness Признак одушевленности
375
     * @return string
376
     * @throws \Exception
377
     */
378 37
    public static function getCase($word, $case, $animateness = false)
379
    {
380 37
        $case = self::canonizeCase($case);
381 37
        $forms = self::getCases($word, $animateness);
382 37
        return $forms[$case];
383
    }
384
385
    /**
386
     * @param $word
387
     * @param $last
388
     * @return bool
389
     */
390 82
    public static function getPrefixOfSecondDeclension($word, $last)
391
    {
392
        // слова с бегающей гласной в корне
393 82
        if (in_array($word, self::$masculineWithSoftAndRunAwayVowels, true)) {
394 7
            $prefix = S::slice($word, 0, -3).S::slice($word, -2, -1);
395 77
        } elseif (in_array($last, ['о', 'е', 'ё', 'ь', 'й'], true)) {
396 29
            $prefix = S::slice($word, 0, -1);
397
        }
398
        // уменьшительные формы слов (котенок) и слова с суффиксом ок
399 48
        elseif (S::slice($word, -2) == 'ок' && S::length($word) > 3) {
400 4
            $prefix = S::slice($word, 0, -2).'к';
401
        } else {
402 44
            $prefix = $word;
403
        }
404 82
        return $prefix;
405
    }
406
407
    /**
408
     * @param array $forms
409
     * @param $animate
410
     * @return mixed
411
     */
412 101
    public static function getVinitCaseByAnimateness(array $forms, $animate)
413
    {
414 101
        if ($animate) {
415 6
            return $forms[Cases::RODIT];
416
        } else {
417 95
            return $forms[Cases::IMENIT];
418
        }
419
    }
420
421
    /**
422
     * @param $word
423
     * @param $last
424
     * @param $prefix
425
     * @return string
426
     */
427 78
    public static function getPredCaseOf12Declensions($word, $last, $prefix)
428
    {
429 78
        if (in_array(S::slice($word, -2), ['ий', 'ие'], true)) {
430 5
            if ($last == 'ё') {
431
                return $prefix.'е';
432
            } else {
433 5
                return $prefix.'и';
434
            }
435
        } else {
436 73
            return $prefix.'е';
437
        }
438
    }
439
}
440