| Total Complexity | 56 |
| Total Lines | 265 |
| Duplicated Lines | 0 % |
| Changes | 3 | ||
| Bugs | 1 | Features | 0 |
Complex classes like Convert often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Convert, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 22 | class Convert |
||
| 23 | { |
||
| 24 | const SIMPLE_DIC = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']; |
||
| 25 | const SIMPLE_SPEC_DIC = ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']; |
||
| 26 | const UPPER_DIC = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '镹', '拾']; |
||
| 27 | const SIMPLE_UNIT_DIC = ['无量大数', '万', '亿', '兆', '京', '垓', '秭', '穰', '沟', '涧', '正', '载', '极', '恒河沙', '阿僧祇', '那由他', '不可思议']; |
||
| 28 | const TRADITION_UNIT_DIC = ['無量大數', '萬', '億', '兆', '京', '垓', '秭', '穰', '溝', '澗', '正', '載', '極', '恆河沙', '阿僧祇', '那由他', '不可思議']; |
||
| 29 | const EXTENSION = ['bcmath', 'mbstring']; |
||
| 30 | |||
| 31 | public $dic; |
||
| 32 | public $unit_dic; |
||
| 33 | public $type; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * @throws ExtensionException |
||
| 37 | */ |
||
| 38 | public function __construct() |
||
| 45 | } |
||
| 46 | |||
| 47 | /** |
||
| 48 | * Check php extension. |
||
| 49 | * |
||
| 50 | * @param array $extensions |
||
| 51 | * |
||
| 52 | * @throws ExtensionException |
||
| 53 | */ |
||
| 54 | public function extensionException($extensions) |
||
| 55 | { |
||
| 56 | foreach ($extensions as $name => $state) { |
||
| 57 | if (false === $state) { |
||
| 58 | throw new ExtensionException('Disabled extension '.$name); |
||
| 59 | } |
||
| 60 | } |
||
| 61 | } |
||
| 62 | |||
| 63 | /** |
||
| 64 | * Convert numbers into Chinese numbers. |
||
| 65 | * |
||
| 66 | * @param int $number |
||
| 67 | * @param int $character |
||
| 68 | * @param int $unit |
||
| 69 | * |
||
| 70 | * @return string |
||
| 71 | * |
||
| 72 | * @throws InvalidArgumentException |
||
| 73 | * @throws DictionarySetException |
||
| 74 | * @throws TypeSetException |
||
| 75 | */ |
||
| 76 | public function convertNumbers($number, $character = 1, $unit = 1) |
||
| 77 | { |
||
| 78 | $number = $this->formatNumber($number); |
||
| 79 | $this->selectDictionaries($character, $unit); |
||
| 80 | if ('float' == $this->type) { |
||
| 81 | $number_arr = \explode('.', $number); |
||
| 82 | $integer_part = $this->convertInteger($number_arr[0]); |
||
| 83 | $decimal_part = $this->convertDecimal($number_arr[1]); |
||
| 84 | |||
| 85 | return $integer_part.'点'.$decimal_part; |
||
| 86 | } elseif ('int' == $this->type) { |
||
| 87 | return $this->convertInteger($number); |
||
| 88 | } else { |
||
| 89 | throw new TypeSetException('Invalid type set'); |
||
| 90 | } |
||
| 91 | } |
||
| 92 | |||
| 93 | /** |
||
| 94 | * Replace Chinese characters string. |
||
| 95 | * |
||
| 96 | * @param string $string |
||
| 97 | * @param string $replacement |
||
| 98 | * @param int $start |
||
| 99 | * @param int $length |
||
| 100 | * @param string $encoding |
||
| 101 | * |
||
| 102 | * @return string |
||
| 103 | */ |
||
| 104 | public function mbSubStrReplace($string, $replacement, $start, $length = null, $encoding = null) |
||
| 125 | } |
||
| 126 | |||
| 127 | /** |
||
| 128 | * Select character dictionary and unit dictionary. |
||
| 129 | * |
||
| 130 | * @param int $character |
||
| 131 | * @param int $unit |
||
| 132 | * |
||
| 133 | * @throws DictionarySetException |
||
| 134 | */ |
||
| 135 | public function selectDictionaries($character, $unit) |
||
| 162 | } |
||
| 163 | |||
| 164 | /** |
||
| 165 | * Check input data and format data into usable numbers. |
||
| 166 | * |
||
| 167 | * @param $number |
||
| 168 | * |
||
| 169 | * @return string |
||
| 170 | * |
||
| 171 | * @throws InvalidArgumentException |
||
| 172 | */ |
||
| 173 | public function formatNumber($number) |
||
| 174 | { |
||
| 175 | if (!\is_string($number)) { |
||
| 176 | throw new InvalidArgumentException('Invalid number type, must be a string'); |
||
| 177 | } |
||
| 178 | $number = \trim(\str_replace(' ', '', $number), ' \t\n\r'); |
||
| 179 | if ($number !== 0) { |
||
| 180 | $number = \ltrim($number,'\0\x0B'); |
||
| 181 | } |
||
| 182 | $pos_dot = \strpos($number, '.'); |
||
| 183 | if (false !== $pos_dot) { |
||
| 184 | if (0 === $pos_dot) { |
||
| 185 | $number = '0'.$number; |
||
| 186 | } |
||
| 187 | $number = \rtrim(\rtrim($number, '0'), '.'); |
||
| 188 | } |
||
| 189 | if (0 === \preg_match('/^\d+(\.{0,1}\d+){0,1}$/', $number)) { |
||
| 190 | throw new InvalidArgumentException('Invalid value number: '.$number); |
||
| 191 | } |
||
| 192 | if (false === \strpos($number, '.')) { |
||
| 193 | $this->type = 'int'; |
||
| 194 | } else { |
||
| 195 | $this->type = 'float'; |
||
| 196 | } |
||
| 197 | |||
| 198 | return $number; |
||
| 199 | } |
||
| 200 | |||
| 201 | /** |
||
| 202 | * Convert integer part. |
||
| 203 | * |
||
| 204 | * @param $integer |
||
| 205 | * |
||
| 206 | * @return string |
||
| 207 | * |
||
| 208 | * @throws DictionarySetException |
||
| 209 | */ |
||
| 210 | public function convertInteger($integer) |
||
| 211 | { |
||
| 212 | if (empty($this->dic)) { |
||
| 213 | throw new DictionarySetException('Dictionary is not set'); |
||
| 214 | } |
||
| 215 | if (empty($this->unit_dic)) { |
||
| 216 | throw new DictionarySetException('Unit dictionary is not set'); |
||
| 217 | } |
||
| 218 | $num_arr_chunk = \array_chunk(\array_reverse(\str_split($integer)), 68); |
||
|
|
|||
| 219 | $complete_str = ''; |
||
| 220 | foreach ($num_arr_chunk as $cycle => $num_arr) { |
||
| 221 | $length = \count($num_arr); |
||
| 222 | $match_unit_digits = 0 == $length % 4 ? \bcdiv($length, 4) : \bcdiv($length, 4) + 1; |
||
| 223 | $chunk_unit_dic = \array_slice($this->unit_dic, 0, $match_unit_digits); |
||
| 224 | if (0 == $cycle) { |
||
| 225 | $chunk_unit_dic[0] = ''; |
||
| 226 | } |
||
| 227 | for ($a = 0; $a < $match_unit_digits; ++$a) { |
||
| 228 | if ($this->dic == $this::UPPER_DIC) { |
||
| 229 | \array_splice($chunk_unit_dic, $a * 4 + 1, 0, ['拾', '百', '千']); |
||
| 230 | } else { |
||
| 231 | \array_splice($chunk_unit_dic, $a * 4 + 1, 0, ['十', '百', '千']); |
||
| 232 | } |
||
| 233 | } |
||
| 234 | $chinese_num = ''; |
||
| 235 | foreach ($num_arr as $key => $value) { |
||
| 236 | if (0 == $key % 4) { |
||
| 237 | if ($key > 4 && $chunk_unit_dic[$key - 4] == \mb_substr($chinese_num, 0, 1)) { |
||
| 238 | $chinese_num = $this->mbSubStrReplace($chinese_num, '', 0, 1); |
||
| 239 | if (\mb_substr($chinese_num, 0, 1) != $this->dic[0]) { |
||
| 240 | $chinese_num = $this->dic[0].$chinese_num; |
||
| 241 | } |
||
| 242 | } |
||
| 243 | $chinese_num = (0 == $value && 1 != $length ? '' : $this->dic[$value]).$chunk_unit_dic[$key].$chinese_num; |
||
| 244 | } else { |
||
| 245 | if (0 == $value && '' == $chinese_num) { |
||
| 246 | continue; |
||
| 247 | } elseif (0 == $value && '' != $chinese_num) { |
||
| 248 | if (0 != $num_arr[$key - 1]) { |
||
| 249 | $chinese_num = $this->dic[0].$chinese_num; |
||
| 250 | } |
||
| 251 | } else { |
||
| 252 | if (1 == $value && 2 == $length % 4 && $length == $key + 1) { |
||
| 253 | $chinese_num = $chunk_unit_dic[$key].$chinese_num; |
||
| 254 | } else { |
||
| 255 | $chinese_num = $this->dic[$value].$chunk_unit_dic[$key].$chinese_num; |
||
| 256 | } |
||
| 257 | } |
||
| 258 | } |
||
| 259 | } |
||
| 260 | $complete_str = $chinese_num.$complete_str; |
||
| 261 | } |
||
| 262 | |||
| 263 | return $complete_str; |
||
| 264 | } |
||
| 265 | |||
| 266 | /** |
||
| 267 | * Convert decimal part. |
||
| 268 | * |
||
| 269 | * @param $decimal |
||
| 270 | * |
||
| 271 | * @return string |
||
| 272 | * |
||
| 273 | * @throws DictionarySetException |
||
| 274 | */ |
||
| 275 | public function convertDecimal($decimal) |
||
| 287 | } |
||
| 288 | } |
||
| 289 |