Completed
Push — master ( 79000f...ecfa5f )
by Sébastien
02:41
created

Soluble/FlexStore/Formatter/NumberFormatter.php (1 issue)

Checks function declaration argument spacing space after default

Coding Style Informational

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * soluble-flexstore library
7
 *
8
 * @author    Vanvelthem Sébastien
9
 * @link      https://github.com/belgattitude/soluble-flexstore
10
 * @copyright Copyright (c) 2016-2017 Vanvelthem Sébastien
11
 * @license   MIT License https://github.com/belgattitude/soluble-flexstore/blob/master/LICENSE.md
12
 *
13
 */
14
15
namespace Soluble\FlexStore\Formatter;
16
17
use Soluble\FlexStore\Exception;
18
use Soluble\FlexStore\I18n\LocalizableInterface;
19
use ArrayObject;
20
use Locale;
21
use NumberFormatter as IntlNumberFormatter;
22
23
class NumberFormatter implements FormatterInterface, LocalizableInterface, FormatterNumberInterface
24
{
25
    public const NO_BREAK_SPACE_HEX = 'c2a0';
26
    public const NARROW_NO_BREAK_SPACE_HEX = 'e280af';
27
28
    /**
29
     * Formatter instances.
30
     *
31
     * @var array
32
     */
33
    protected $formatters = [];
34
35
    /**
36
     * @var array
37
     */
38
    protected $params = [];
39
40
    /**
41
     * @var array
42
     */
43
    protected $default_params = [
44
        'decimals' => 2,
45
        'locale' => null,
46
        'pattern' => null,
47
        'disableUseOfNonBreakingSpaces' => false
48
    ];
49
50
    /**
51
     * @param array $params
52
     *
53
     * @throws Exception\ExtensionNotLoadedException if ext/intl is not present
54
     * @throws Exception\InvalidArgumentException
55
     */
56 24
    public function __construct(array $params = [])
57
    {
58 24
        if (!extension_loaded('intl')) {
59
            throw new Exception\ExtensionNotLoadedException(sprintf(
60
                '%s component requires the intl PHP extension',
61
                __NAMESPACE__
62
            ));
63
        }
64
65
        // As default locale may include unsupported
66
        // variants (like 'en_US_POSIX' for example),
67
        // only the 5 chars will be taken into consideration
68
69 24
        $default_locale = Locale::getDefault();
70 24
        $this->default_params['locale'] = substr($default_locale, 0, 5);
71 24
        $this->setParams($params);
72 24
    }
73
74
    /**
75
     * @throws Exception\InvalidArgumentException
76
     *
77
     * @param array $params
78
     */
79 24
    protected function setParams($params)
80
    {
81 24
        $this->params = $this->default_params;
82 24
        foreach ($params as $name => $value) {
83 17
            $method = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', strtolower($name))));
84 17
            if (!method_exists($this, $method)) {
85 3
                throw new Exception\InvalidArgumentException(__METHOD__ . " Parameter '$name' does not exists.");
86
            }
87 14
            $this->$method($value);
88
        }
89 24
    }
90
91 12
    protected function initWhitespaceSeparator(IntlNumberFormatter $formatter): void
92
    {
93 12
        if ($this->params['disableUseOfNonBreakingSpaces'] === true
94 3
        && in_array(bin2hex($formatter->getSymbol(IntlNumberFormatter::GROUPING_SEPARATOR_SYMBOL)), [
95 3
                self::NARROW_NO_BREAK_SPACE_HEX,
96 3
                self::NO_BREAK_SPACE_HEX
97 12
            ], true)) {
98
99 3
            $formatter->setSymbol(IntlNumberFormatter::GROUPING_SEPARATOR_SYMBOL, ' ');
100
        }
101 12
    }
102
103 6
    protected function loadFormatterId(string $formatterId): void
104
    {
105 6
        $locale = $this->params['locale'];
106 6
        $formatter = new IntlNumberFormatter(
107 6
            $locale,
108 6
            IntlNumberFormatter::DECIMAL
109
        );
110 6
        $formatter->setAttribute(IntlNumberFormatter::FRACTION_DIGITS, $this->params['decimals']);
111 6
        if ($this->params['pattern'] !== null) {
112 2
            $formatter->setPattern($this->params['pattern']);
113
        }
114
115 6
        $this->initWhitespaceSeparator($formatter);
116
117 6
        $this->formatters[$formatterId] = $formatter;
118 6
    }
119
120
    /**
121
     * Format a number.
122
     *
123
     * @param float $number
124
     *
125
     * @return string
126
     */
127 3
    public function format($number, ArrayObject $row = null): string
128
    {
129 3
        $locale = $this->params['locale'];
130
        //$formatterId = md5($locale);
131 3
        $formatterId = $locale . (string) $this->params['pattern'];
132 3
        if (!array_key_exists($formatterId, $this->formatters)) {
133 3
            $this->loadFormatterId($formatterId);
134
        }
135
136 3
        if (!is_numeric($number)) {
137 2
            $this->throwNumberFormatterException($this->formatters[$formatterId], $number);
138
        }
139
140 1
        return $this->formatters[$formatterId]->format($number);
141
    }
142
143
    /**
144
     * Throws an Exception when number cannot be formatted.
145
     *
146
     * @param IntlNumberFormatter $intlFormatter
147
     * @param int|string|float    $number
148
     *
149
     * @throws Exception\RuntimeException
150
     */
151 4
    protected function throwNumberFormatterException(IntlNumberFormatter $intlFormatter, $number): void
152
    {
153 4
        $error_code = $intlFormatter->getErrorCode();
154 4
        if (is_scalar($number)) {
155 2
            $val = (string) $number;
156
        } else {
157 2
            $val = 'type: ' . gettype($number);
158
        }
159 4
        throw new Exception\RuntimeException(__METHOD__ . " Cannot format value '$val', Intl/NumberFormatter error code: $error_code.");
160
    }
161
162
    /**
163
     * Set locale to use instead of the default.
164
     *
165
     * @param string $locale
166
     */
167 17
    public function setLocale(?string $locale): self
168
    {
169 17
        $this->params['locale'] = $locale;
170
171 17
        return $this;
172
    }
173
174
    /**
175
     * Get the locale to use.
176
     *
177
     * @return string|null
178
     */
179 6
    public function getLocale(): ?string
180
    {
181 6
        return $this->params['locale'];
182
    }
183
184
    /**
185
     * Set decimals.
186
     *
187
     * @param int $decimals
188
     */
189 15
    public function setDecimals($decimals): self
190
    {
191 15
        $this->params['decimals'] = $decimals;
192
193 15
        return $this;
194
    }
195
196
    /**
197
     * @return int
198
     */
199 6
    public function getDecimals(): int
200
    {
201 6
        return $this->params['decimals'];
202
    }
203
204
    /**
205
     * Set the number pattern, (#,##0.###, ....).
206
     *
207
     * @see http://php.net/manual/en/numberformatter.setpattern.php
208
     *
209
     * @param string $pattern
210
     */
211 8
    public function setPattern($pattern): self
212
    {
213 8
        $this->params['pattern'] = $pattern;
214
215 8
        return $this;
216
    }
217
218
    /**
219
     * Get the number pattern.
220
     *
221
     * @return string|null
222
     */
223 6
    public function getPattern(): ?string
224
    {
225 6
        return $this->params['pattern'];
226
    }
227
228 3
    public function setDisableUseOfNonBreakingSpaces(bool $disable=true): self {
0 ignored issues
show
Incorrect spacing between default value and equals sign for argument "$disable"; expected 1 but found 0
Loading history...
229 3
        $this->params['disableUseOfNonBreakingSpaces'] = $disable;
230 3
        return $this;
231
    }
232
}
233