Behavior::canGetProperty()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 2
eloc 2
nc 2
nop 2
crap 2
1
<?php
2
/**
3
 * @link https://github.com/yiiviet/yii2-payment
4
 * @copyright Copyright (c) 2017 Yii Viet
5
 * @license [New BSD License](http://www.opensource.org/licenses/bsd-license.php)
6
 */
7
8
namespace yiiviet\n2w;
9
10
use yii\base\Behavior as BaseBehavior;
11
use yii\base\InvalidConfigException;
12
13
/**
14
 * Lớp Behavior hổ trợ chuyển đổi giá trị các thuộc tính là số sang chữ số đối với các lớp thuộc `Component`.
15
 *
16
 * Ví dụ:
17
 *
18
 * ```php
19
 *
20
 * class MyComponent extends Component {
21
 *
22
 *      public $money = '100';
23
 *
24
 *      public function behaviors() {
25
 *          return [
26
 *              'class' => 'yiiviet\n2w\Behavior',
27
 *              'property' => 'money',
28
 *              'unit' => 'đồng'
29
 *          ];
30
 *      }
31
 *
32
 * }
33
 *
34
 * $component = new MyComponent;
35
 * $component->moneyFormat; // Một trăm đồng
36
 *
37
 * ```
38
 *
39
 *
40
 * @author Vuong Minh <[email protected]>
41
 * @since 1.0
42
 */
