Skip to content

Commit 4412563

Browse files
committed
Initial work on new number helper
1 parent b21364f commit 4412563

3 files changed

Lines changed: 324 additions & 0 deletions

File tree

system/Helpers/number_helper.php

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
<?php
2+
/**
3+
* CodeIgniter
4+
*
5+
* An open source application development framework for PHP
6+
*
7+
* This content is released under the MIT License (MIT)
8+
*
9+
* Copyright (c) 2014 - 2016, British Columbia Institute of Technology
10+
*
11+
* Permission is hereby granted, free of charge, to any person obtaining a copy
12+
* of this software and associated documentation files (the "Software"), to deal
13+
* in the Software without restriction, including without limitation the rights
14+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15+
* copies of the Software, and to permit persons to whom the Software is
16+
* furnished to do so, subject to the following conditions:
17+
*
18+
* The above copyright notice and this permission notice shall be included in
19+
* all copies or substantial portions of the Software.
20+
*
21+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27+
* THE SOFTWARE.
28+
*
29+
* @package CodeIgniter
30+
* @author EllisLab Dev Team
31+
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
32+
* @copyright Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
33+
* @license http://opensource.org/licenses/MIT MIT License
34+
* @link https://codeigniter.com
35+
* @since Version 1.0.0
36+
* @filesource
37+
*/
38+
39+
40+
if ( ! function_exists('number_to_size'))
41+
{
42+
/**
43+
* Formats a numbers as bytes, based on size, and adds the appropriate suffix
44+
*
45+
* @param mixed will be cast as int
46+
* @param int
47+
* @return string
48+
*/
49+
function number_to_size($num, int $precision = 1, string $locale=null)
50+
{
51+
// Strip any formatting
52+
$num = 0 + str_replace(',','',$num);
53+
54+
// Can't work with non-numbers...
55+
if (! is_numeric($num))
56+
{
57+
return false;
58+
}
59+
60+
if ($num >= 1000000000000)
61+
{
62+
$num = round($num / 1099511627776, $precision);
63+
$unit = lang('Number.terabyteAbbr');
64+
}
65+
elseif ($num >= 1000000000)
66+
{
67+
$num = round($num / 1073741824, $precision);
68+
$unit = lang('Number.gigabyteAbbr');
69+
}
70+
elseif ($num >= 1000000)
71+
{
72+
$num = round($num / 1048576, $precision);
73+
$unit = lang('Number.megabyteAbbr');
74+
}
75+
elseif ($num >= 1000)
76+
{
77+
$num = round($num / 1024, $precision);
78+
$unit = lang('Number.kilobyteAbbr');
79+
}
80+
else
81+
{
82+
$unit = lang('Number.bytes');
83+
return number_format($num).' '.$unit;
84+
}
85+
86+
return format_number($num, $precision, $locale).' '.$unit;
87+
}
88+
}
89+
90+
//--------------------------------------------------------------------
91+
92+
if (! function_exists('number_to_amount'))
93+
{
94+
/**
95+
* Converts numbers to a more readable representation
96+
* when dealing with very large numbers (in the thousands or above),
97+
* up to the quadrillions, because you won't often deal with numbers
98+
* larger than that.
99+
*
100+
* It uses the "short form" numbering system as this is most commonly
101+
* used within most English-speaking countries today.
102+
*
103+
* @see https://simple.wikipedia.org/wiki/Names_for_large_numbers
104+
*
105+
* @param $num
106+
* @param int $precision
107+
* @param string|null $locale
108+
*
109+
* @return bool|string
110+
*/
111+
function number_to_amount($num, int $precision, string $locale = null)
112+
{
113+
// Strip any formatting
114+
$num = 0 + str_replace(',','',$num);
115+
116+
// Can't work with non-numbers...
117+
if (! is_numeric($num))
118+
{
119+
return false;
120+
}
121+
122+
$suffix = '';
123+
124+
if ($num > 1000000000000000)
125+
{
126+
$suffix = lang('Number.quadrillion');
127+
$num = round(($num / 1000000000000000), $precision);
128+
}
129+
elseif ($num > 1000000000000)
130+
{
131+
$suffix = lang('Number.trillion');
132+
$num = round(($num / 1000000000000), $precision);
133+
}
134+
else if ($num > 1000000000)
135+
{
136+
$suffix = lang('Number.billion');
137+
$num = round(($num/1000000000), $precision);
138+
}
139+
else if ($num > 1000000)
140+
{
141+
$suffix = lang('Number.million');
142+
$num = round(($num/1000000), $precision);
143+
}
144+
else if ($num > 1000)
145+
{
146+
$suffix = lang('Number.thousand');
147+
$num = round(($num/1000), $precision);
148+
}
149+
150+
return format_number($num, $precision, $locale). $suffix;
151+
}
152+
}
153+
154+
//--------------------------------------------------------------------
155+
156+
if (! function_exists('format_number'))
157+
{
158+
function format_number($num, int $precision = 1, string $locale = null, array $options=[])
159+
{
160+
// Locale is either passed in here, negotiated with client, or grabbed from our config file.
161+
$locale = $locale ?? \CodeIgniter\Config\Services::request()->getLocale();
162+
163+
// Type can be any of the NumberFormatter options, but provide a default.
164+
$type = isset($options['type'])
165+
? (int)$options['type'] :
166+
NumberFormatter::DECIMAL;
167+
168+
// In order to specify a precision, we'll have to modify
169+
// the pattern used by NumberFormatter.
170+
$pattern = '#,##0.'. str_repeat('#', $precision);
171+
172+
$formatter = new NumberFormatter($locale, $type);
173+
$formatter->setPattern($pattern);
174+
175+
// Try to format it per the locale
176+
$output = $formatter->format($num);
177+
178+
if (intl_is_failure($formatter->getErrorCode()))
179+
{
180+
throw new BadFunctionCallException($formatter->getErrorMessage());
181+
}
182+
183+
return $output;
184+
}
185+
}
186+
187+
//--------------------------------------------------------------------

