Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

2.3 CakeNumber::formatDelta() #771

Closed
wants to merge 3 commits into from

4 participants

@dereuromark
Collaborator

in some cases you just want to display the values as signed values in the view than first figuring out the sign and passing this on to the format() method.
this is especially useful for outputting differences in values (e.g. "+50 meters since xxxx-xx-xx").

implementing it I found a related issue with format() and almost-zero values. fixed and test cases added.
-0.01 would not show as -0.0 anymore for format() now anymore.

note: used to be #658

@lorenzo
Owner

I like the idea, but not the method name that much

@dereuromark
Collaborator

@lorenzo you had like months to complain :) hm, any ideas for it?

@lorenzo
Owner

Dd not follow the other pull request, sorry :(

@dereuromark
Collaborator

no problem. what about formatDelta()?

@dereuromark
Collaborator

@lorenzo How do you like CakeNumber::formatDelta()? After all, that's what it is. I can modify the PR then.

@lorenzo
Owner

Votes for/against this PR?

@dereuromark
Collaborator

don't forget the bugfix about almost-zero values and the sign being displayed otherwise (-0)

lib/Cake/Utility/CakeNumber.php
@@ -158,6 +159,27 @@ public static function format($number, $options = false) {
}
/**
+ * Formats a number into a currency format to show deltas (as signed value).
+ *
+ * @param float $number A floating point number
+ * @param integer $options if int then places, if string then before, if (,.-) then use it
+ * or array with places and before keys
+ * @return string formatted difference
+ */
+ public static function formatDelta($value, $options = array()) {
+ $places = isset($options['places']) ? $options['places'] : 0;
+ $value = self::_numberFormat($value, $places, '.', '');
+ $sign = $value > 0 ? '+' : '';
+ $options = (array)$options;
@markstory Owner

Shouldn't this happen first? I remember in that in 5.2.x `isset($var['key']) on a string is always true. I don't see why we need to accept mixed types here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/Cake/Utility/CakeNumber.php
@@ -158,6 +159,27 @@ public static function format($number, $options = false) {
}
/**
+ * Formats a number into a currency format to show deltas (as signed value).
+ *
+ * @param float $number A floating point number
+ * @param integer $options if int then places, if string then before, if (,.-) then use it
@markstory Owner

Isn't this parameter an array?

@dereuromark Collaborator

well, not that easy, i am afraid - it uses format() - and its doc: "integer $options if int then places, if string then before, if (,.-) then use it or array with places and before keys"
so it can be multiple things at once (which I dont like by the way)

@markstory Owner

Ugh, its probably still a good idea to fix the isset() and do type checks on the parameter instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/Cake/Utility/CakeNumber.php
((5 lines not shown))
+ *
+ * @param float $number A floating point number
+ * @param integer $options if int then places, if string then before, if (,.-) then use it
+ * or array with places and before keys
+ * @return string formatted difference
+ */
+ public static function formatDelta($value, $options = array()) {
+ $places = isset($options['places']) ? $options['places'] : 0;
+ $value = self::_numberFormat($value, $places, '.', '');
+ $sign = $value > 0 ? '+' : '';
+ $options = (array)$options;
+ if (isset($options['before'])) {
+ $options['before'] .= $sign;
+ } else {
+ $options['before'] = $sign;
+ }
@markstory Owner

Couldn't this whole if/else be written as $options['before'] = isset($options['before']) ? $options['before'] . $sign : $sign; ?

@dereuromark Collaborator

sure, I just copy and pasted the old format method here. But I can refactor accordingly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/Cake/Utility/CakeNumber.php
@@ -158,6 +159,27 @@ public static function format($number, $options = false) {
}
/**
+ * Formats a number into a currency format to show deltas (as signed value).
+ *
+ * @param float $number A floating point number
@jrbasso Collaborator
jrbasso added a note

This param is called $value, not $number.

@dereuromark Collaborator

I correct this and rename all $number into $value

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@dereuromark
Collaborator

maybe we should only accept an array here. providing the different string/int params as well makes it way more complicated without gaining anything. it is a new method anyway (so no BC issues.

@markstory
Owner

That's probably a better option :)

@dereuromark
Collaborator

closing in favor of #859 which is not screwed up by some "fast forward" mistakes i made.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
41 lib/Cake/Test/Case/Utility/CakeNumberTest.php
@@ -70,6 +70,47 @@ public function testFormat() {
$result = $this->Number->format($value, '-');
$expected = '100-100-100';
$this->assertEquals($expected, $result);
+
+ $value = 0.00001;
+ $result = $this->Number->format($value, array('places' => 1));
+ $expected = '$0.0';
+ $this->assertEquals($expected, $result);
+
+ $value = -0.00001;
+ $result = $this->Number->format($value, array('places' => 1));
+ $expected = '$0.0';
+ $this->assertEquals($expected, $result);
+ }
+
+/**
+ * testFormatDifference method
+ *
+ * @return void
+ */
+ public function testFormatDifference() {
+ $value = '100100100';
+
+ $result = $this->Number->formatDifference($value, array('before' => '', 'after' => ''));
+ $expected = '+100,100,100.00';
+ $this->assertEquals($expected, $result);
+
+ $result = $this->Number->formatDifference($value, array('before' => '[', 'after' => ']'));
+ $expected = '[+100,100,100.00]';
+ $this->assertEquals($expected, $result);
+
+ $result = $this->Number->formatDifference(-$value, array('before' => '[', 'after' => ']'));
+ $expected = '[-100,100,100.00]';
+ $this->assertEquals($expected, $result);
+
+ $value = 0;
+ $result = $this->Number->formatDifference($value, array('places' => 1, 'before' => '[', 'after' => ']'));
+ $expected = '[0.0]';
+ $this->assertEquals($expected, $result);
+
+ $value = 0.0001;
+ $result = $this->Number->formatDifference($value, array('places' => 1, 'before' => '[', 'after' => ']'));
+ $expected = '[0.0]';
+ $this->assertEquals($expected, $result);
}
/**
View
74 lib/Cake/Utility/CakeNumber.php
@@ -70,13 +70,13 @@ class CakeNumber {
/**
* Formats a number with a level of precision.
*
- * @param float $number A floating point number.
+ * @param float $value A floating point number.
* @param integer $precision The precision of the returned number.
* @return float Formatted float.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::precision
*/
- public static function precision($number, $precision = 3) {
- return sprintf("%01.{$precision}F", $number);
+ public static function precision($value, $precision = 3) {
+ return sprintf("%01.{$precision}F", $value);
}
/**
@@ -135,25 +135,25 @@ public static function fromReadableSize($size, $default = false) {
/**
* Formats a number into a percentage string.
*
- * @param float $number A floating point number
+ * @param float $value A floating point number
* @param integer $precision The precision of the returned number
* @return string Percentage string
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::toPercentage
*/
- public static function toPercentage($number, $precision = 2) {
- return self::precision($number, $precision) . '%';
+ public static function toPercentage($value, $precision = 2) {
+ return self::precision($value, $precision) . '%';
}
/**
* Formats a number into a currency format.
*
- * @param float $number A floating point number
+ * @param float $value A floating point number
* @param integer $options if int then places, if string then before, if (,.-) then use it
* or array with places and before keys
* @return string formatted number
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::format
*/
- public static function format($number, $options = false) {
+ public static function format($value, $options = false) {
$places = 0;
if (is_int($options)) {
$places = $options;
@@ -180,7 +180,8 @@ public static function format($number, $options = false) {
extract($options);
}
- $out = $before . self::_numberFormat($number, $places, $decimals, $thousands) . $after;
+ $value = self::_numberFormat($value, $places, '.', '');
+ $out = $before . self::_numberFormat($value, $places, $decimals, $thousands) . $after;
if ($escape) {
return h($out);
@@ -189,33 +190,50 @@ public static function format($number, $options = false) {
}
/**
+ * Formats a number into a currency format to show differences.
+ *
+ * @param float $value A floating point number
+ * @param integer $options if int then places, if string then before, if (,.-) then use it
+ * or array with places and before keys
+ * @return string formatted difference
+ */
+ public static function formatDifference($value, $options = array()) {
+ $places = isset($options['places']) ? $options['places'] : 0;
+ $value = self::_numberFormat($value, $places, '.', '');
+ $sign = $value > 0 ? '+' : '';
+ $options = (array)$options;
+ $options['before'] = isset($options['before']) ? $options['before'] . $sign : $sign;
+ return self::format($value, $options);
+ }
+
+/**
* Alternative number_format() to accommodate multibyte decimals and thousands < PHP 5.4
*
- * @param float $number
+ * @param float $value
* @param integer $places
* @param string $decimals
* @param string $thousands
* @return string
*/
- protected static function _numberFormat($number, $places = 0, $decimals = '.', $thousands = ',') {
+ protected static function _numberFormat($value, $places = 0, $decimals = '.', $thousands = ',') {
if (!isset(self::$_numberFormatSupport)) {
self::$_numberFormatSupport = version_compare(PHP_VERSION, '5.4.0', '>=');
}
if (self::$_numberFormatSupport) {
- return number_format($number, $places, $decimals, $thousands);
+ return number_format($value, $places, $decimals, $thousands);
}
- $number = number_format($number, $places, '.', '');
+ $value = number_format($value, $places, '.', '');
$after = '';
- $foundDecimal = strpos($number, '.');
+ $foundDecimal = strpos($value, '.');
if ($foundDecimal !== false) {
- $after = substr($number, $foundDecimal);
- $number = substr($number, 0, $foundDecimal);
+ $after = substr($value, $foundDecimal);
+ $value = substr($value, 0, $foundDecimal);
}
- while (($foundThousand = preg_replace('/(\d+)(\d\d\d)/', '\1 \2', $number)) != $number) {
- $number = $foundThousand;
+ while (($foundThousand = preg_replace('/(\d+)(\d\d\d)/', '\1 \2', $value)) != $value) {
+ $value = $foundThousand;
}
- $number .= $after;
- return strtr($number, array(' ' => $thousands, '.' => $decimals));
+ $value .= $after;
+ return strtr($value, array(' ' => $thousands, '.' => $decimals));
}
/**
@@ -244,14 +262,14 @@ protected static function _numberFormat($number, $places = 0, $decimals = '.', $
* the number will be wrapped with ( and )
* - `escape` - Should the output be htmlentity escaped? Defaults to true
*
- * @param float $number
+ * @param float $value
* @param string $currency Shortcut to default options. Valid values are
* 'USD', 'EUR', 'GBP', otherwise set at least 'before' and 'after' options.
* @param array $options
* @return string Number formatted as a currency.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::currency
*/
- public static function currency($number, $currency = 'USD', $options = array()) {
+ public static function currency($value, $currency = 'USD', $options = array()) {
$default = self::$_currencyDefaults;
if (isset(self::$_currencies[$currency])) {
@@ -272,14 +290,14 @@ public static function currency($number, $currency = 'USD', $options = array())
$result = $options['before'] = $options['after'] = null;
$symbolKey = 'whole';
- if ($number == 0 ) {
- if ($options['zero'] !== 0 ) {
+ if ($value == 0) {
+ if ($options['zero'] !== 0) {
return $options['zero'];
}
- } elseif ($number < 1 && $number > -1 ) {
+ } elseif ($value < 1 && $value > -1) {
if ($options['fractionSymbol'] !== false) {
$multiply = intval('1' . str_pad('', $options['places'], '0'));
- $number = $number * $multiply;
+ $value = $value * $multiply;
$options['places'] = null;
$symbolKey = 'fraction';
}
@@ -288,10 +306,10 @@ public static function currency($number, $currency = 'USD', $options = array())
$position = $options[$symbolKey . 'Position'] != 'after' ? 'before' : 'after';
$options[$position] = $options[$symbolKey . 'Symbol'];
- $abs = abs($number);
+ $abs = abs($value);
$result = self::format($abs, $options);
- if ($number < 0 ) {
+ if ($value < 0 ) {
if ($options['negative'] == '()') {
$result = '(' . $result . ')';
} else {
Something went wrong with that request. Please try again.