Completed
Push — master ( 18bbe5...4b1809 )
by f
01:51
created

RussianLanguage::checkBaseLastConsonantSoftness()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 15

Duplication

Lines 7
Ratio 46.67 %

Code Coverage

Tests 6
CRAP Score 6.6

Importance

Changes 0
Metric Value
cc 5
nc 4
nop 1
dl 7
loc 15
ccs 6
cts 10
cp 0.6
crap 6.6
rs 9.4555
c 0
b 0
f 0
1
<?php
2
namespace morphos\Russian;
3
4
use morphos\Gender;
5
use morphos\S;
6
7
trait RussianLanguage
8
{
9
    /**
10
     * @var array Все гласные
11
     */
12
    public static $vowels = [
13
        'а',
14
        'е',
15
        'ё',
16
        'и',
17
        'о',
18
        'у',
19
        'ы',
20
        'э',
21
        'ю',
22
        'я',
23
    ];
24
25
    /**
26
     * @var array Все согласные
27
     */
28
    public static $consonants = [
29
        'б',
30
        'в',
31
        'г',
32
        'д',
33
        'ж',
34
        'з',
35
        'й',
36
        'к',
37
        'л',
38
        'м',
39
        'н',
40
        'п',
41
        'р',
42
        'с',
43
        'т',
44
        'ф',
45
        'х',
46
        'ц',
47
        'ч',
48
        'ш',
49
        'щ',
50
    ];
51
52
    /**
53
     * @var array Пары согласных
54
     */
55
    public static $pairs = [
56
        'б' => 'п',
57
        'в' => 'ф',
58
        'г' => 'к',
59
        'д' => 'т',
60
        'ж' => 'ш',
61
        'з' => 'с',
62
    ];
63
64
    /**
65
     * @var array Звонкие согласные
66
     */
67
    public static $sonorousConsonants = ['б', 'в', 'г', 'д', 'з', 'ж', 'л', 'м', 'н', 'р'];
68
    /**
69
     * @var array Глухие согласные
70
     */
71
    public static $deafConsonants = ['п', 'ф', 'к', 'т', 'с', 'ш', 'х', 'ч', 'щ'];
72
73
    /**
74
     * Проверка гласной
75
     * @param $char
76
     * @return bool
77
     */
78 348
    public static function isVowel($char)
79
    {
80 348
        return in_array($char, static::$vowels, true);
81
    }
82
83
    /**
84
     * Проверка согласной
85
     * @param $char
86
     * @return bool
87
     */
88 208
    public static function isConsonant($char)
89
    {
90 208
        return in_array($char, static::$consonants, true);
91
    }
92
93
    /**
94
     * Проверка звонкости согласной
95
     */
96 3
    public static function isSonorousConsonant($char)
97
    {
98 3
        return in_array($char, static::$sonorousConsonants, true);
99
    }
100
101
    /**
102
     * Проверка глухости согласной
103
     * @param $char
104
     * @return bool
105
     */
106 6
    public static function isDeafConsonant($char)
107
    {
108 6
        return in_array($char, static::$deafConsonants, true);
109
    }
110
111
    /**
112
     * Щипящая ли согласная
113
     * @param $consonant
114
     * @return bool
115
     */
116 461
    public static function isHissingConsonant($consonant)
117
    {
118 461
        return in_array(S::lower($consonant), ['ж', 'ш', 'ч', 'щ'], true);
119
    }
120
121
    /**
122
     * Проверка на велярность согласной
123
     * @param string[1] $consonant
0 ignored issues
show
Documentation introduced by wapmorgan
The doc-type string[1] could not be parsed: Expected "]" at position 2, but found "1". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
124
     * @return bool
125
     */
126 15
    protected static function isVelarConsonant($consonant)
127
    {
128 15
        return in_array(S::lower($consonant), ['г', 'к', 'х'], true);
129
    }
130
131
    /**
132
     * Подсчет слогов
133
     * @param $string
134
     * @return bool|int
135
     */
136
    public static function countSyllables($string)
137
    {
138
        return S::countChars($string, static::$vowels);
139
    }
140
141
    /**
142
     * Проверка парности согласной
143
     *
144
     * @param $consonant
145
     * @return bool
146
     */
147
    public static function isPairedConsonant($consonant)
148
    {
149
        $consonant = S::lower($consonant);
150
        return array_key_exists($consonant, static::$pairs) || (array_search($consonant, static::$pairs) !== false);
151
    }
152
153
    /**
154
     * Проверка мягкости последней согласной
155
     * @param $word
156
     * @return bool
157
     */
158 46
    public static function checkLastConsonantSoftness($word)
159
    {
160 46 View Code Duplication
        if (($substring = S::findLastPositionForOneOfChars(S::lower($word), static::$consonants)) !== false) {
0 ignored issues
show
Duplication introduced by wapmorgan
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...
161 46
            if (in_array(S::slice($substring, 0, 1), ['й', 'ч', 'щ', 'ш'], true)) { // always soft consonants
162 14
                return true;
163 32
            } elseif (S::length($substring) > 1 && in_array(S::slice($substring, 1, 2), ['е', 'ё', 'и', 'ю', 'я', 'ь'], true)) { // consonants are soft if they are trailed with these vowels
164 3
                return true;
165
            }
166
        }
167 29
        return false;
168
    }
169
170
    /**
171
     * Проверка мягкости последней согласной, за исключением Н
172
     * @param $word
173
     * @return bool
174
     */
175 10
    public static function checkBaseLastConsonantSoftness($word)
176
    {
177 10
        $consonants = static::$consonants;
178 10
        unset($consonants[array_search('н', $consonants)]);
179 10
        unset($consonants[array_search('й', $consonants)]);
180
181 10 View Code Duplication
        if (($substring = S::findLastPositionForOneOfChars(S::lower($word), $consonants)) !== false) {
0 ignored issues
show
Duplication introduced by wapmorgan
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...
182
            if (in_array(S::slice($substring, 0, 1), ['й', 'ч', 'щ', 'ш'], true)) { // always soft consonants
183
                return true;
184
            } elseif (S::length($substring) > 1 && in_array(S::slice($substring, 1, 2), ['е', 'ё', 'и', 'ю', 'я', 'ь'], true)) { // consonants are soft if they are trailed with these vowels
185
                return true;
186
            }
187
        }
188 10
        return false;
189
    }
190
191
    /**
192
     * Проверяет, что гласная образует два звука в словах
193
     * @param $vowel
194
     * @return bool
195
     */
196 2
    public static function isBinaryVowel($vowel)
197
    {
198 2
        return in_array(S::lower($vowel), ['е', 'ё', 'ю', 'я'], true);
199
    }
200
201
    /**
202
     * Выбор предлога по первой букве
203
     *
204
     * @param string $word Слово
205
     * @param string $prepositionWithVowel Предлог, если слово начинается с гласной
206
     * @param string $preposition Предлог, если слово не начинается с гласной
207
     *
208
     * @return string
209
     */
210
    public static function choosePrepositionByFirstLetter($word, $prepositionWithVowel, $preposition)
211
    {
212 View Code Duplication
        if (in_array(S::lower(S::slice($word, 0, 1)), ['а', 'о', 'и', 'у', 'э'], true)) {
0 ignored issues
show
Duplication introduced by wapmorgan
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...
213
            return $prepositionWithVowel;
214
        } else {
215
            return $preposition;
216
        }
217
    }
218
219
    /**
220
     * Выбор окончания в зависимости от мягкости
221
     *
222
     * @param $last
223
     * @param $softLast
224
     * @param $afterSoft
225
     * @param $afterHard
226
     *
227
     * @return mixed
228
     */
229 130
    public static function chooseVowelAfterConsonant($last, $softLast, $afterSoft, $afterHard)
230
    {
231 130
        if ((RussianLanguage::isHissingConsonant($last) && !in_array($last, ['ж', 'ч'], true)) || /*static::isVelarConsonant($last) ||*/ $softLast) {
232 46
            return $afterSoft;
233
        } else {
234 100
            return $afterHard;
235
        }
236
    }
237
238
    /**
239
     * @param string $verb Verb to modify if gender is female
240
     * @param string $gender If not `m`, verb will be modified
241
     * @return string Correct verb
242
     */
243 10
    public static function verb($verb, $gender)
244
    {
245 10
        $verb = S::lower($verb);
246
        // возвратный глагол
247 10
        if (S::slice($verb, -2) == 'ся') {
0 ignored issues
show
Bug introduced by wapmorgan
It seems like $verb defined by \morphos\S::lower($verb) 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...
248
249 5
            return ($gender == Gender::MALE
250 2
                ? $verb
251 5
                : S::slice($verb, 0, -2).(S::slice($verb, -3, -2) === 'л' ? null : 'л').'ась');
0 ignored issues
show
Bug introduced by wapmorgan
It seems like $verb defined by \morphos\S::lower($verb) 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...
252
        }
253
254
        // обычный глагол
255 5
        return ($gender == Gender::MALE
256 2
            ? $verb
257 5
            : $verb.(S::slice($verb, -1) === 'л' ? null : 'л').'а');
0 ignored issues
show
Bug introduced by wapmorgan
It seems like $verb defined by \morphos\S::lower($verb) 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...
258
    }
259
260
    /**
261
     * Add 'в' or 'во' prepositional before the word
262
     * @param string $word
263
     * @return string
264
     */
265 1
    public static function in($word)
266
    {
267 1
        $normalized = trim(S::lower($word));
268 1 View Code Duplication
        if (in_array(S::slice($normalized, 0, 1), ['в', 'ф'], true))
0 ignored issues
show
Duplication introduced by wapmorgan
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...
269 1
            return 'во '.$word;
270 1
        return 'в '.$word;
271
    }
272
273
    /**
274
     * Add 'с' or 'со' prepositional before the word
275
     * @param string $word
276
     * @return string
277
     */
278 1
    public static function with($word)
279
    {
280 1
        $normalized = trim(S::lower($word));
281 1
        if (in_array(S::slice($normalized, 0, 1), ['c', 'з', 'ш', 'ж'], true) && static::isConsonant(S::slice($normalized, 1, 2)) || S::slice($normalized, 0, 1) == 'щ')
282 1
            return 'со '.$word;
283 1
        return 'с '.$word;
284
    }
285
286
    /**
287
     * Add 'о' or 'об' or 'обо' prepositional before the word
288
     * @param string $word
289
     * @return string
290
     */
291 1
    public static function about($word)
292
    {
293 1
        $normalized = trim(S::lower($word));
294 1
        if (static::isVowel(S::slice($normalized, 0, 1)) && !in_array(S::slice($normalized, 0, 1), ['е', 'ё', 'ю', 'я'], true))
295 1
            return 'об '.$word;
296
297 1 View Code Duplication
        if (in_array(S::slice($normalized, 0, 3), ['все', 'всё', 'всю', 'что', 'мне'], true))
0 ignored issues
show
Duplication introduced by wapmorgan
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...
298 1
            return 'обо '.$word;
299
300 1
        return 'о '.$word;
301
    }
302
303
    /**
304
     * Выбирает первое или второе окончание в зависимости от звонкости/глухости в конце слова.
305
     * @param string $word Слово (или префикс), на основе звонкости которого нужно выбрать окончание
306
     * @param string $ifSonorous Окончание, если слово оканчивается на звонкую согласную
307
     * @param string $ifDeaf Окончание, если слово оканчивается на глухую согласную
308
     * @return string Первое или второе окончание
309
     * @throws \Exception
310
     */
311 3
    public static function chooseEndingBySonority($word, $ifSonorous, $ifDeaf)
312
    {
313 3
        $last = S::slice($word, -1);
314 3
        if (static::isSonorousConsonant($last))
315 2
            return $ifSonorous;
316 1
        if (static::isDeafConsonant($last))
317 1
            return $ifDeaf;
318
319
        throw new \Exception('Not implemented');
320
    }
321
322
    /**
323
     * Проверяет, является ли существительно адъективным существительным
324
     * @param string $noun Существительное
325
     * @return bool
326
     */
327 157
    public static function isAdjectiveNoun($noun)
328
    {
329 157
        return in_array(S::slice($noun, -2), ['ой', 'ий', 'ый', 'ая', 'ое', 'ее'])
330 157
            && !in_array($noun, ['гений', 'комментарий']);
331
    }
332
333
    /**
334
     * @param array $forms
335
     * @param $animate
336
     * @return mixed
337
     */
338 117
    public static function getVinitCaseByAnimateness(array $forms, $animate)
339
    {
340 117
        if ($animate) {
341 9
            return $forms[Cases::RODIT];
342
        } else {
343 108
            return $forms[Cases::IMENIT];
344
        }
345
    }
346
}
347