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

AdjectiveDeclension::declinateHardAdjective()   B

Complexity

Conditions 9
Paths 128

Size

Total Lines 34

Duplication

Lines 34
Ratio 100 %

Code Coverage

Tests 19
CRAP Score 9

Importance

Changes 0
Metric Value
cc 9
nc 128
nop 4
dl 34
loc 34
ccs 19
cts 19
cp 1
crap 9
rs 7.8222
c 0
b 0
f 0
1
<?php
2
namespace morphos\Russian;
3
4
use morphos\BaseInflection;
5
use morphos\Gender;
6
use morphos\S;
7
8
/**
9
 * Class AdjectiveDeclension.
10
 *
11
 * Склонение прилагательных.
12
 *
13
 * Правила склонения:
14
 * - http://www.fio.ru/pravila/grammatika/sklonenie-prilagatelnykh-v-russkom-yazyke/
15
 *
16
 * @package morphos\Russian
17
 */
18
class AdjectiveDeclension extends BaseInflection implements Cases, Gender
19
{
20
    use RussianLanguage, CasesHelper;
21
22
    const HARD_BASE = 1;
23
    const SOFT_BASE = 2;
24
    const MIXED_BASE = 3;
25
26
    /**
27
     * @param string $adjective
28
     * @return bool|void
29
     */
30
    public static function isMutable($adjective)
31
    {
32
        return false;
33
    }
34
35
    /**
36
     * @param string $adjective
37
     * @param string $case
38
     * @param bool   $animateness
39
     * @param null   $gender
40
     *
41
     * @return string
42
     * @throws \Exception
43
     */
44
    public static function getCase($adjective, $case, $animateness = false, $gender = null)
45
    {
46
        $case = static::canonizeCase($case);
47
48
        if ($gender === null)
49
            $gender = static::detectGender($adjective);
50
51
        $forms = static::getCases($adjective, $animateness, $gender);
52
        return $forms[$case];
53
    }
54
55
    /**
56
     * @param      $adjective
57
     *
58
     * @param bool $isEmphasized
59
     *
60
     * @return string
61
     */
62 24
    public static function detectGender($adjective, &$isEmphasized = false)
63
    {
64 24
        switch (S::lower(S::slice($adjective, -2)))
65
        {
66 24
            case 'ой':
67 4
                $isEmphasized = true;
68 20
            case 'ый':
69 19
            case 'ий':
70 8
                return static::MALE;
71
72 16
            case 'ая':
73 10
            case 'яя':
74 8
                return static::FEMALE;
75
76 8
            case 'ое':
77 2
            case 'ее':
78 8
                return static::NEUTER;
79
        }
80
    }
81
82
    /**
83
     * @param string $adjective
84
     * @param bool $animateness
85
     * @param null|string $gender
86
     *
87
     * @return array
88
     */
89 18
    public static function getCases($adjective, $animateness = false, $gender = null)
90
    {
91 18
        if ($gender === null)
92 18
            $gender = static::detectGender($adjective, $isEmphasized);
93
94 18
        $last_consonant_vowel = S::slice($adjective, -2, -1);
95 18
        $type = static::getAdjectiveBaseType($adjective);
96 18
        $adjective = S::slice($adjective, 0, -2);
97
98
        switch ($type)
99
        {
100 18
            case static::HARD_BASE:
101 6
                return static::declinateHardAdjective($adjective, $animateness, $gender,
0 ignored issues
show
Security Bug introduced by wapmorgan
It seems like $adjective defined by \morphos\S::slice($adjective, 0, -2) on line 96 can also be of type false; however, morphos\Russian\Adjectiv...eclinateHardAdjective() 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...
102 6
                    $last_consonant_vowel);
103
104 12
            case static::SOFT_BASE:
105 3
                return static::declinateSoftAdjective($adjective, $animateness, $gender,
0 ignored issues
show
Security Bug introduced by wapmorgan
It seems like $adjective defined by \morphos\S::slice($adjective, 0, -2) on line 96 can also be of type false; however, morphos\Russian\Adjectiv...eclinateSoftAdjective() 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...
106 3
                    $last_consonant_vowel);
107
108 9
            case static::MIXED_BASE:
109 9
                return static::declinateMixedAdjective($adjective, $animateness, $gender,
0 ignored issues
show
Security Bug introduced by wapmorgan
It seems like $adjective defined by \morphos\S::slice($adjective, 0, -2) on line 96 can also be of type false; however, morphos\Russian\Adjectiv...clinateMixedAdjective() 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...
110 9
                    $last_consonant_vowel);
111
        }
112
    }
113
114
    /**
115
     * @param $adjective
116
     *
117
     * @return int
118
     */
119 19
    public static function getAdjectiveBaseType($adjective)
120
    {
121 19
        $adjective = S::lower($adjective);
122 19
        $consonants = static::$consonants;
123
124 19
        unset($consonants[array_search('н', $consonants)]);
125 19
        unset($consonants[array_search('й', $consonants)]);
126
127 19
        $substring = S::findLastPositionForOneOfChars($adjective, $consonants);
128 19
        $last_consonant = S::slice($substring, 0, 1);
0 ignored issues
show
Security Bug introduced by wapmorgan
It seems like $substring defined by \morphos\S::findLastPosi...adjective, $consonants) on line 127 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...
129
130
        // г, к, х, ударное ш - признак смешанного прилагательно
131 19
        if (in_array($last_consonant, ['г', 'к', 'х'], true) ||
132
            (
133 19
            $last_consonant === 'ш' && in_array(S::slice($substring, 1, 2), ['о', 'а'], true)
0 ignored issues
show
Security Bug introduced by wapmorgan
It seems like $substring defined by \morphos\S::findLastPosi...adjective, $consonants) on line 127 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...
134
            )) {
135 9
            return static::MIXED_BASE;
136
        }
