Completed
Push — master ( 082bc3...d55ee4 )
by f
11:06 queued 21s
created

src/Russian/RussianLanguage.php (2 issues)

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
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 342
    public static function isVowel($char)
79
    {
80 342
        return in_array($char, self::$vowels, true);
81
    }
82
83
    /**
84
     * Проверка согласной
85
     * @param $char
86
     * @return bool
87
     */
88 199
    public static function isConsonant($char)
89
    {
90 199
        return in_array($char, self::$consonants, true);
91
    }
92
93
    /**
94
     * Проверка звонкости согласной
95
     */
96 3
    public static function isSonorousConsonant($char)
97
    {
98 3
        return in_array($char, self::$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, self::$deafConsonants, true);
109
    }
110
111
    /**
112
     * Щипящая ли согласная
113
     * @param $consonant
114
     * @return bool
115
     */
116 450
    public static function isHissingConsonant($consonant)
117
    {
118 450
        return in_array(S::lower($consonant), ['ж', 'ш', 'ч', 'щ'], true);
119
    }
120
121
    /**
122
     * Проверка на велярность согласной
123
     * @param string[1] $consonant
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, self::$vowels);
139
    }
140
141
    /**
142
     * Проверка парности согласной
143
     *
144
     * @param $consonant
145
     * @return bool
146
     */
147
    public static function isPaired($consonant)
148
    {
149
        $consonant = S::lower($consonant);
150
        return array_key_exists($consonant, self::$pairs) || (array_search($consonant, self::$pairs) !== false);
151
    }
152
153
    /**
154
     * Проверка мягкости последней согласной
155
     * @param $word
156
     * @return bool
157
     */
158 44
    public static function checkLastConsonantSoftness($word)
159
    {
160 44
        if (($substring = S::findLastPositionForOneOfChars(S::lower($word), self::$consonants)) !== false) {
161 44
            if (in_array(S::slice($substring, 0, 1), ['й', 'ч', 'щ'], true)) { // always soft consonants
162 14
                return true;
163 30
            } 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 27
        return false;
168
    }
169
170
    /**
171
     * Проверяет, что гласная образует два звука в словах
172
     * @param $vowel
173
     * @return bool
174
     */
175 2
    public static function isBinaryVowel($vowel)
176
    {
177 2
        return in_array(S::lower($vowel), ['е', 'ё', 'ю', 'я'], true);
178
    }
179
180
    /**
181
     * Выбор предлога по первой букве
182
     */
183
    public static function choosePrepositionByFirstLetter($word, $prepositionWithVowel, $preposition)
184
    {
185 View Code Duplication
        if (in_array(S::lower(S::slice($word, 0, 1)), ['а', 'о', 'и', 'у', 'э'], true)) {
186
            return $prepositionWithVowel;
187
        } else {
188
            return $preposition;
189
        }
190
    }
191
192
    /**
193
     * Выбор окончания в зависимости от мягкости
194
     *
195
     * @param $last
196
     * @param $softLast
197
     * @param $afterSoft
198
     * @param $afterHard
199
     *
200
     * @return mixed
201
     */
202 121
    public static function chooseVowelAfterConsonant($last, $softLast, $afterSoft, $afterHard)
203
    {
204 121
        if ((RussianLanguage::isHissingConsonant($last) && !in_array($last, ['ж', 'ч'], true)) || /*self::isVelarConsonant($last) ||*/ $softLast) {
205 42
            return $afterSoft;
206
        } else {
207 94
            return $afterHard;
208
        }
209
    }
210
211
    /**
212
     * @param string $verb Verb to modify if gender is female
213
     * @param string $gender If not `m`, verb will be modified
214
     * @return string Correct verb
215
     */
216 10
    public static function verb($verb, $gender)
217
    {
218 10
        $verb = S::lower($verb);
219
        // возвратный глагол
220 10
        if (S::slice($verb, -2) == 'ся') {
221
222 5
            return ($gender == Gender::MALE
223 2
                ? $verb
224 5
                : S::slice($verb, 0, -2).(S::slice($verb, -3, -2) === 'л' ? null : 'л').'ась');
0 ignored issues
show
It seems like $verb defined by \morphos\S::lower($verb) on line 218 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...
225
        }
226
227
        // обычный глагол
228 5
        return ($gender == Gender::MALE
229 2
            ? $verb
230 5
            : $verb.(S::slice($verb, -1) === 'л' ? null : 'л').'а');
0 ignored issues
show
It seems like $verb defined by \morphos\S::lower($verb) on line 218 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...
231
    }
232
233
    /**
234
     * Add 'в' or 'во' prepositional before the word
235
     * @param string $word
236
     * @return string
237
     */
238 1
    public static function in($word)
239
    {
240 1
        $normalized = trim(S::lower($word));
241 1 View Code Duplication
        if (in_array(S::slice($normalized, 0, 1), ['в', 'ф'], true))
242 1
            return 'во '.$word;
243 1
        return 'в '.$word;
244
    }
245
246
    /**
247
     * Add 'с' or 'со' prepositional before the word
248
     * @param string $word
249
     * @return string
250
     */
251 1
    public static function with($word)
252
    {
253 1
        $normalized = trim(S::lower($word));
254 1
        if (in_array(S::slice($normalized, 0, 1), ['c', 'з', 'ш', 'ж'], true) && static::isConsonant(S::slice($normalized, 1, 2)) || S::slice($normalized, 0, 1) == 'щ')
255 1
            return 'со '.$word;
256 1
        return 'с '.$word;
257
    }
258
259
    /**
260
     * Add 'о' or 'об' or 'обо' prepositional before the word
261
     * @param string $word
262
     * @return string
263
     */
264 1
    public static function about($word)
265
    {
266 1
        $normalized = trim(S::lower($word));
267 1
        if (static::isVowel(S::slice($normalized, 0, 1)) && !in_array(S::slice($normalized, 0, 1), ['е', 'ё', 'ю', 'я'], true))
268 1
            return 'об '.$word;
269
270 1 View Code Duplication
        if (in_array(S::slice($normalized, 0, 3), ['все', 'всё', 'всю', 'что', 'мне'], true))
271 1
            return 'обо '.$word;
272
273 1
        return 'о '.$word;
274
    }
275
276
    /**
277
     * Выбирает первое или второе окончание в зависимости от звонкости/глухости в конце слова.
278
     * @param string $word Слово (или префикс), на основе звонкости которого нужно выбрать окончание
279
     * @param string $ifSonorous Окончание, если слово оканчивается на звонкую согласную
280
     * @param string $ifDeaf Окончание, если слово оканчивается на глухую согласную
281
     * @return string Первое или второе окончание
282
     * @throws \Exception
283
     */
284 3
    public static function chooseEndingBySonority($word, $ifSonorous, $ifDeaf)
285
    {
286 3
        $last = S::slice($word, -1);
287 3
        if (self::isSonorousConsonant($last))
288 2
            return $ifSonorous;
289 1
        if (self::isDeafConsonant($last))
290 1
            return $ifDeaf;
291
292
        throw new \Exception('Not implemented');
293
    }
294
295
    /**
296
     * Проверяет, является ли существительно адъективным существительным
297
     * @param string $noun Существительное
298
     * @return bool
299
     */
300 150
    public static function isAdjectiveNoun($noun)
301
    {
302 150
        return in_array(S::slice($noun, -2), ['ой', 'ий', 'ый', 'ая', 'ое', 'ее'])
303 150
            && !in_array($noun, ['гений', 'комментарий']);
304
    }
305
}
306