| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  | namespace morphos\Russian; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | use morphos\S; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  |  * Rules are from http://morpher.ru/Russian/Noun.aspx | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | class NounPluralization extends \morphos\BasePluralization implements Cases | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |     use RussianLanguage, CasesHelper; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |     const ONE = 1; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |     const TWO_FOUR = 2; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |     const FIVE_OTHER = 3; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |      * @var string[][] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |      * @phpstan-var array<string, string[]> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  |     protected static $abnormalExceptions = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  |         'человек' => ['люди', 'человек', 'людям', 'людей', 'людьми', 'людях'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |     ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |     /** @var string[] */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |     protected static $neuterExceptions = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |         'поле', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |         'море', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |     ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |      * @var string[] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |      * @phpstan-var array<string, string> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |     protected static $genitiveExceptions = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |         'письмо' => 'писем', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |         'пятно' => 'пятен', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |         'кресло' => 'кресел', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |         'коромысло' => 'коромысел', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |         'ядро' => 'ядер', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |         'блюдце' => 'блюдец', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |         'полотенце' => 'полотенец', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |         'гривна' => 'гривен', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |         'год' => 'лет', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |     ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |      * Склонение существительного для сочетания с числом (кол-вом предметов). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |      * @param string|int $word        Название предмета | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |      * @param int|float|string $count Количество предметов | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |      * @param bool       $animateness Признак одушевленности | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |      * @param string     $case        Род существительного | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |      * @return string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |      * @throws \Exception | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 | 62 |  |     public static function pluralize($word, $count = 2, $animateness = false, $case = null) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |         // меняем местами аргументы, если они переданы в старом формате | 
            
                                                                                                            
                            
            
                                                                    
                                                                                                        
            
            
                | 61 | 62 | View Code Duplication |         if (is_string($count) && is_numeric($word)) { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 | 1 |  |             list($count, $word) = [$word, $count]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 | 62 |  |         if ($case !== null) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 | 3 |  |             $case = static::canonizeCase($case); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |         // для адъективных существительных правила склонения проще: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |         // только две формы | 
            
                                                                                                            
                            
            
                                                                    
                                                                                                        
            
            
                | 70 | 62 | View Code Duplication |         if (static::isAdjectiveNoun($word)) { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 | 3 |  |             if (static::getNumeralForm($count) == static::ONE) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 | 2 |  |                 return $word; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |             else | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 | 3 |  |                 return NounPluralization::getCase($word, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 | 3 |  |                     $case !== null | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |                         ? $case | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 | 3 |  |                         : static::RODIT, $animateness); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 | 60 |  |         if ($case === null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 | 57 |  |             switch (static::getNumeralForm($count)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 | 57 |  |                 case static::ONE: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 | 29 |  |                     return $word; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 | 57 |  |                 case static::TWO_FOUR: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 | 36 |  |                     return NounDeclension::getCase($word, static::RODIT, $animateness); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 | 44 |  |                 case static::FIVE_OTHER: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 | 44 |  |                     return NounPluralization::getCase($word, static::RODIT, $animateness); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |  | 
            
                                                                                                            
                            
            
                                                                    
                                                                                                        
            
            
                | 91 | 3 | View Code Duplication |         if (static::getNumeralForm($count) == static::ONE) | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 | 3 |  |             return NounDeclension::getCase($word, $case, $animateness); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |         else | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 | 3 |  |             return NounPluralization::getCase($word, $case, $animateness); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |      * @param int|float $count | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |      * @return int | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 | 74 |  |     public static function getNumeralForm($count) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 | 74 |  |         if ($count > 100) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 | 48 |  |             $count %= 100; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 | 74 |  |         $ending = $count % 10; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 | 74 |  |         if (($count > 20 && $ending == 1) || $count == 1) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 | 38 |  |             return static::ONE; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 | 73 |  |         } elseif (($count > 20 && in_array($ending, range(2, 4))) || in_array($count, range(2, 4))) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 | 48 |  |             return static::TWO_FOUR; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |         } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 | 56 |  |             return static::FIVE_OTHER; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |      * @param string $word | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |      * @param string $case | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |      * @param bool $animateness | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |      * @return string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |      * @throws \Exception | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 123 |  |  |      */ | 
            
                                                                        
                            
            
                                    
            
            
                | 124 | 49 |  |     public static function getCase($word, $case, $animateness = false) | 
            
                                                                        
                            
            
                                    
            
            
                | 125 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 126 | 49 |  |         $case = static::canonizeCase($case); | 
            
                                                                        
                            
            
                                    
            
            
                | 127 | 49 |  |         $forms = static::getCases($word, $animateness); | 
            
                                                                        
                            
            
                                    
            
            
                | 128 | 49 |  |         return $forms[$case]; | 
            
                                                                        
                            
            
                                    
            
            
                | 129 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |      * @param string $word | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |      * @param bool $animateness | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |      * @return string[] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |      * @phpstan-return array<string, string> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 | 97 |  |     public static function getCases($word, $animateness = false) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 | 97 |  |         $word = S::lower($word); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |  | 
            
                                                                                                            
                            
            
                                                                    
                                                                                                        
            
            
                | 141 | 97 | View Code Duplication |         if (in_array($word, NounDeclension::$immutableWords, true)) { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |             return [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 | 1 |  |                 static::IMENIT => $word, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 | 1 |  |                 static::RODIT => $word, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 | 1 |  |                 static::DAT => $word, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 | 1 |  |                 static::VINIT => $word, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 | 1 |  |                 static::TVORIT => $word, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 | 1 |  |                 static::PREDLOJ => $word, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |             ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |  | 
            
                                                                                                            
                            
            
                                                                    
                                                                                                        
            
            
                | 152 | 97 | View Code Duplication |         if (isset(static::$abnormalExceptions[$word])) { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 | 1 |  |             return array_combine( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 | 1 |  |                 [static::IMENIT, static::RODIT, static::DAT, static::VINIT, static::TVORIT, static::PREDLOJ], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 | 1 |  |                 static::$abnormalExceptions[$word]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |         // Адъективное склонение (Сущ, образованные от прилагательных и причастий) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |         // Пример: прохожий, существительное | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 | 96 |  |         if (static::isAdjectiveNoun($word)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 | 11 |  |             return static::declinateAdjective($word, $animateness); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  |         // Субстантивное склонение (существительные) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 | 86 |  |         return static::declinateSubstative($word, $animateness); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  |      * Склонение обычных существительных. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  |      * @param string $word | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  |      * @param bool $animateness | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 |  |  |      * @return string[] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  |      * @phpstan-return array<string, string> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 | 86 |  |     protected static function declinateSubstative($word, $animateness) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 | 86 |  |         $prefix = S::slice($word, 0, -1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 | 86 |  |         $last = S::slice($word, -1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 | 86 |  |         if (($declension = NounDeclension::getDeclension($word)) == NounDeclension::SECOND_DECLENSION) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 | 56 |  |             $soft_last = $last == 'й' || (in_array($last, ['ь', 'е', 'ё', 'ю', 'я'], true) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 |  |  |                     && (( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 | 21 |  |                         static::isConsonant(S::slice($word, -2, -1)) && !static::isHissingConsonant(S::slice($word, -2, -1))) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 | 56 |  |                         || S::slice($word, -2, -1) == 'и')); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 | 56 |  |             $prefix = NounDeclension::getPrefixOfSecondDeclension($word, $last); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 | 42 |  |         } elseif ($declension == NounDeclension::FIRST_DECLENSION) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 | 37 |  |             $soft_last = static::checkLastConsonantSoftness($word); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 |  |  |         } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 | 5 |  |             $soft_last = in_array(S::slice($word, -2), ['чь', 'сь', 'ть', 'нь', 'дь'], true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 | 86 |  |         $forms = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 | 86 |  |         if (in_array($last, ['ч', 'г'], true) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 | 84 |  |             || in_array(S::slice($word, -2), ['чь', 'сь', 'ть', 'нь', 'рь', 'дь', 'ль'], true) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 | 86 |  |             || (static::isVowel($last) && in_array(S::slice($word, -2, -1), ['ч', 'к'], true))) { // before ч, чь, сь, ч+vowel, к+vowel | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 | 44 |  |             $forms[Cases::IMENIT] = $prefix.'и'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 | 48 |  |         } elseif (in_array($last, ['н', 'ц', 'р', 'т'], true)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 199 | 19 |  |             $forms[Cases::IMENIT] = $prefix.'ы'; | 
            
                                                                                                            
                            
            
                                                                    
                                                                                                        
            
            
                | 200 |  | View Code Duplication |         } else { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 201 | 33 |  |             $forms[Cases::IMENIT] = static::chooseVowelAfterConsonant($last, $soft_last, $prefix.'я', $prefix.'а'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 202 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 203 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 204 |  |  |         // RODIT | 
            
                                                                                                            
                            
            
                                    
            
            
                | 205 | 86 |  |         if (isset(static::$genitiveExceptions[$word])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 206 | 10 |  |             $forms[Cases::RODIT] = static::$genitiveExceptions[$word]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 207 | 78 |  |         } elseif (in_array($last, ['о', 'е'], true)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 208 |  |  |             // exceptions | 
            
                                                                                                            
                            
            
                                    
            
            
                | 209 | 8 |  |             if (in_array($word, static::$neuterExceptions, true)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 210 | 3 |  |                 $forms[Cases::RODIT] = $prefix.'ей'; | 
            
                                                                                                            
                            
            
                                                                    
                                                                                                        
            
            
                | 211 | 5 | View Code Duplication |             } elseif (S::slice($word, -2, -1) == 'и') { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 212 | 2 |  |                 $forms[Cases::RODIT] = $prefix.'й'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 213 |  |  |             } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 214 | 8 |  |                 $forms[Cases::RODIT] = $prefix; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 215 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 216 | 70 |  |         } elseif (S::slice($word, -2) == 'ка' && S::slice($word, -3, -2) !== 'и') { // words ending with -ка: чашка, вилка, ложка, тарелка, копейка, батарейка, аптека | 
            
                                                                                                            
                            
            
                                    
            
            
                | 217 | 13 |  |             if (S::slice($word, -3, -2) == 'л') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 218 | 2 |  |                 $forms[Cases::RODIT] = S::slice($word, 0, -2).'ок'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 219 | 11 |  |             } elseif (in_array(S::slice($word, -3, -2), ['й', 'е'], true)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 220 | 9 |  |                 $forms[Cases::RODIT] = S::slice($word, 0, -3).'ек'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 221 |  |  |             } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 222 | 13 |  |                 $forms[Cases::RODIT] = S::slice($word, 0, -2).'ек'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 223 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 224 | 63 |  |         } elseif (in_array($last, ['а'], true)) { // обида, ябеда | 
            
                                                                                                            
                            
            
                                    
            
            
                | 225 | 23 |  |             $forms[Cases::RODIT] = $prefix; | 
            
                                                                                                            
                            
            
                                                                    
                                                                                                        
            
            
                | 226 | 47 | View Code Duplication |         } elseif (in_array($last, ['я'], true)) { // молния | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 227 | 1 |  |             $forms[Cases::RODIT] = $prefix.'й'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 228 | 46 |  |         } elseif (RussianLanguage::isHissingConsonant($last) || ($soft_last && $last != 'й') || in_array(S::slice($word, -2), ['чь', 'сь', 'ть', 'нь', 'дь'], true)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 229 | 22 |  |             $forms[Cases::RODIT] = $prefix.'ей'; | 
            
                                                                                                            
                            
            
                                                                    
                                                                                                        
            
            
                | 230 | 27 | View Code Duplication |         } elseif ($last == 'й' || S::slice($word, -2) == 'яц') { // месяц | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 231 | 7 |  |             $forms[Cases::RODIT] = $prefix.'ев'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 232 |  |  |         } else { // (static::isConsonant($last) && !RussianLanguage::isHissingConsonant($last)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 233 | 20 |  |             $forms[Cases::RODIT] = $prefix.'ов'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 234 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 235 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 236 |  |  |         // DAT | 
            
                                                                                                            
                            
            
                                    
            
            
                | 237 | 86 |  |         $forms[Cases::DAT] = static::chooseVowelAfterConsonant($last, $soft_last && S::slice($word, -2, -1) != 'ч', $prefix.'ям', $prefix.'ам'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 238 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 239 |  |  |         // VINIT | 
            
                                                                                                            
                            
            
                                    
            
            
                | 240 | 86 |  |         $forms[Cases::VINIT] = NounDeclension::getVinitCaseByAnimateness($forms, $animateness); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 241 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 242 |  |  |         // TVORIT | 
            
                                                                                                            
                            
            
                                    
            
            
                | 243 |  |  |         // my personal rule | 
            
                                                                                                            
                            
            
                                    
            
            
                | 244 | 86 |  |         if ($last == 'ь' && $declension == NounDeclension::THIRD_DECLENSION && !in_array(S::slice($word, -2), ['чь', 'сь', 'ть', 'нь', 'дь'], true)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 245 |  |  |             $forms[Cases::TVORIT] = $prefix.'ми'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 246 |  |  |         } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 247 | 86 |  |             $forms[Cases::TVORIT] = static::chooseVowelAfterConsonant($last, $soft_last && S::slice($word, -2, -1) != 'ч', $prefix.'ями', $prefix.'ами'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 248 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 249 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 250 |  |  |         // PREDLOJ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 251 | 86 |  |         $forms[Cases::PREDLOJ] = static::chooseVowelAfterConsonant($last, $soft_last && S::slice($word, -2, -1) != 'ч', $prefix.'ях', $prefix.'ах'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 252 | 86 |  |         return $forms; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 253 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 254 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 255 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 256 |  |  |      * Склонение существительных, образованных от прилагательных и причастий. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 257 |  |  |      * Rules are from http://rusgram.narod.ru/1216-1231.html | 
            
                                                                                                            
                            
            
                                    
            
            
                | 258 |  |  |      * @param string $word | 
            
                                                                                                            
                            
            
                                    
            
            
                | 259 |  |  |      * @param bool $animateness | 
            
                                                                                                            
                            
            
                                    
            
            
                | 260 |  |  |      * @return string[] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 261 |  |  |      * @phpstan-return array<string, string> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 262 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 263 | 11 |  |     protected static function declinateAdjective($word, $animateness) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 264 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 265 | 11 |  |         $prefix = S::slice($word, 0, -2); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 266 | 11 |  |         $vowel = static::isHissingConsonant(S::slice($prefix, -1)) ? 'и' : 'ы'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 267 |  |  |         return [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 268 | 11 |  |             Cases::IMENIT => $prefix.$vowel.'е', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 269 | 11 |  |             Cases::RODIT => $prefix.$vowel.'х', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 270 | 11 |  |             Cases::DAT => $prefix.$vowel.'м', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 271 | 11 |  |             Cases::VINIT => $prefix.$vowel.($animateness ? 'х' : 'е'), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 272 | 11 |  |             Cases::TVORIT => $prefix.$vowel.'ми', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 273 | 11 |  |             Cases::PREDLOJ => $prefix.$vowel.'х', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 274 |  |  |         ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 275 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 276 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 277 |  |  |  | 
            
                        
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.