3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\I18n\View\Helper
;
14 use Zend\I18n\Exception
;
15 use Zend\View\Helper\AbstractHelper
;
18 * View helper for formatting currency.
20 class CurrencyFormat
extends AbstractHelper
23 * The 3-letter ISO 4217 currency code indicating the currency to use
27 protected $currencyCode;
34 protected $formatters = [];
37 * Locale to use instead of the default
48 protected $currencyPattern;
51 * If set to true, the currency will be returned with two decimals
55 protected $showDecimals = true;
58 * Special condition to be checked due to ICU bug:
59 * http://bugs.icu-project.org/trac/ticket/10997
63 protected $correctionNeeded = false;
68 * @throws Exception\ExtensionNotLoadedException if ext/intl is not present
70 public function __construct()
72 if (! extension_loaded('intl')) {
73 throw new Exception\
ExtensionNotLoadedException(sprintf(
74 '%s component requires the intl PHP extension',
83 * @param float $number
84 * @param string $currencyCode
85 * @param bool $showDecimals
86 * @param string $locale
87 * @param string $pattern
90 public function __invoke(
97 if (null === $locale) {
98 $locale = $this->getLocale();
100 if (null === $currencyCode) {
101 $currencyCode = $this->getCurrencyCode();
103 if (null === $showDecimals) {
104 $showDecimals = $this->shouldShowDecimals();
106 if (null === $pattern) {
107 $pattern = $this->getCurrencyPattern();
110 return $this->formatCurrency($number, $currencyCode, $showDecimals, $locale, $pattern);
116 * @param float $number
117 * @param string $currencyCode
118 * @param bool $showDecimals
119 * @param string $locale
120 * @param string $pattern
123 protected function formatCurrency(
130 $formatterId = md5($locale);
132 if (! isset($this->formatters
[$formatterId])) {
133 $this->formatters
[$formatterId] = new NumberFormatter(
135 NumberFormatter
::CURRENCY
139 if ($pattern !== null) {
140 $this->formatters
[$formatterId]->setPattern($pattern);
144 $this->formatters
[$formatterId]->setAttribute(NumberFormatter
::FRACTION_DIGITS
, 2);
145 $this->correctionNeeded
= false;
147 $this->formatters
[$formatterId]->setAttribute(NumberFormatter
::FRACTION_DIGITS
, 0);
148 $defaultCurrencyCode = $this->formatters
[$formatterId]->getTextAttribute(NumberFormatter
::CURRENCY_CODE
);
149 $this->correctionNeeded
= $defaultCurrencyCode !== $currencyCode;
152 $formattedNumber = $this->formatters
[$formatterId]->formatCurrency($number, $currencyCode);
154 if ($this->correctionNeeded
) {
155 $formattedNumber = $this->fixICUBugForNoDecimals(
157 $this->formatters
[$formatterId],
163 return $formattedNumber;
167 * The 3-letter ISO 4217 currency code indicating the currency to use
169 * @param string $currencyCode
170 * @return CurrencyFormat
172 public function setCurrencyCode($currencyCode)
174 $this->currencyCode
= $currencyCode;
179 * Get the 3-letter ISO 4217 currency code indicating the currency to use
183 public function getCurrencyCode()
185 return $this->currencyCode
;
189 * Set the currency pattern
191 * @param string $currencyPattern
192 * @return CurrencyFormat
194 public function setCurrencyPattern($currencyPattern)
196 $this->currencyPattern
= $currencyPattern;
201 * Get the currency pattern
205 public function getCurrencyPattern()
207 return $this->currencyPattern
;
211 * Set locale to use instead of the default
213 * @param string $locale
214 * @return CurrencyFormat
216 public function setLocale($locale)
218 $this->locale
= (string) $locale;
223 * Get the locale to use
225 * @return string|null
227 public function getLocale()
229 if ($this->locale
=== null) {
230 $this->locale
= Locale
::getDefault();
233 return $this->locale
;
237 * Set if the view helper should show two decimals
239 * @param bool $showDecimals
240 * @return CurrencyFormat
242 public function setShouldShowDecimals($showDecimals)
244 $this->showDecimals
= (bool) $showDecimals;
249 * Get if the view helper should show two decimals
253 public function shouldShowDecimals()
255 return $this->showDecimals
;
261 * @param string $formattedNumber
262 * @param NumberFormatter $formatter
263 * @param string $locale
264 * @param string $currencyCode
268 private function fixICUBugForNoDecimals($formattedNumber, NumberFormatter
$formatter, $locale, $currencyCode)
271 '/\%s\d+(\s?%s)?$/u',
272 $formatter->getSymbol(NumberFormatter
::DECIMAL_SEPARATOR_SYMBOL
),
273 preg_quote($this->getCurrencySymbol($locale, $currencyCode))
276 return preg_replace($pattern, '$1', $formattedNumber);
282 * @param string $locale
283 * @param string $currencyCode
287 private function getCurrencySymbol($locale, $currencyCode)
289 $numberFormatter = new NumberFormatter($locale . '@currency=' . $currencyCode, NumberFormatter
::CURRENCY
);
291 return $numberFormatter->getSymbol(NumberFormatter
::CURRENCY_SYMBOL
);