1<?php
2/**
3 * Zend Framework (http://framework.zend.com/)
4 *
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
8 */
9
10namespace Zend\I18n\View\Helper;
11
12use Locale;
13use NumberFormatter;
14use Zend\I18n\Exception;
15use Zend\View\Helper\AbstractHelper;
16
17/**
18 * View helper for formatting dates.
19 */
20class NumberFormat extends AbstractHelper
21{
22    /**
23     * number of decimals to use.
24     *
25     * @var int
26     */
27    protected $decimals;
28
29    /**
30     * NumberFormat style to use
31     *
32     * @var int
33     */
34    protected $formatStyle;
35
36    /**
37     * NumberFormat type to use
38     *
39     * @var int
40     */
41    protected $formatType;
42
43    /**
44     * Formatter instances
45     *
46     * @var array
47     */
48    protected $formatters = array();
49
50    /**
51     * Locale to use instead of the default
52     *
53     * @var string
54     */
55    protected $locale;
56
57    /**
58     * @throws Exception\ExtensionNotLoadedException if ext/intl is not present
59     */
60    public function __construct()
61    {
62        if (!extension_loaded('intl')) {
63            throw new Exception\ExtensionNotLoadedException(sprintf(
64                '%s component requires the intl PHP extension',
65                __NAMESPACE__
66            ));
67        }
68    }
69
70    /**
71     * Format a number
72     *
73     * @param  int|float $number
74     * @param  int       $formatStyle
75     * @param  int       $formatType
76     * @param  string    $locale
77     * @param  int       $decimals
78     * @return string
79     */
80    public function __invoke(
81        $number,
82        $formatStyle = null,
83        $formatType = null,
84        $locale = null,
85        $decimals = null
86    ) {
87        if (null === $locale) {
88            $locale = $this->getLocale();
89        }
90        if (null === $formatStyle) {
91            $formatStyle = $this->getFormatStyle();
92        }
93        if (null === $formatType) {
94            $formatType = $this->getFormatType();
95        }
96        if (!is_int($decimals) || $decimals < 0) {
97            $decimals = $this->getDecimals();
98        }
99
100        $formatterId = md5($formatStyle . "\0" . $locale . "\0" . $decimals);
101
102        if (!isset($this->formatters[$formatterId])) {
103            $this->formatters[$formatterId] = new NumberFormatter(
104                $locale,
105                $formatStyle
106            );
107
108            if ($decimals !== null) {
109                $this->formatters[$formatterId]->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $decimals);
110                $this->formatters[$formatterId]->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $decimals);
111            }
112        }
113
114        return $this->formatters[$formatterId]->format($number, $formatType);
115    }
116
117    /**
118     * Set format style to use instead of the default
119     *
120     * @param  int $formatStyle
121     * @return NumberFormat
122     */
123    public function setFormatStyle($formatStyle)
124    {
125        $this->formatStyle = (int) $formatStyle;
126        return $this;
127    }
128
129    /**
130     * Get the format style to use
131     *
132     * @return int
133     */
134    public function getFormatStyle()
135    {
136        if (null === $this->formatStyle) {
137            $this->formatStyle = NumberFormatter::DECIMAL;
138        }
139
140        return $this->formatStyle;
141    }
142
143    /**
144     * Set format type to use instead of the default
145     *
146     * @param  int $formatType
147     * @return NumberFormat
148     */
149    public function setFormatType($formatType)
150    {
151        $this->formatType = (int) $formatType;
152        return $this;
153    }
154
155    /**
156     * Get the format type to use
157     *
158     * @return int
159     */
160    public function getFormatType()
161    {
162        if (null === $this->formatType) {
163            $this->formatType = NumberFormatter::TYPE_DEFAULT;
164        }
165        return $this->formatType;
166    }
167
168    /**
169     * Set number of decimals to use instead of the default.
170     *
171     * @param  int $decimals
172     * @return NumberFormat
173     */
174    public function setDecimals($decimals)
175    {
176        $this->decimals = $decimals;
177        return $this;
178    }
179
180    /**
181     * Get number of decimals.
182     *
183     * @return int
184     */
185    public function getDecimals()
186    {
187        return $this->decimals;
188    }
189
190    /**
191     * Set locale to use instead of the default.
192     *
193     * @param  string $locale
194     * @return NumberFormat
195     */
196    public function setLocale($locale)
197    {
198        $this->locale = (string) $locale;
199        return $this;
200    }
201
202    /**
203     * Get the locale to use
204     *
205     * @return string|null
206     */
207    public function getLocale()
208    {
209        if ($this->locale === null) {
210            $this->locale = Locale::getDefault();
211        }
212
213        return $this->locale;
214    }
215}
216