dolibarr  20.0.0-beta
functionsnumtoword.lib.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2015 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2015 Víctor Ortiz Pérez <victor@accett.com.mx>
4  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  * or see https://www.gnu.org/
19  */
20 
37 function dol_convertToWord($num, $langs, $currency = '', $centimes = false)
38 {
39  global $conf;
40 
41  //$num = str_replace(array(',', ' '), '', trim($num)); This should be useless since $num MUST be a php numeric value
42  if (!$num) {
43  return false;
44  }
45 
46  if ($centimes && strlen((string) $num) == 1) {
47  $num = $num * 10;
48  }
49 
50  if (isModEnabled('numberwords')) {
51  if ($currency) {
52  $type = '1';
53  } else {
54  $type = '0';
55  }
56 
57  $concatWords = $langs->getLabelFromNumber($num, $type);
58  return $concatWords;
59  } else {
60  $TNum = explode('.', (string) $num);
61 
62  $num = (int) $TNum[0];
63  $words = array();
64  $list1 = array(
65  '',
66  $langs->transnoentitiesnoconv('one'),
67  $langs->transnoentitiesnoconv('two'),
68  $langs->transnoentitiesnoconv('three'),
69  $langs->transnoentitiesnoconv('four'),
70  $langs->transnoentitiesnoconv('five'),
71  $langs->transnoentitiesnoconv('six'),
72  $langs->transnoentitiesnoconv('seven'),
73  $langs->transnoentitiesnoconv('eight'),
74  $langs->transnoentitiesnoconv('nine'),
75  $langs->transnoentitiesnoconv('ten'),
76  $langs->transnoentitiesnoconv('eleven'),
77  $langs->transnoentitiesnoconv('twelve'),
78  $langs->transnoentitiesnoconv('thirteen'),
79  $langs->transnoentitiesnoconv('fourteen'),
80  $langs->transnoentitiesnoconv('fifteen'),
81  $langs->transnoentitiesnoconv('sixteen'),
82  $langs->transnoentitiesnoconv('seventeen'),
83  $langs->transnoentitiesnoconv('eighteen'),
84  $langs->transnoentitiesnoconv('nineteen')
85  );
86  $list2 = array(
87  '',
88  $langs->transnoentitiesnoconv('ten'),
89  $langs->transnoentitiesnoconv('twenty'),
90  $langs->transnoentitiesnoconv('thirty'),
91  $langs->transnoentitiesnoconv('forty'),
92  $langs->transnoentitiesnoconv('fifty'),
93  $langs->transnoentitiesnoconv('sixty'),
94  $langs->transnoentitiesnoconv('seventy'),
95  $langs->transnoentitiesnoconv('eighty'),
96  $langs->transnoentitiesnoconv('ninety'),
97  $langs->transnoentitiesnoconv('hundred')
98  );
99  $list3 = array(
100  '',
101  $langs->transnoentitiesnoconv('thousand'),
102  $langs->transnoentitiesnoconv('million'),
103  $langs->transnoentitiesnoconv('billion'),
104  $langs->transnoentitiesnoconv('trillion'),
105  $langs->transnoentitiesnoconv('quadrillion')
106  );
107 
108  $num_length = strlen((string) $num);
109  $levels = (int) (($num_length + 2) / 3);
110  $max_length = $levels * 3;
111  $num = substr('00'.$num, -$max_length);
112  $num_levels = str_split($num, 3);
113  $nboflevels = count($num_levels);
114  for ($i = 0; $i < $nboflevels; $i++) {
115  $levels--;
116  $hundreds = (int) ($num_levels[$i] / 100);
117  $hundreds = ($hundreds ? ' '.$list1[$hundreds].' '.$langs->transnoentities('hundred').($hundreds == 1 ? '' : 's').' ' : '');
118  $tens = (int) ($num_levels[$i] % 100);
119  $singles = '';
120  if ($tens < 20) {
121  $tens = ($tens ? ' '.$list1[$tens].' ' : '');
122  } else {
123  $tens = (int) ($tens / 10);
124  $tens = ' '.$list2[$tens].' ';
125  $singles = (int) ($num_levels[$i] % 10);
126  $singles = ' '.$list1[$singles].' ';
127  }
128  $words[] = $hundreds.$tens.$singles.(($levels && (int) ($num_levels[$i])) ? ' '.$list3[$levels].' ' : '');
129  } //end for loop
130  $commas = count($words);
131  if ($commas > 1) {
132  $commas = $commas - 1;
133  }
134  $concatWords = implode(' ', $words);
135  // Delete multi whitespaces
136  $concatWords = trim(preg_replace('/[ ]+/', ' ', $concatWords));
137 
138  if (!empty($currency)) {
139  $concatWords .= ' '.$currency;
140  }
141 
142  // If we need to write cents call again this function for cents
143  $decimalpart = empty($TNum[1]) ? '' : preg_replace('/0+$/', '', $TNum[1]);
144 
145  if ($decimalpart) {
146  if (!empty($currency)) {
147  $concatWords .= ' '.$langs->transnoentities('and');
148  }
149 
150  $concatWords .= ' '.dol_convertToWord($decimalpart, $langs, '', true);
151  if (!empty($currency)) {
152  $concatWords .= ' '.$langs->transnoentities('centimes');
153  }
154  }
155  return $concatWords;
156  }
157 }
158 
159 
169 function dolNumberToWord($numero, $langs, $numorcurrency = 'number')
170 {
171  // If the number is negative convert to positive and return -1 if it is too long
172  if ($numero < 0) {
173  $numero *= -1;
174  }
175  if ($numero >= 1000000000001) {
176  return -1;
177  }
178 
179  // Get 2 decimals to cents, another functions round or truncate
180  $strnumber = number_format($numero, 10);
181  $len = strlen($strnumber);
182  for ($i = 0; $i < $len; $i++) {
183  if ($strnumber[$i] == '.') {
184  $parte_decimal = $strnumber[$i + 1].$strnumber[$i + 2];
185  break;
186  }
187  }
188 
189  /*In dolibarr 3.6.2 (my current version) doesn't have $langs->default and
190  in case exist why ask $lang like a parameter?*/
191  if (((is_object($langs) && $langs->getDefaultLang(0) == 'es_MX') || (!is_object($langs) && $langs == 'es_MX')) && $numorcurrency == 'currency') {
192  if ($numero >= 1 && $numero < 2) {
193  return ("UN PESO ".$parte_decimal." / 100 M.N.");
194  } elseif ($numero >= 0 && $numero < 1) {
195  return ("CERO PESOS ".$parte_decimal." / 100 M.N.");
196  } elseif ($numero >= 1000000 && $numero < 1000001) {
197  return ("UN MILL&OacuteN DE PESOS ".$parte_decimal." / 100 M.N.");
198  } elseif ($numero >= 1000000000000 && $numero < 1000000000001) {
199  return ("UN BILL&OacuteN DE PESOS ".$parte_decimal." / 100 M.N.");
200  } else {
201  $entexto = "";
202  $number = $numero;
203  if ($number >= 1000000000) {
204  $CdMMillon = (int) ($numero / 100000000000);
205  $numero = $numero - $CdMMillon * 100000000000;
206  $DdMMillon = (int) ($numero / 10000000000);
207  $numero = $numero - $DdMMillon * 10000000000;
208  $UdMMillon = (int) ($numero / 1000000000);
209  $numero = $numero - $UdMMillon * 1000000000;
210  $entexto .= hundreds2text($CdMMillon, $DdMMillon, $UdMMillon);
211  $entexto .= " MIL ";
212  }
213  if ($number >= 1000000) {
214  $CdMILLON = (int) ($numero / 100000000);
215  $numero = $numero - $CdMILLON * 100000000;
216  $DdMILLON = (int) ($numero / 10000000);
217  $numero = $numero - $DdMILLON * 10000000;
218  $udMILLON = (int) ($numero / 1000000);
219  $numero = $numero - $udMILLON * 1000000;
220  $entexto .= hundreds2text($CdMILLON, $DdMILLON, $udMILLON);
221  if (!$CdMMillon && !$DdMMillon && !$UdMMillon && !$CdMILLON && !$DdMILLON && $udMILLON == 1) {
222  $entexto .= " MILL&OacuteN ";
223  } else {
224  $entexto .= " MILLONES ";
225  }
226  }
227  if ($number >= 1000) {
228  $cdm = (int) ($numero / 100000);
229  $numero = $numero - $cdm * 100000;
230  $ddm = (int) ($numero / 10000);
231  $numero = $numero - $ddm * 10000;
232  $udm = (int) ($numero / 1000);
233  $numero = $numero - $udm * 1000;
234  $entexto .= hundreds2text($cdm, $ddm, $udm);
235  if ($cdm || $ddm || $udm) {
236  $entexto .= " MIL ";
237  }
238  }
239  $c = (int) ($numero / 100);
240  $numero = $numero - $c * 100;
241  $d = (int) ($numero / 10);
242  $u = (int) $numero - $d * 10;
243  $entexto .= hundreds2text($c, $d, $u);
244  if (!$cdm && !$ddm && !$udm && !$c && !$d && !$u && $number > 1000000) {
245  $entexto .= " DE";
246  }
247  $entexto .= " PESOS ".$parte_decimal." / 100 M.N.";
248  }
249  return $entexto;
250  }
251  return -1;
252 }
253 
262 function hundreds2text($hundreds, $tens, $units)
263 {
264  if ($hundreds == 1 && $tens == 0 && $units == 0) {
265  return "CIEN";
266  }
267  $centenas = array("CIENTO", "DOSCIENTOS", "TRESCIENTOS", "CUATROCIENTOS", "QUINIENTOS", "SEISCIENTOS", "SETECIENTOS", "OCHOCIENTOS", "NOVECIENTOS");
268  $decenas = array("", "", "TREINTA ", "CUARENTA ", "CINCUENTA ", "SESENTA ", "SETENTA ", "OCHENTA ", "NOVENTA ");
269  $veintis = array("VEINTE", "VEINTIUN", "VEINTID&OacuteS", "VEINTITR&EacuteS", "VEINTICUATRO", "VEINTICINCO", "VEINTIS&EacuteIS", "VEINTISIETE", "VEINTIOCHO", "VEINTINUEVE");
270  $diecis = array("DIEZ", "ONCE", "DOCE", "TRECE", "CATORCE", "QUINCE", "DIECIS&EacuteIS", "DIECISIETE", "DIECIOCHO", "DIECINUEVE");
271  $unidades = array("UN", "DOS", "TRES", "CUATRO", "CINCO", "SEIS", "SIETE", "OCHO", "NUEVE");
272  $entexto = "";
273  if ($hundreds != 0) {
274  $entexto .= $centenas[$hundreds - 1];
275  }
276  if ($tens > 2) {
277  if ($hundreds != 0) {
278  $entexto .= " ";
279  }
280  $entexto .= $decenas[$tens - 1];
281  if ($units != 0) {
282  $entexto .= " Y ";
283  $entexto .= $unidades[$units - 1];
284  }
285  return $entexto;
286  } elseif ($tens == 2) {
287  if ($hundreds != 0) {
288  $entexto .= " ";
289  }
290  $entexto .= " ".$veintis[$units];
291  return $entexto;
292  } elseif ($tens == 1) {
293  if ($hundreds != 0) {
294  $entexto .= " ";
295  }
296  $entexto .= $diecis[$units];
297  return $entexto;
298  }
299  if ($units != 0) {
300  if ($hundreds != 0 || $tens != 0) {
301  $entexto .= " ";
302  }
303  $entexto .= $unidades[$units - 1];
304  }
305  return $entexto;
306 }
isModEnabled($module)
Is Dolibarr module enabled.
dol_convertToWord($num, $langs, $currency='', $centimes=false)
Function to return a number into a text.
hundreds2text($hundreds, $tens, $units)
hundreds2text
dolNumberToWord($numero, $langs, $numorcurrency='number')
Function to return number or amount in text.