137
138 10
        return static::checkBaseLastConsonantSoftness($substring)
139 10
            || (S::slice($substring, 0, 2) === 'шн')
0 ignored issues
show
Security Bug introduced by wapmorgan
It seems like $substring defined by \morphos\S::findLastPosi...adjective, $consonants) on line 127 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...
140 3
            ? static::SOFT_BASE
141 10
            : static::HARD_BASE;
142
    }
143
144
    /**
145
     * @param string $adjective
146
     * @param bool   $animateness
147
     * @param string $gender
148
     * @param bool   $isEmphasized
0 ignored issues
show
Bug introduced by wapmorgan
There is no parameter named $isEmphasized. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
149
     *
150
     * @param        $afterConsonantVowel
151
     *
152
     * @return array
153
     */
154 6 View Code Duplication
    protected static function declinateHardAdjective($adjective, $animateness, $gender,
0 ignored issues
show
Duplication introduced by wapmorgan
This method seems to be duplicated in 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...
155
        $afterConsonantVowel)
156
    {
157
        switch ($gender)
158
        {
159 6
            case static::MALE:
160 2
                $postfix = $afterConsonantVowel.'й';
161 2
                break;
162
163 4
            case static::FEMALE:
164 2
                $postfix = $afterConsonantVowel.'я';
165 2
                break;
166
167 2
            case static::NEUTER:
168 2
                $postfix = $afterConsonantVowel.'е';
169 2
                break;
170
        }
171
172
        $cases = [
173 6
            static::IMENIT => $adjective.$postfix,
0 ignored issues
show
Bug introduced by wapmorgan
The variable $postfix does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
174 6
            static::RODIT => $adjective.'о'.($gender !== static::FEMALE ? 'го' : 'й'),
175 6
            static::DAT => $adjective.'о'.($gender !== static::FEMALE ? 'му' : 'й'),
176
        ];
177
178 6
        if ($gender !== static::FEMALE)
179 4
            $cases[static::VINIT] = static::getVinitCaseByAnimateness($cases, $animateness);
180
        else
181 2
            $cases[static::VINIT] = $adjective.'ую';
182
183 6
        $cases[static::TVORIT] = $adjective.($gender !== static::FEMALE ? 'ым' : 'ой');
184 6
        $cases[static::PREDLOJ] = $adjective.($gender !== static::FEMALE ? 'ом' : 'ой');
185
186 6
        return $cases;
187
    }
