Passed
Push — master ( 63d1f8...7c50e7 )
by Joe Nilson
02:33
created

NumberToLetterConverter::convertNumber()   F

Complexity

Conditions 17
Paths 594

Size

Total Lines 61
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 17
eloc 36
c 1
b 0
f 0
nc 594
nop 3
dl 0
loc 61
rs 1.6137

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * Copyright (C) 2021 Joe Nilson <[email protected]>
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU Lesser General Public License as
7
 * published by the Free Software Foundation, either version 3 of the
8
 * License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU Lesser General Public License for more details.
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
/**
19
 * Clase que implementa un conversor de números a letras.
20
 * @author AxiaCore S.A.S
21
 * https://github.com/axiacore/number-to-letter-php
22
 */
23
class NumberToLetterConverter
24
{
25
    private $UNIDADES = array(
26
        '',
27
        'UN ',
28
        'DOS ',
29
        'TRES ',
30
        'CUATRO ',
31
        'CINCO ',
32
        'SEIS ',
33
        'SIETE ',
34
        'OCHO ',
35
        'NUEVE ',
36
        'DIEZ ',
37
        'ONCE ',
38
        'DOCE ',
39
        'TRECE ',
40
        'CATORCE ',
41
        'QUINCE ',
42
        'DIECISEIS ',
43
        'DIECISIETE ',
44
        'DIECIOCHO ',
45
        'DIECINUEVE ',
46
        'VEINTE '
47
    );
48
49
    private $DECENAS = array(
50
        'VEINTI',
51
        'TREINTA ',
52
        'CUARENTA ',
53
        'CINCUENTA ',
54
        'SESENTA ',
55
        'SETENTA ',
56
        'OCHENTA ',
57
        'NOVENTA ',
58
        'CIEN '
59
    );
60
61
    private $CENTENAS = array(
62
        'CIENTO ',
63
        'DOSCIENTOS ',
64
        'TRESCIENTOS ',
65
        'CUATROCIENTOS ',
66
        'QUINIENTOS ',
67
        'SEISCIENTOS ',
68
        'SETECIENTOS ',
69
        'OCHOCIENTOS ',
70
        'NOVECIENTOS '
71
    );
72
73
    private $MONEDAS = [
74
        ['country' => 'Colombia', 'currency' => 'COP', 'singular' => 'PESO COLOMBIANO', 'plural' => 'PESOS COLOMBIANOS', 'symbol', '$'],
75
        ['country' => 'Estados Unidos', 'currency' => 'USD', 'singular' => 'DÓLAR', 'plural' => 'DÓLARES', 'symbol', 'US$'],
76
        ['country' => 'El Salvador', 'currency' => 'USD', 'singular' => 'DÓLAR', 'plural' => 'DÓLARES', 'symbol', 'US$'],
77
        ['country' => 'Europa', 'currency' => 'EUR', 'singular' => 'EURO', 'plural' => 'EUROS', 'symbol', '€'],
78
        ['country' => 'México', 'currency' => 'MXN', 'singular' => 'PESO MEXICANO', 'plural' => 'PESOS MEXICANOS', 'symbol', '$'],
79
        ['country' => 'Perú', 'currency' => 'PEN', 'singular' => 'NUEVO SOL', 'plural' => 'NUEVOS SOLES', 'symbol', 'S/'],
80
        ['country' => 'Reino Unido', 'currency' => 'GBP', 'singular' => 'LIBRA', 'plural' => 'LIBRAS', 'symbol', '£'],
81
        ['country' => 'Argentina', 'currency' => 'ARS', 'singular' => 'PESO', 'plural' => 'PESOS', 'symbol', '$'],
82
        ['country' => 'República Dominicana', 'currency' => 'DOP', 'singular' => 'PESO DOMINICANO', 'plural' => 'PESOS DOMINICANOS', 'symbol', 'RD$']
83
    ];
84
85
    private $separator = FS_NF2;
0 ignored issues
show
Bug introduced by
The constant FS_NF2 was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
86
    private $decimal_mark = FS_NF1;
0 ignored issues
show
Bug introduced by
The constant FS_NF1 was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
87
    private $glue = ' CON ';
88
89
    /**
90
     * Evalua si el número contiene separadores o decimales
91
     * formatea y ejecuta la función conversora
92
     * @param number $number número a convertir
93
     * @param string $miMoneda clave de la moneda
94
     * @return string completo
95
     */
96
    public function to_word($number, $miMoneda = null)
97
    {
98
        if (strpos($number, $this->decimal_mark) === false) {
99
            $convertedNumber = array(
100
                $this->convertNumber($number, $miMoneda, 'entero')
101
            );
102
        } else {
103
            $number = explode($this->decimal_mark, str_replace($this->separator, '', trim($number)));
104
105
            $convertedNumber = array(
106
                $this->convertNumber($number[0], $miMoneda, 'entero'),
0 ignored issues
show
Bug introduced by
$number[0] of type string is incompatible with the type double|integer expected by parameter $number of NumberToLetterConverter::convertNumber(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

106
                $this->convertNumber(/** @scrutinizer ignore-type */ $number[0], $miMoneda, 'entero'),
Loading history...
107
                $this->convertNumber($number[1], $miMoneda, 'decimal'),
108
            );
109
        }
110
        return implode($this->glue, array_filter($convertedNumber));
111
    }
112
113
    /**
114
     * Convierte número a letras
115
     * @param number $number
116
     * @param string $miMoneda
117
     * @param string $type tipo de dígito (entero/decimal)
118
     * @return string $converted string convertido
119
     */
120
    private function convertNumber($number, $miMoneda = null, string $type = 'entero')
121
    {
122
123
        $converted = '';
124
        $moneda = '';
125
        if ($miMoneda !== null) {
126
            try {
127
                $moneda = array_filter($this->MONEDAS, static function ($m) use ($miMoneda) {
128
                    return ($m['currency'] === $miMoneda);
129
                });
130
131
                $moneda = array_values($moneda);
132
133
                if (count($moneda) <= 0) {
134
                    throw new Exception("Tipo de moneda inválido");
135
                    //return;
136
                }
137
                ($number < 2 ? $moneda = $moneda[0]['singular'] : $moneda = $moneda[0]['plural']);
138
            } catch (Exception $e) {
139
                echo $e->getMessage();
140
                //return;
141
            }
142
        }
143
144
        if (($number < 0) || ($number > 999999999)) {
145
            return ($type === 'decimal')?' 00/100' : '';
146
        }
147
148
        $numberStr = (string) $number;
149
        $numberStrFill = str_pad($numberStr, 9, '0', STR_PAD_LEFT);
150
        $millones = substr($numberStrFill, 0, 3);
151
        $miles =  substr($numberStrFill, 3, 3);
152
        $cientos = substr($numberStrFill, 6);
153
154
        if ($millones > 0) {
155
            if ($millones === '001') {
156
                $converted .= 'UN MILLON ';
157
            } elseif ($millones > 0) {
158
                $converted .= sprintf('%sMILLONES ', $this->convertGroup($millones));
159
            }
160
        }
161
162
        if ($miles > 0) {
163
            if ($miles === '001') {
164
                $converted .= 'MIL ';
165
            } elseif ($miles > 0) {
166
                $converted .= sprintf('%sMIL ', $this->convertGroup($miles));
167
            }
168
        }
169
170
        if ($cientos > 0) {
171
            if ($cientos === '001') {
172
                $converted .= 'UN ';
173
            } elseif ($cientos > 0) {
174
                $converted .= sprintf('%s ', $this->convertGroup($cientos));
175
            }
176
        }
177
178
        $converted .= $moneda;
179
180
        return $converted;
181
    }
182
183
    /**
184
     * Define el tipo de representación decimal (centenas/millares/millones)
185
     * @param string $n
186
     * @return string $output
187
     */
188
    private function convertGroup($n)
189
    {
190
        $output = '';
191
192
        if ($n === '100') {
193
            $output = "CIEN ";
194
        } elseif ($n[0] !== '0') {
195
            $output = $this->CENTENAS[(int) $n[0] - 1];
196
        }
197
198
        $k = (int) substr($n, 1);
199
200
        if ($k <= 20) {
201
            $output .= $this->UNIDADES[$k];
202
        } elseif (($k > 30) && ($n[2] !== '0')) {
203
            $output .= sprintf('%sY %s', $this->DECENAS[(int)$n[1] - 2], $this->UNIDADES[(int)$n[2]]);
204
        } else {
205
            $output .= sprintf('%s%s', $this->DECENAS[(int)$n[1] - 2], $this->UNIDADES[(int)$n[2]]);
206
        }
207
        return $output;
208
    }
209
}