Completed
Push — master ( a340ad...e06350 )
by f
01:53
created

src/Russian/RussianLanguage.php (1 issue)

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
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
0 ignored issues
show
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, 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 8
    public static function verb($verb, $gender)
217
    {
218 8
        $verb = S::lower($verb);
219
        // возвратный глагол
220 8
        if (S::slice($verb, -2) == 'ся') {
221 4
            return ($gender == Gender::MALE ? $verb : mb_substr($verb, 0, -2).'ась');
222
        }
223
224
        // обычный глагол
225 4
        return ($gender == Gender::MALE ? $verb : $verb.'а');
226
    }
227
228
    /**
229
     * Add 'в' or 'во' prepositional before the word
230
     * @param string $word
231
     * @return string
232
     */
233 1
    public static function in($word)
234
    {
235 1
        $normalized = trim(S::lower($word));
236 1 View Code Duplication
        if (in_array(S::slice($normalized, 0, 1), ['в', 'ф'], true))
237 1
            return 'во '.$word;
238 1
        return 'в '.$word;
239
    }
240
241
    /**
242
     * Add 'с' or 'со' prepositional before the word
243
     * @param string $word
244
     * @return string
245
     */
246 1
    public static function with($word)
247
    {
248 1
        $normalized = trim(S::lower($word));
249 1
        if (in_array(S::slice($normalized, 0, 1), ['c', 'з', 'ш', 'ж'], true) && static::isConsonant(S::slice($normalized, 1, 2)) || S::slice($normalized, 0, 1) == 'щ')
250 1
            return 'со '.$word;
251 1
        return 'с '.$word;
252
    }
253
254
    /**
255
     * Add 'о' or 'об' or 'обо' prepositional before the word
256
     * @param string $word
257
     * @return string
258
     */
259 1
    public static function about($word)
260
    {
261 1
        $normalized = trim(S::lower($word));
262 1
        if (static::isVowel(S::slice($normalized, 0, 1)) && !in_array(S::slice($normalized, 0, 1), ['е', 'ё', 'ю', 'я'], true))
263 1
            return 'об '.$word;
264
265 1 View Code Duplication
        if (in_array(S::slice($normalized, 0, 3), ['все', 'всё', 'всю', 'что', 'мне'], true))
266 1
            return 'обо '.$word;
267
268 1
        return 'о '.$word;
269
    }
270
271
    /**
272
     * Выбирает первое или второе окончание в зависимости от звонкости/глухости в конце слова.
273
     * @param string $word Слово (или префикс), на основе звонкости которого нужно выбрать окончание
274
     * @param string $ifSonorous Окончание, если слово оканчивается на звонкую согласную
275
     * @param string $ifDeaf Окончание, если слово оканчивается на глухую согласную
276
     * @return string Первое или второе окончание
277
     * @throws \Exception
278
     */
279 3
    public static function chooseEndingBySonority($word, $ifSonorous, $ifDeaf)
280
    {
281 3
        $last = S::slice($word, -1);
282 3
        if (self::isSonorousConsonant($last))
283 2
            return $ifSonorous;
284 1
        if (self::isDeafConsonant($last))
285 1
            return $ifDeaf;
286
287
        throw new \Exception('Not implemented');
288
    }
289
290
    /**
291
     * Проверяет, является ли существительно адъективным существительным
292
     * @param string $noun Существительное
293
     * @return bool
294
     */
295 150
    public static function isAdjectiveNoun($noun)
296
    {
297 150
        return in_array(S::slice($noun, -2), ['ой', 'ий', 'ый', 'ая', 'ое', 'ее'])
298 150
            && !in_array($noun, ['гений', 'комментарий']);
299
    }
300
}
301