Completed
Push — master ( 075722...9e15a4 )
by f
01:43
created

src/Russian/CardinalNumber.php (1 issue)

Labels

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace morphos\Russian;
3
4
use morphos\NumberCreation;
5
6
/**
7
 * Rules are from http://www.fio.ru/pravila/grammatika/sklonenie-imen-chislitelnykh/
8
 */
9
class CardinalNumber extends NumberCreation implements Cases {
10
    use RussianLanguage;
11
12
    protected $words = array(
13
        1 => 'один',
14
        2 => 'два',
15
        3 => 'три',
16
        4 => 'четыре',
17
        5 => 'пять',
18
        6 => 'шесть',
19
        7 => 'семь',
20
        8 => 'восемь',
21
        9 => 'девять',
22
        10 => 'десять',
23
        11 => 'одиннадцать',
24
        12 => 'двенадцать',
25
        13 => 'тринадцать',
26
        14 => 'четырнадцать',
27
        15 => 'пятнадцать',
28
        16 => 'шестнадцать',
29
        17 => 'семнадцать',
30
        18 => 'восемнадцать',
31
        19 => 'девятнадцать',
32
        20 => 'двадцать',
33
        30 => 'тридцать',
34
        40 => 'сорок',
35
        50 => 'пятьдесят',
36
        60 => 'шестьдесят',
37
        70 => 'семьдесят',
38
        80 => 'восемьдесят',
39
        90 => 'девяносто',
40
        100 => 'сто',
41
        200 => 'двести',
42
        300 => 'триста',
43
        400 => 'четыреста',
44
        500 => 'пятьсот',
45
        600 => 'шестьсот',
46
        700 => 'семьсот',
47
        800 => 'восемьсот',
48
        900 => 'девятьсот',
49
    );
50
51
    protected $exponents = array(
52
        1000 => 'тысяча',
53
        1000000 => 'миллион',
54
        1000000000 => 'миллиард',
55
    );
56
57
    protected $declension;
58
    protected $plurality;
59
60
    protected $precalculated = array(
61
        'один' => array(
62
            self::IMENIT => 'один',
63
            self::RODIT => 'одного',
64
            self::DAT => 'одному',
65
            self::VINIT => 'один',
66
            self::TVORIT => 'одним',
67
            self::PREDLOJ => 'об одном',
68
        ),
69
        'два' => array(
70
            self::IMENIT => 'два',
71
            self::RODIT => 'двух',
72
            self::DAT => 'двум',
73
            self::VINIT => 'два',
74
            self::TVORIT => 'двумя',
75
            self::PREDLOJ => 'о двух',
76
        ),
77
        'три' => array(
78
            self::IMENIT => 'три',
79
            self::RODIT => 'трех',
80
            self::DAT => 'трем',
81
            self::VINIT => 'три',
82
            self::TVORIT => 'тремя',
83
            self::PREDLOJ => 'о трех',
84
        ),
85
        'четыре' => array(
86
            self::IMENIT => 'четыре',
87
            self::RODIT => 'четырех',
88
            self::DAT => 'четырем',
89
            self::VINIT => 'четыре',
90
            self::TVORIT => 'четырьмя',
91
            self::PREDLOJ => 'о четырех',
92
        ),
93
        'двести' => array(
94
            self::IMENIT => 'двести',
95
            self::RODIT => 'двухсот',
96
            self::DAT => 'двумстам',
97
            self::VINIT => 'двести',
98
            self::TVORIT => 'двумястами',
99
            self::PREDLOJ => 'о двухстах',
100
        ),
101
        'восемьсот' => array(
102
            self::IMENIT => 'восемьсот',
103
            self::RODIT => 'восьмисот',
104
            self::DAT => 'восьмистам',
105
            self::VINIT => 'восемьсот',
106
            self::TVORIT => 'восьмистами',
107
            self::PREDLOJ => 'о восьмистах',
108
        ),
109
        'тысяча' => array(
110
            self::IMENIT => 'тысяча',
111
            self::RODIT => 'тысяч',
112
            self::DAT => 'тысячам',
113
            self::VINIT => 'тысяч',
114
            self::TVORIT => 'тысячей',
115
            self::PREDLOJ => 'о тысячах',
116
        ),
117
    );
118
119
    public function getForms($number) {
120
        // simple numeral
121
        if (isset($this->words[$number]) || isset($this->exponents[$number])) {
122
            $word = isset($this->words[$number]) ? $this->words[$number] : $this->exponents[$number];
123
            if (isset($this->precalculated[$word])) {
124
                return $this->precalculated[$word];
125
            } else if (($number >= 5 && $number <= 20) || $number == 30) {
126
                $prefix = slice($word, 0, -1);
127
                return array(
128
                    self::IMENIT => $word,
129
                    self::RODIT => $prefix.'и',
130
                    self::DAT => $prefix.'и',
131
                    self::VINIT => $word,
132
                    self::TVORIT => $prefix.'ью',
133
                    self::PREDLOJ => $this->choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'и',
134
                );
135
            } else if (in_array($number, array(40, 90, 100))) {
136
                $prefix = $number == 40 ? $word : slice($word, 0, -1);
137
                return array(
138
                    self::IMENIT => $word,
139
                    self::RODIT => $prefix.'а',
140
                    self::DAT => $prefix.'а',
141
                    self::VINIT => $word,
142
                    self::TVORIT => $prefix.'а',
143
                    self::PREDLOJ => $this->choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'а',
144
                );
145
            } else if (($number >= 50 && $number <= 80)) {
146
                $prefix = slice($word, 0, -6);
147
                return array(
148
                    self::IMENIT => $prefix.'ьдесят',
149
                    self::RODIT => $prefix.'идесяти',
150
                    self::DAT => $prefix.'идесяти',
151
                    self::VINIT => $prefix.'ьдесят',
152
                    self::TVORIT => $prefix.'ьюдесятью',
153
                    self::PREDLOJ => $this->choosePrepositionByFirstLetter($word, 'об', 'о').' '.$prefix.'идесяти',
154
                );
155
            } else if (in_array($number, array(300, 400))) {
156
                $prefix = slice($word, 0, -4);
157
                return array(
158
                    self::IMENIT => $word,
159
                    self::RODIT => $prefix.'ехсот',
160
                    self::DAT => $prefix.'емстам',
161
                    self::VINIT => $word,
162
                    self::TVORIT => $prefix.($number == 300 ? 'е' : 'ь').'мястами',
163
                    self::PREDLOJ => $this->choosePrepositionByFirstLetter($word, 'об', 'о').' '.$prefix.'ехстах',
164
                );
165
            } else if ($number >= 500 && $number <= 900) {
166
                $prefix = slice($word, 0, -4);
167
                return array(
168
                    self::IMENIT => $word,
169
                    self::RODIT => $prefix.'исот',
170
                    self::DAT => $prefix.'истам',
171
                    self::VINIT => $word,
172
                    self::TVORIT => $prefix.'ьюстами',
173
                    self::PREDLOJ => $this->choosePrepositionByFirstLetter($word, 'об', 'о').' '.$prefix.'истах',
174
                );
175
            }
176
        }
177
        // compound numeral
178
        else {
179
            $parts = array();
180
            $result = array();
181
182
            foreach (array_reverse($this->exponents, true) as $word_number => $word) {
183
                if ($number >= $word_number) {
184
                    $count = floor($number / $word_number);
185
                    $parts[] = $this->getForms($count);
186
187
                    // get forms of word
188
                    if (empty($this->declension)) $this->declension = new GeneralDeclension();
189
                    if (empty($this->plurality)) $this->plurality = new Plurality();
190
191
                    switch (Plurality::getNumeralForm($count)) {
192
                        case Plurality::ONE:
193
                            $parts[] = $this->declension->getForms($word, false);
194
                            break;
195 View Code Duplication
                        case Plurality::TWO_FOUR:
196
                            $part = $this->plurality->getForms($word);
197
                            if ($word_number != 1000) // get dative case of word for 1000000 and 1000000000
198
                                $part[Cases::IMENIT] = $part[Cases::VINIT] = $this->declension->getForm($word, Cases::RODIT);
199
                            $parts[] = $part;
200
                            break;
201 View Code Duplication
                        case Plurality::FIVE_OTHER:
202
                            $part = $this->plurality->getForms($word);
203
                            $part[Cases::IMENIT] = $part[Cases::VINIT] = $part[Cases::RODIT];
204
                            $parts[] = $part;
205
                            break;
206
                    }
207
208
                    $number = $number % ($count * $word_number);
209
                }
210
            }
211
212
            foreach (array_reverse($this->words, true) as $word_number => $word) {
213
                if ($number >= $word_number) {
214
                    $parts[] = $this->getForms($word_number);
215
                    $number %= $word_number;
216
                }
217
            }
218
219 View Code Duplication
            foreach (array(self::IMENIT, self::RODIT, self::DAT, self::VINIT, self::TVORIT, self::PREDLOJ) as $case) {
220
                $result[$case] = array();
221
                foreach ($parts as $partN => $part) {
222
                    if ($case == self::PREDLOJ && $partN > 0) list(, $part[$case]) = explode(' ', $part[$case], 2);
223
                    $result[$case][] = $part[$case];
224
                }
225
                $result[$case] = implode(' ', $result[$case]);
226
            }
227
228
            return $result;
229
        }
230
    }
231
232
    public function getForm($number, $form) {
233
        $forms = $this->getForms($name);
0 ignored issues
show
The variable $name does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
234
        return $forms[$form];
235
    }
236
}
237