system/Language/en/Number.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
/**
3+
* CodeIgniter
4+
*
5+
* An open source application development framework for PHP
6+
*
7+
* This content is released under the MIT License (MIT)
8+
*
9+
* Copyright (c) 2014 - 2016, British Columbia Institute of Technology
10+
*
11+
* Permission is hereby granted, free of charge, to any person obtaining a copy
12+
* of this software and associated documentation files (the "Software"), to deal
13+
* in the Software without restriction, including without limitation the rights
14+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15+
* copies of the Software, and to permit persons to whom the Software is
16+
* furnished to do so, subject to the following conditions:
17+
*
18+
* The above copyright notice and this permission notice shall be included in
19+
* all copies or substantial portions of the Software.
20+
*
21+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27+
* THE SOFTWARE.
28+
*
29+
* @package CodeIgniter
30+
* @author EllisLab Dev Team
31+
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
32+
* @copyright Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
33+
* @license http://opensource.org/licenses/MIT MIT License
34+
* @link https://codeigniter.com
35+
* @since Version 1.0.0
36+
* @filesource
37+
*/
38+
return [
39+
'terabyteAbbr' => 'TB',
40+
'gigabyteAbbr' => 'GB',
41+
'megabyteAbbr' => 'MB',
42+
'kilobyteAbbr' => 'KB',
43+
'bytes' => 'Bytes',
44+
// don't forget the space in front of these!
45+
'thousand' => ' thousand',
46+
'million' => ' million',
47+
'billion' => ' billion',
48+
'trillion' => ' trillion',
49+
'quadrillion' => ' quadrillion',
50+
];
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php namespace CodeIgniter\HTTP;
2+
3+
class numberHelperTest extends \CIUnitTestCase
4+
{
5+
public function __construct(...$params)
6+
{
7+
parent::__construct(...$params);
8+
9+
helper('number');
10+
}
11+
12+
//--------------------------------------------------------------------
13+
14+
public function test_format_number()
15+
{
16+
$this->assertEquals('123,456', format_number(123456, 0, 'en_US'));
17+
}
18+
19+
/**
20+
* @group single
21+
*/
22+
public function test_format_number_with_precision()
23+
{
24+
$this->assertEquals('123,456.8', format_number(123456.789, 1, 'en_US'));
25+
$this->assertEquals('123,456.79', format_number(123456.789, 2, 'en_US'));
26+
}
27+
28+
public function test_number_to_size()
29+
{
30+
$this->assertEquals('456 Bytes', number_to_size(456));
31+
}
32+
33+
public function test_kb_format()
34+
{
35+
$this->assertEquals('4.5 KB', number_to_size(4567));
36+
}
37+
38+
public function test_kb_format_medium()
39+
{
40+
$this->assertEquals('44.6 KB', number_to_size(45678));
41+
}
42+
43+
public function test_kb_format_large()
44+
{
45+
$this->assertEquals('446.1 KB', number_to_size(456789));
46+
}
47+
48+
public function test_mb_format()
49+
{
50+
$this->assertEquals('3.3 MB', number_to_size(3456789));
51+
}
52+
53+
public function test_gb_format()
54+
{
55+
$this->assertEquals('1.8 GB', number_to_size(1932735283.2));
56+
}
57+
58+
public function test_tb_format()
59+
{
60+
$this->assertEquals('112,283.3 TB', number_to_size(123456789123456789));
61+
}
62+
63+
public function test_thousands()
64+
{
65+
$this->assertEquals('123 thousand', number_to_amount('123,000', 0, 'en_US'));
66+
}
67+
68+
public function test_millions()
69+
{
70+
$this->assertEquals('123.4 million', number_to_amount('123,400,000', 1, 'en_US'));
71+
}
72+
73+
public function test_billions()
74+
{
75+
$this->assertEquals('123.46 billion', number_to_amount('123,456,000,000', 2, 'en_US'));
76+
}
77+
78+
public function test_trillions()
79+
{
80+
$this->assertEquals('123.457 trillion', number_to_amount('123,456,700,000,000', 3, 'en_US'));
81+
}
82+
83+
public function test_quadrillions()
84+
{
85+
$this->assertEquals('123.5 quadrillion', number_to_amount('123,456,700,000,000,000', 1, 'en_US'));
86+
}
87+
}

0 commit comments

Comments
 (0)