Browse Source

Improving Number::defaultCurrency() and fixing issue with showing negative cents

Jose Lorenzo Rodriguez 11 years ago
parent
commit
cec48ac475
2 changed files with 36 additions and 139 deletions
  1. 30 10
      src/Utility/Number.php
  2. 6 129
      tests/TestCase/Utility/NumberTest.php

+ 30 - 10
src/Utility/Number.php

@@ -84,7 +84,7 @@ class Number {
  *
  * @var string
  */
-	protected static $_defaultCurrency = 'USD';
+	protected static $_defaultCurrency;
 
 /**
  * Formats a number with a level of precision.
@@ -277,7 +277,7 @@ class Number {
  * - `pattern` - An ICU number patter to use for formatting the number. e.g #,###.00
  *
  * @param float $value Value to format.
- * @param string $currency International currency name such as 'USD', 'EUR', 'YEN', 'CAD'
+ * @param string $currency International currency name such as 'USD', 'EUR', 'JPY', 'CAD'
  * @param array $options Options list.
  * @return string Number formatted as a currency.
  */
@@ -303,20 +303,28 @@ class Number {
 		}
 
 		$formatter = static::$_currencyFormatters[$locale];
+		$hasPlaces = isset($options['places']);
+		$hasPrecision = isset($options['precision']);
+		$hasPattern = !empty($options['pattern']);
 
-		if (isset($options['places'])) {
+		if ($hasPlaces || $hasPrecision || $hasPattern) {
+			$formatter = clone $formatter;
+		}
+
+		if ($hasPlaces) {
 			$formatter->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $options['places']);
 		}
 
-		if (isset($options['precision'])) {
+		if ($hasPrecision) {
 			$formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $options['precision']);
 		}
 
-		if (!empty($options['pattern'])) {
+		if ($hasPattern) {
 			$formatter->setPattern($options['pattern']);
 		}
 
-		if (!empty($options['fractionSymbol']) && $value > 0 && $value < 1) {
+		$abs = abs($value);
+		if (!empty($options['fractionSymbol']) && $abs > 0 && $abs < 1) {
 			$value = $value * 100;
 			$pos = isset($options['fractionPosition']) ? $options['fractionPosition'] : 'after';
 			return static::format($value, ['precision' => 0, $pos => $options['fractionSymbol']]);
@@ -353,14 +361,26 @@ class Number {
 /**
  * Getter/setter for default currency
  *
- * @param string $currency Default currency string used by currency() if $currency argument is not provided
+ * @param string|boolean $currency Default currency string to be used by currency()
+ * if $currency argument is not provided. If boolean false is passed, it will clear the
+ * currently stored value
  * @return string Currency
- * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::defaultCurrency
  */
 	public static function defaultCurrency($currency = null) {
-		if ($currency) {
-			self::$_defaultCurrency = $currency;
+		if (!empty($currency)) {
+			return self::$_defaultCurrency = $currency;
+		}
+
+		if ($currency === false) {
+			self::$_defaultCurrency = null;
 		}
+
+		if (empty(self::$_defaultCurrency)) {
+			$locale = ini_get('intl.default_locale') ?: 'en_US';
+			$formatter = new NumberFormatter($locale, NumberFormatter::CURRENCY);
+			self::$_defaultCurrency = $formatter->getTextAttribute(NumberFormatter::CURRENCY_CODE);
+		}
+
 		return self::$_defaultCurrency;
 	}
 

+ 6 - 129
tests/TestCase/Utility/NumberTest.php

@@ -46,6 +46,7 @@ class NumberTest extends TestCase {
 		parent::tearDown();
 		unset($this->Number);
 		I18n::defaultLocale($this->locale);
+		Number::defaultCurrency(false);
 	}
 
 /**
@@ -261,24 +262,11 @@ class NumberTest extends TestCase {
 	}
 
 /**
- * Test that the default fraction handling does not cause issues.
- *
- * @return void
- */
-	public function testCurrencyFractionSymbol() {
-		$result = $this->Number->currency(0.2, '', array(
-			'places' => 2,
-			'decimal' => '.'
-		));
-		$this->assertEquals('0.2', $result);
-	}
-
-/**
  * Test adding currency format options to the number helper
  *
  * @return void
  */
-	public function testCurrencyAddFormat() {
+	public function _testCurrencyAddFormat() {
 		$this->Number->addFormat('NOK', array('before' => 'Kr. '));
 		$result = $this->Number->currency(1000, 'NOK');
 		$expected = 'Kr. 1,000.00';
@@ -333,93 +321,6 @@ class NumberTest extends TestCase {
 	}
 
 /**
- * testCurrencyPositive method
- *
- * @return void
- */
-	public function testCurrencyPositive() {
-		$value = '100100100';
-
-		$result = $this->Number->currency($value);
-		$expected = '$100,100,100.00';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'USD', array('before' => '#'));
-		$expected = '#100,100,100.00';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, false);
-		$expected = '100,100,100.00';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'USD');
-		$expected = '$100,100,100.00';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'EUR');
-		$expected = '€100.100.100,00';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'GBP');
-		$expected = '£100,100,100.00';
-		$this->assertEquals($expected, $result);
-	}
-
-/**
- * testCurrencyNegative method
- *
- * @return void
- */
-	public function testCurrencyNegative() {
-		$value = '-100100100';
-
-		$result = $this->Number->currency($value);
-		$expected = '($100,100,100.00)';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'EUR');
-		$expected = '(€100.100.100,00)';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'GBP');
-		$expected = '(£100,100,100.00)';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'USD', array('negative' => '-'));
-		$expected = '-$100,100,100.00';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'EUR', array('negative' => '-'));
-		$expected = '-€100.100.100,00';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'GBP', array('negative' => '-'));
-		$expected = '-£100,100,100.00';
-		$this->assertEquals($expected, $result);
-	}
-
-/**
- * testCurrencyCentsPositive method
- *
- * @return void
- */
-	public function testCurrencyCentsPositive() {
-		$value = '0.99';
-
-		$result = $this->Number->currency($value, 'USD');
-		$expected = '99c';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'EUR');
-		$expected = '€0,99';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'GBP');
-		$expected = '99p';
-		$this->assertEquals($expected, $result);
-	}
-
-/**
  * testCurrencyCentsNegative method
  *
  * @return void
@@ -427,29 +328,13 @@ class NumberTest extends TestCase {
 	public function testCurrencyCentsNegative() {
 		$value = '-0.99';
 
-		$result = $this->Number->currency($value, 'USD');
-		$expected = '(99c)';
-		$this->assertEquals($expected, $result);
-
 		$result = $this->Number->currency($value, 'EUR');
-		$expected = '(€0,99)';
+		$expected = '-€0.99';
 		$this->assertEquals($expected, $result);
 
-		$result = $this->Number->currency($value, 'GBP');
-		$expected = '(99p)';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'USD', array('negative' => '-'));
+		$result = $this->Number->currency($value, 'USD', ['fractionSymbol' => 'c']);
 		$expected = '-99c';
 		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'EUR', array('negative' => '-'));
-		$expected = '-€0,99';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'GBP', array('negative' => '-'));
-		$expected = '-99p';
-		$this->assertEquals($expected, $result);
 	}
 
 /**
@@ -464,16 +349,8 @@ class NumberTest extends TestCase {
 		$expected = '$0.00';
 		$this->assertEquals($expected, $result);
 
-		$result = $this->Number->currency($value, 'EUR');
-		$expected = '€0,00';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'GBP');
-		$expected = '£0.00';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Number->currency($value, 'GBP', array('zero' => 'FREE!'));
-		$expected = 'FREE!';
+		$result = $this->Number->currency($value, 'EUR', ['locale' => 'fr_FR']);
+		$expected = '0,00 €';
 		$this->assertEquals($expected, $result);
 	}