188
189
    /**
190
     * @param string $adjective
191
     * @param bool   $animateness
192
     * @param string $gender
193
     * @param bool   $isEmphasized
0 ignored issues
show
Bug introduced by wapmorgan
There is no parameter named $isEmphasized. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
194
     *
195
     * @param        $afterConsonantVowel
196
     *
197
     * @return array
198
     */
199 3 View Code Duplication
    protected static function declinateSoftAdjective($adjective, $animateness, $gender, $afterConsonantVowel)
0 ignored issues
show
Duplication introduced by wapmorgan
This method seems to be duplicated in 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...
200
    {
201
        switch ($gender)
202
        {
203 3
            case static::MALE:
204 1
                $postfix = $afterConsonantVowel.'й';
205 1
                break;
206
207 2
            case static::FEMALE:
208 1
                $postfix = $afterConsonantVowel.'я';
209 1
                break;
210
211 1
            case static::NEUTER:
212 1
                $postfix = $afterConsonantVowel.'е';
213 1
                break;
214
        }
215
216
        $cases = [
217 3
            static::IMENIT => $adjective.$postfix,
0 ignored issues
show
Bug introduced by wapmorgan
The variable $postfix does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
218 3
            static::RODIT => $adjective.'е'.($gender !== static::FEMALE ? 'го' : 'й'),
219 3
            static::DAT => $adjective.'е'.($gender !== static::FEMALE ? 'му' : 'й'),
220
        ];
221
222 3
        if ($gender !== static::FEMALE)
223 2
            $cases[static::VINIT] = static::getVinitCaseByAnimateness($cases, $animateness);
224
        else
225 1
            $cases[static::VINIT] = $adjective.'юю';
226
227 3
        $cases[static::TVORIT] = $adjective.($gender !== static::FEMALE ? 'им' : 'ей');
228 3
        $cases[static::PREDLOJ] = $adjective.($gender !== static::FEMALE ? 'ем' : 'ей');
229
230 3
        return $cases;
231
    }
232
233
    /**
234
     * @param string $adjective
235
     * @param bool   $animateness
236
     * @param string $gender
237
     * @param bool   $isEmphasized
0 ignored issues
show
Bug introduced by wapmorgan
There is no parameter named $isEmphasized. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
238
     *
239
     * @return array
240
     */
241 9
    protected static function declinateMixedAdjective($adjective, $animateness, $gender, $afterConsonantVowel)
242
    {
243
        switch ($gender)
244
        {
245 9
            case static::MALE:
246 3
                $postfix = $afterConsonantVowel.'й';
247 3
                break;
248
249 6
            case static::FEMALE:
250 3
                $postfix = $afterConsonantVowel.'я';
251 3
                break;
252
253 3
            case static::NEUTER:
254 3
                $postfix = $afterConsonantVowel.'е';
255 3
                break;
256
        }
257
258
        $cases = [
259 9
            static::IMENIT => $adjective.$postfix,
0 ignored issues
show
Bug introduced by wapmorgan
The variable $postfix does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
260 9
            static::RODIT => $adjective.'о'.($gender !== static::FEMALE ? 'го' : 'й'),
261 9
            static::DAT => $adjective.'о'.($gender !== static::FEMALE ? 'му' : 'й'),
262
        ];
263
264 9
        if ($gender === static::MALE)
265 3
            $cases[static::VINIT] = static::getVinitCaseByAnimateness($cases, $animateness);
266 6
        else if ($gender === static::NEUTER)
267 3
            $cases[static::VINIT] = $adjective.'ое';
268
        else
269 3
            $cases[static::VINIT] = $adjective.'ую';
270
271 9
        $cases[static::TVORIT] = $adjective.($gender !== static::FEMALE ? 'им' : 'ой');
272 9
        $cases[static::PREDLOJ] = $adjective.($gender !== static::FEMALE ? 'ом' : 'ой');
273
274 9
        return $cases;
275
    }
276
}