43
class Behavior extends BaseBehavior
44
{
45
46
    const DICTIONARY = [
47
        0 => 'không',
48
        1 => 'một',
49
        2 => 'hai',
50
        3 => 'ba',
51
        4 => 'bốn',
52
        5 => 'năm',
53
        6 => 'sáu',
54
        7 => 'bảy',
55
        8 => 'tám',
56
        9 => 'chín',
57
        10 => 'mười',
58
        11 => 'mười một',
59
        12 => 'mười hai',
60
        13 => 'mười ba',
61
        14 => 'mười bốn',
62
        15 => 'mười năm',
63
        16 => 'mười sáu',
64
        17 => 'mười bảy',
65
        18 => 'mười tám',
66
        19 => 'mười chín',
67
        20 => 'hai mươi',
68
        30 => 'ba mươi',
69
        40 => 'bốn mươi',
70
        50 => 'năm mươi',
71
        60 => 'sáu mươi',
72
        70 => 'bảy mươi',
73
        80 => 'tám mươi',
74
        90 => 'chín mươi',
75
        100 => 'trăm',
76
        1000 => 'ngàn',
77
        1000000 => 'triệu',
78
        1000000000 => 'tỷ',
79
        1000000000000 => 'nghìn tỷ',
80
        1000000000000000 => 'ngàn triệu triệu',
81
        1000000000000000000 => 'tỷ tỷ'
82
    ];
83
84
    const SEPARATOR = ' ';
85
86
    const HYPHEN = ' ';
87
88
    const CONJUNCTION = ' ';
89
90
    const NEGATIVE = 'Âm ';
91
92
    const DECIMAL = ' phẩy ';
93
94
    /**
95
     * @var string đơn vị sau khi chuyển đổi số sang chữ số.
96
     * Ví dụ: đồng, cái, kg, tấn, tạ, yến...
97
     */
98
    public $unit = '';
99
100
    /**
101
     * @var string Suffix dùng để tạo ra property đã chuyển đối số sang chữ số.
102
     * Ví dụ property là `money` để show dưới dạng chữ số sẽ là `moneyFormat`.
103
     */
104
    public $suffix = 'Format';
105
106
    /**
107
     * @var string Thuộc tính cần hổ trợ chuyển giá trị số thành chữ số.
108
     */
109
    public $property;
110
111
    /**
112
     * @var array Danh sách thuộc tính cần hổ trợ chuyển giá trị số thành chữ số.
113
     */
114
    public $properties = [];
115
116
    /**
117
     * @var array Danh sách thuộc tính `magic getter` map với thuộc tính của `owner` cần hổ trợ chuyển đổi.
118
     */
119
    protected $propertiesFormatted = [];
120
121
    /**
122
     * @inheritdoc
123
     * @throws InvalidConfigException
124
     */
125 10
    public function init()
126
    {
127 10
        $this->properties = array_merge((array)$this->property, $this->properties);
128
129 10
        if (empty($this->properties)) {
130
            throw new InvalidConfigException('Property need to format must be set!');
131
        } else {
132 10
            foreach ($this->properties as $property) {
133 10
                $this->propertiesFormatted[$property . $this->suffix] = $property;
134
            }
135
        }
136
137 10
        parent::init();
138 10
    }
139
140
    /**
141
     * @inheritdoc
142
     */
143 10
    public function canGetProperty($name, $checkVars = true)
144
    {
145 10
        return parent::canGetProperty($name, $checkVars) || array_key_exists($name, $this->propertiesFormatted);
146
    }
147
148
    /**
149
     * @inheritdoc
150
     * @throws InvalidConfigException
151
     */
152 10
    public function __get($name)
153
    {
154 10
        if (isset($this->propertiesFormatted[$name])) {
155 10
            $property = $this->propertiesFormatted[$name];
156
157 10
            if ($result = $this->n2w($this->owner->{$property})) {
158 10
                $result .= (! empty($this->unit) ? " {$this->unit}" : '');
159
            }
160
161 10
            return $result;
162
        } else {
163
            return parent::__get($name);
164
        }
165
    }
166
167
    /**
168
     * Phương thức chuyển đổi số thành chữ số.
169
     * Nó được trích từ: https://developers.mynukeviet.net/code/Ham-PHP-chuyen-doi-chu-so-ra-chu-44/
170
     *
171
     * @param mixed $number Số cần chuyển sang chữ.
172
     * @param bool $ucfirst Thiết lập nếu như bạn muốn tự động viết hoa chữ cái đầu.
173
     * @return bool|string Trả về false
174
     * @throws InvalidConfigException
175
     */
176 10
    protected function n2w($number, $ucfirst = true)
177
    {
178 10
        if (! is_numeric($number)) {
179 10
            return false;
180
        }
181
182 10
        if (($number >= 0 && (int)$number < 0) || (int)$number < 0 - PHP_INT_MAX) {
183
            throw new InvalidConfigException('Only accepts numbers between -' . PHP_INT_MAX . ' and ' . PHP_INT_MAX);
184 10
        } elseif ($number < 0) {
185 1
            return self::NEGATIVE . $this->n2w(abs($number), false);
186
        }
187
188 10
        $fraction = null;
189
190 10
        if (strpos($number, '.') !== false) {
191
            list($number, $fraction) = explode('.', $number);
192
        }
193
194
        switch (true) {
195 10
            case $number < 21:
196 5
                $string = self::DICTIONARY[$number];
197 5
                break;
198 7
            case $number < 100:
199 4
                $tens = ((int)($number / 10)) * 10;
200 4
                $units = $number % 10;
201 4
                $string = self::DICTIONARY[$tens];
202 4
                if ($units) {
203 4
                    $string .= self::HYPHEN . self::DICTIONARY[$units];
204
                }
205 4
                break;
206 6
            case $number < 1000:
207 4
                $hundreds = $number / 100;
208 4
                $remainder = $number % 100;
209 4
                $string = self::DICTIONARY[$hundreds] . ' ' . self::DICTIONARY[100];
210 4
                if ($remainder) {
211 2
                    $string .= self::CONJUNCTION . $this->n2w($remainder, $ucfirst);
212
                }
213 4
                break;
214
            default:
215 5
                $baseUnit = pow(1000, floor(log($number, 1000)));
216 5
                $numBaseUnits = (int)($number / $baseUnit);
217 5
                $remainder = $number % $baseUnit;
218 5
                $string = $this->n2w($numBaseUnits, $ucfirst) . ' ' . self::DICTIONARY[$baseUnit];
219 5
                if ($remainder) {
220 3
                    $string .= $remainder < 100 ? self::CONJUNCTION : self::SEPARATOR;
221 3
                    $string .= $this->n2w($remainder, $ucfirst);
222
                }
223 5
                break;
224
        }
225
226 10
        if (null !== $fraction && is_numeric($fraction)) {
227
            $string .= self::DECIMAL;
228
            $words = [];
229
            foreach (str_split((string)$fraction) as $number) {
230
                $words[] = self::DICTIONARY[$number];
231
            }
232
            $string .= implode(' ', $words);
233
        }
234
235 10
        if ($ucfirst) {
236 9
            return ucfirst(mb_strtolower($string, 'utf8'));
237
        } else {
238 1
            return $string;
239
        }
240
    }
241
242
243
}
244