PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 1.5.21
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v1.5.21
2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 1.7.2 All 33 releases
fluent-booking / vendor / wpfluent / framework / src / WPFluent / Support / Number.php

Number.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 1.5.21, at vendor/wpfluent/framework/src/WPFluent/Support/Number.php

572 lines 13.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBooking\Framework\Support;
4
5 use RangeException;
6 use TypeError;
7
8 class Number
9 {
10 /**
11 * Format a number depending on the locale
12 *
13 * @param int|float $value
14 * @param integer $dec
15 * @return Formatted number
16 * @see https://developer.wordpress.org/reference/functions/number_format_i18n
17 */
18 public static function format($value, $dec = 0)
19 {
20 return number_format_i18n($value, $dec);
21 }
22
23 /**
24 * Format a number as int
25 *
26 * @param int|float $value
27 * @return int
28 */
29 public static function toInt($val)
30 {
31 return intval(static::format($val));
32 }
33
34 /**
35 * Format a number as float
36 *
37 * @param int|float $value
38 * @param integer $dec
39 * @return float
40 */
41 public static function toFloat($val, $dec = 2)
42 {
43 return static::format($val, $dec);
44 }
45
46 /**
47 * Convert a number to bool
48 *
49 * @param int $val
50 * @return bool
51 */
52 public static function toBool($val)
53 {
54 return boolval(intval($val));
55 }
56
57 /**
58 * Format a number to currency depending on the locale
59 *
60 * @param int|float $value
61 * @param array $before Options fpr formatting
62 * @return Formatted number with currency symbol
63 */
64 public static function toCurrency($value, $options = [])
65 {
66 $defaults = [
67 'locale' => get_locale(),
68 'currency_symbol' => '$',
69 'number_of_decimals' => 0,
70 'space_with_currency' => 0,
71 'currency_position' => 'left',
72 ];
73
74 $args = wp_parse_args($options, $defaults);
75
76 $originalLocale = get_locale();
77 switch_to_locale($args['locale']);
78 $formattedNumber = static::format($value, $args['number_of_decimals']);
79 switch_to_locale($originalLocale);
80
81 $symbol = $args['currency_symbol'];
82
83 $space = $args['space_with_currency'] ? ' ' : '';
84
85 if ($args['currency_position'] === 'left') {
86 return $symbol . $space . $formattedNumber;
87 } else {
88 return $formattedNumber . $space . $symbol;
89 }
90 }
91
92 /**
93 * Notation to numbers.
94 *
95 * This function transforms the php.ini notation
96 * for numbers (like '2M') to an integer.
97 *
98 * @param string $size Size value.
99 * @return int
100 */
101 public static function notationToNum($num)
102 {
103 $l = substr($num, -1);
104
105 $ret = (int) substr($num, 0, -1);
106
107 switch (strtoupper($l)) {
108 case 'P':
109 $ret *= 1024;
110 // No break.
111 case 'T':
112 $ret *= 1024;
113 // No break.
114 case 'G':
115 $ret *= 1024;
116 // No break.
117 case 'M':
118 $ret *= 1024;
119 // No break.
120 case 'K':
121 $ret *= 1024;
122 // No break.
123 }
124
125 return $ret;
126 }
127
128 /**
129 * Calculates the percentage/$percent from the $value/$total
130 *
131 * @param int|float $percent
132 * @param int|float $total
133 * @return int|float
134 */
135 public static function getPercentage($percent, $total)
136 {
137 return ($percent / 100) * $total;
138 }
139
140 /**
141 * Converts a number of bytes to human readable format
142 * using the maximum unit available to convert the bytes.
143 *
144 * @param int|float $bytes
145 * @param integer $decimals
146 * @return Formatted size units of bytes, i.e: 1mb/1gb e.t.c.
147 */
148 public static function formatBytes($bytes, $decimals = 0)
149 {
150 return size_format($bytes, $decimals);
151 }
152
153 /**
154 * Makes an ordinal number from the integer
155 *
156 * @param int $number
157 * @return The ordinal number, i.e: 1st, 5th e.t.c.
158 */
159 public static function toOrdinal($number)
160 {
161 if (!is_numeric($number)) {
162 return $number;
163 }
164
165 if (($number % 100) >= 11 && ($number % 100) <= 13) {
166 $suffix = 'th';
167 } else {
168 switch ($number % 10) {
169 case 1:
170 $suffix = 'st';
171 break;
172 case 2:
173 $suffix = 'nd';
174 break;
175 case 3:
176 $suffix = 'rd';
177 break;
178 default:
179 $suffix = 'th';
180 break;
181 }
182 }
183
184 return $number . $suffix;
185 }
186
187 /**
188 * Convert the number to its human readable equivalent.
189 *
190 * @param int $number
191 * @param int $precision
192 * @param int|null $maxPrecision
193 * @return string
194 */
195 public static function forHumans(
196 $number, $precision = 0, $maxPrecision = null, $abbr = false
197 )
198 {
199 return static::summarize($number, $precision, $maxPrecision, $abbr ? [
200 3 => 'K',
201 6 => 'M',
202 9 => 'B',
203 12 => 'T',
204 15 => 'Q',
205 ] : [
206 3 => ' thousand',
207 6 => ' million',
208 9 => ' billion',
209 12 => ' trillion',
210 15 => ' quadrillion',
211 ]);
212 }
213
214 /**
215 * Convert the number to its human readable equivalent.
216 *
217 * @param int $number
218 * @param int $precision
219 * @param int|null $maxPrecision
220 * @param array $units
221 * @return string
222 */
223 protected static function summarize(
224 $number, $precision = 0, $maxPrecision = null, $units = []
225 )
226 {
227 if (empty($units)) {
228 $units = [
229 3 => 'K',
230 6 => 'M',
231 9 => 'B',
232 12 => 'T',
233 15 => 'Q',
234 ];
235 }
236
237 switch (true) {
238 case floatval($number) === 0.0:
239 return $precision > 0 ? static::format(0, $precision, $maxPrecision) : '0';
240 case $number < 0:
241 return sprintf('-%s', static::summarize(abs($number), $precision, $maxPrecision, $units));
242 case $number >= 1e15:
243 return sprintf('%s'.end($units), static::summarize($number / 1e15, $precision, $maxPrecision, $units));
244 }
245
246 $numberExponent = floor(log10($number));
247 $displayExponent = $numberExponent - ($numberExponent % 3);
248 $number /= pow(10, $displayExponent);
249
250 return trim(
251 sprintf('%s%s', static::format(
252 $number, $precision, $maxPrecision
253 ), $units[$displayExponent] ?? '')
254 );
255 }
256
257 /**
258 * Converts a numeric number in words
259 *
260 * @param int|float $number
261 * @param boolean $round whether to round (float to int)
262 * @param boolean $inCents whether the result should say
263 * "and n cents" for the fraction.
264 *
265 * @return string number in words (in human readable words),
266 * i.e: from 199900010500.91 to:
267 * one hundred and ninety nine billion nine hundred million
268 * ten thousand five hundred and ninety one cents.
269 *
270 * @throws \RangeException
271 */
272 public static function inWords($number, $options = [])
273 {
274 $defaults = [
275 'should_round' => false,
276 'thousand_seperator' => ',',
277 'decimal_seperator' => '.',
278 'use_cents_for_decimal' => true
279 ];
280
281 $args = wp_parse_args($defaults, $options);
282
283 if (!is_numeric($number)) {
284 throw new TypeError('Not a number.');
285 }
286
287 if (is_int($number) && $number > strval(PHP_INT_MAX)) {
288 throw new RangeException('out of range', 500);
289 } elseif (is_float($number) && printf('%0.0f', $number) > PHP_FLOAT_MAX) {
290 throw new RangeException('out of range', 500);
291 }
292
293 $result = '';
294
295 $numberWords = [
296 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
297 'nine','ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen',
298 'sixteen','seventeen', 'eighteen', 'nineteen'
299 ];
300
301 $tensWords = [
302 '', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'
303 ];
304
305 $decimalSeparator = $args['decimal_seperator'];
306
307 $thousandSeparator = $args['thousand_seperator'];
308
309 $number = str_replace($thousandSeparator, '', $number);
310
311 if (!is_numeric($number) || $number < 0) {
312 return 'Invalid number';
313 }
314
315 $precision = 0;
316
317 if (str_contains($number, $decimalSeparator)) {
318 $precision = 2;
319 }
320
321 if ($args['should_round']) {
322 $precision = 0;
323 }
324
325 $numberStr = str_replace($thousandSeparator, '', static::format($number, $precision));
326
327 $integerPart = strstr($numberStr, $decimalSeparator, true) ?: $numberStr;
328
329 $decimalPart = strstr($numberStr, $decimalSeparator);
330
331 if (intval($integerPart) > 0) {
332 $result .= static::spellInteger($integerPart, $numberWords, $tensWords);
333 } else {
334 $result .= 'zero';
335 }
336
337 if ($decimalPart !== false && $precision) {
338 if (!$args['use_cents_for_decimal']) {
339 $result .= ' point ' . static::spellDecimal(
340 $decimalPart, $numberWords, $decimalSeparator
341 );
342 } else {
343 $decimalPart = (int) str_replace($decimalSeparator, '', $decimalPart);
344
345 $cents = static::toCents($decimalPart, $numberWords, $tensWords);
346
347 if ($cents != 'zero') {
348 $result .= ' and ' . $cents . ' cents';
349 }
350 }
351 }
352
353 return $result;
354 }
355
356 /**
357 * Make words from integers
358 *
359 * @param int $number
360 * @param array $numberWords
361 * @param array $tensWords
362 * @return string
363 */
364 protected static function spellInteger($number, $numberWords, $tensWords)
365 {
366 $result = '';
367
368 $result .= static::convertToWords($number, $numberWords, $tensWords);
369
370 return trim($result);
371 }
372
373 /**
374 * Make words from fraction part
375 *
376 * @param int $number
377 * @param array $numberWords
378 * @return string
379 */
380 protected static function spellDecimal($number, $numberWords, $decimalSeparator)
381 {
382 $result = '';
383
384 $decimalPosition = strpos($number, $decimalSeparator);
385
386 if ($decimalPosition !== false) {
387
388 $decimalAsString = substr($number, $decimalPosition + 1);
389
390 for ($i = 0; $i < strlen($decimalAsString); $i++) {
391
392 $digit = intval($decimalAsString[$i]);
393
394 $result .= $numberWords[$digit] . ' ';
395 }
396 } else {
397 $result .= 'zero';
398 }
399
400 return trim($result);
401 }
402
403 /**
404 * Main function to make the unit words
405 *
406 * @param int|float $number
407 * @param array $numberWords
408 * @param array $tensWords
409 * @return string
410 */
411 protected static function convertToWords($number, $numberWords, $tensWords)
412 {
413 if ($number < 20) {
414 return $numberWords[$number];
415
416 } elseif ($number < 100) {
417
418 $result = $tensWords[intval($number / 10)];
419
420 if (intval($number) % 10 !== 0) {
421 $result .= ' ' . static::convertToWords(
422 intval($number) % 10, $numberWords, $tensWords
423 );
424 }
425
426 return $result;
427
428 } elseif ($number < 1000) {
429
430 $result = $numberWords[intval($number / 100)] . ' hundred';
431
432 if (intval($number) % 100 !== 0) {
433 $result .= ' and ' . static::convertToWords(
434 intval($number) % 100, $numberWords, $tensWords
435 );
436 }
437
438 return $result;
439
440 } elseif ($number < 1000000) {
441
442 $result = static::convertToWords(
443 intval($number / 1000), $numberWords, $tensWords
444 );
445
446 $result .= ' thousand';
447
448 if (intval($number) % 1000 !== 0) {
449 $result .= ' ' . static::convertToWords(
450 intval($number) % 1000, $numberWords, $tensWords
451 );
452 }
453
454 return $result;
455
456 } elseif ($number < 1000000000) {
457
458 $result = static::convertToWords(
459 intval($number / 1000000), $numberWords, $tensWords
460 );
461
462 $result .= ' million';
463
464 if (intval($number) % 1000000 !== 0) {
465 $result .= ' ' . static::convertToWords(
466 intval($number) % 1000000, $numberWords, $tensWords
467 );
468 }
469
470 return $result;
471
472 } elseif ($number < 1000000000000) {
473
474 $result = static::convertToWords(
475 intval($number / 1000000000), $numberWords, $tensWords
476 );
477
478 $result .= ' billion';
479
480 if (intval($number) % 1000000000 !== 0) {
481 $result .= ' ' . static::convertToWords(
482 intval($number) % 1000000000, $numberWords, $tensWords
483 );
484 }
485
486 return $result;
487
488 } elseif ($number < 1000000000000000) {
489
490 $result = static::convertToWords(
491 intval($number / 1000000000000), $numberWords, $tensWords
492 );
493
494 $result .= ' trillion';
495
496 if (intval($number) % 1000000000000 !== 0) {
497 $result .= ' ' . static::convertToWords(
498 intval($number) % 1000000000000, $numberWords, $tensWords
499 );
500 }
501
502 return $result;
503
504 } elseif (intval($number) < 1000000000000000000) {
505
506 $result = static::convertToWords(
507 intval($number / 1000000000000000), $numberWords, $tensWords
508 );
509
510 $result .= ' quadrillion';
511
512 if (intval($number) % 1000000000000000 !== 0) {
513 $result .= ' ' . static::convertToWords(
514 intval($number) % 1000000000000000, $numberWords, $tensWords
515 );
516 }
517
518 return $result;
519
520 } elseif (intval($number) < 1000000000000000000000) {
521
522 $result = static::convertToWords(
523 intval($number / 1000000000000000000), $numberWords, $tensWords
524 );
525
526 $result .= ' quintillion';
527
528 if (intval($number) % 1000000000000000000 !== 0) {
529 $result .= ' ' . static::convertToWords(
530 intval($number) % 1000000000000000000, $numberWords, $tensWords
531 );
532 }
533
534 return $result;
535 } else {
536 throw new RangeException('Out of range', 500);
537 }
538 }
539
540 /**
541 * Make words for cents
542 *
543 * @param int|float $cents
544 * @param array $numberWords
545 * @param array $tensWords
546 * @return string
547 */
548 protected static function toCents($cents, $numberWords, $tensWords)
549 {
550 if (array_key_exists($cents, $numberWords)) {
551 return $numberWords[$cents];
552 } elseif (array_key_exists($cents, $tensWords)) {
553 return $tensWords[$cents];
554 }
555
556 $result = '';
557 $tens = substr(floor($cents / 10) * 10, 0, 1);
558 $unitsPart = $cents % 10;
559
560 if (array_key_exists($tens, $tensWords)) {
561 $result .= $tensWords[$tens];
562 if ($unitsPart > 0) {
563 $result .= ' ' . $numberWords[$unitsPart];
564 }
565 } elseif (array_key_exists($unitsPart, $numberWords)) {
566 $result .= $numberWords[$unitsPart];
567 }
568
569 return $result;
570 }
571 }
572