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

src/Russian/RussianLanguage.php (3 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
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 343
    public static function isVowel($char)
79
    {
80 343
        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 452
    public static function isHissingConsonant($consonant)
117
    {
118 452
        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 46
    public static function checkLastConsonantSoftness($word)
159
    {
160 46
        if (($substring = S::findLastPositionForOneOfChars(S::lower($word), self::$consonants)) !== false) {
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 $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 123
    public static function chooseVowelAfterConsonant($last, $softLast, $afterSoft, $afterHard)
203
    {
204 123
        if ((RussianLanguage::isHissingConsonant($last) && !in_array($last, ['ж', 'ч'], true)) || /*self::isVelarConsonant($last) ||*/ $softLast) {
205 43
            return $afterSoft;
206
        } else {
207 96
            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) == 'ся') {
0 ignored issues
show
It seems like $verb defined by \morphos\S::lower($verb) on line 218 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...
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 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...
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 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...
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 152
    public static function isAdjectiveNoun($noun)
301
    {
302 152
        return in_array(S::slice($noun, -2), ['ой', 'ий', 'ый', 'ая', 'ое', 'ее'])
303 152
            && !in_array($noun, ['гений', 'комментарий']);
304
    }
305
}
306