diff --git a/src/Filter/FilterPluginManager.php b/src/Filter/FilterPluginManager.php new file mode 100644 index 00000000..80b24c32 --- /dev/null +++ b/src/Filter/FilterPluginManager.php @@ -0,0 +1,77 @@ + 'Zend\I18n\Filter\NumberFormat', + ); + + /** + * Validate the plugin + * + * Checks that the filter loaded is either a valid callback or an instance + * of FilterInterface. + * + * @param mixed $plugin + * @return void + * @throws Exception\RuntimeException if invalid + */ + public function validatePlugin($plugin) + { + if ($plugin instanceof FilterInterface) { + // we're okay + return; + } + if (is_callable($plugin)) { + // also okay + return; + } + + throw new Exception\RuntimeException(sprintf( + 'Plugin of type %s is invalid; must implement %s\FilterInterface or be callable', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)), + __NAMESPACE__ + )); + } +} diff --git a/src/Filter/NumberFormat.php b/src/Filter/NumberFormat.php new file mode 100644 index 00000000..37fa6f36 --- /dev/null +++ b/src/Filter/NumberFormat.php @@ -0,0 +1,169 @@ + null, + 'style' => NumberFormatter::DEFAULT_STYLE, + 'type' => NumberFormatter::TYPE_DOUBLE + ); + + /** + * @var NumberFormatter + */ + protected $formatter = null; + + public function __construct($options = null) + { + if ($options !== null) { + if ($options instanceof Traversable) { + $options = iterator_to_array($options); + } + + if (!is_array($options)) { + $args = func_get_args(); + if (isset($args[0])) { + $this->setLocale($args[0]); + } + if (isset($args[1])) { + $this->setStyle($args[1]); + } + if (isset($args[2])) { + $this->setType($args[2]); + } + } else { + $this->setOptions($options); + } + } + } + + /** + * @param null $locale + * @return NumberFormat + */ + public function setLocale($locale = null) + { + $this->options['locale'] = $locale; + $this->formatter = null; + return $this; + } + + /** + * @param int $style + * @return NumberFormat + */ + public function setStyle($style) + { + $this->options['style'] = (int) $style; + $this->formatter = null; + return $this; + } + + /** + * @return int + */ + public function getStyle() + { + return $this->options['style']; + } + + /** + * @param int $type + * @return NumberFormat + */ + public function setType($type) + { + $this->options['type'] = (int) $type; + return $this; + } + + /** + * @return int + */ + public function getType() + { + return $this->options['type']; + } + + /** + * @param NumberFormatter $formatter + * @return NumberFormat + */ + public function setFormatter(NumberFormatter $formatter) + { + $this->formatter = $formatter; + return $this; + } + + /** + * @return NumberFormatter + * @throws Exception\RuntimeException + */ + public function getFormatter() + { + if ($this->formatter === null) { + $formatter = NumberFormatter::create($this->getLocale(), $this->getStyle()); + if (!$formatter) { + throw new Exception\RuntimeException( + 'Can not create NumberFormatter instance; ' . intl_get_error_message() + ); + } + + $this->formatter = $formatter; + } + + return $this->formatter; + } + + /** + * Defined by Zend\Filter\FilterInterface + * + * @see Zend\Filter\FilterInterface::filter() + * @param mixed $value + * @return mixed + */ + public function filter($value) + { + $formatter = $this->getFormatter(); + $type = $this->getType(); + + if (is_int($value) || is_float($value)) { + $result = @numfmt_format($formatter, $value, $type); + } else { + $value = str_replace(array("\xC2\xA0", ' '), '', $value); + $result = @numfmt_parse($formatter, $value, $type); + } + + if ($result === false) { + return $value; + } + + return str_replace("\xC2\xA0", ' ', $result); + } +} diff --git a/test/Filter/NumberFormatTest.php b/test/Filter/NumberFormatTest.php new file mode 100644 index 00000000..14425674 --- /dev/null +++ b/test/Filter/NumberFormatTest.php @@ -0,0 +1,92 @@ +assertEquals($expected, $filter->filter($value)); + } + + /** + * @param $locale + * @param $style + * @param $type + * @param $value + * @param $expected + * @dataProvider formattedToNumberProvider + */ + public function testFormattedToNumber($locale, $style, $type, $value, $expected) + { + $filter = new NumberFormatFilter($locale, $style, $type); + $this->assertEquals($expected, $filter->filter($value)); + } + + static public function numberToFormattedProvider() + { + return array( + array( + 'en_US', + null, + null, + 1234567.8912346, + '1,234,567.891' + ), + array( + 'de_DE', + null, + null, + 1234567.8912346, + '1.234.567,891' + ), + array( + 'ru_RU', + null, + null, + 1234567.8912346, + '1 234 567,891' + ), + ); + } + + static public function formattedToNumberProvider() + { + return array( + array( + 'en_US', + null, + null, + '1,234,567.891', + 1234567.891, + ), + array( + 'de_DE', + null, + null, + '1.234.567,891', + 1234567.891, + ), + array( + 'ru_RU', + null, + null, + '1 234 567,891', + 1234567.891, + ), + ); + } +}