Passed
Push — master ( c0fedc...e8d487 )
by Sebastian
05:21
created

Localization_Currency   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 295
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 85
c 2
b 0
f 0
dl 0
loc 295
rs 10
wmc 30

14 Methods

Rating   Name   Duplication   Size   Complexity  
A getCountry() 0 3 1
A create() 0 9 2
A isCurrencyKnown() 0 3 1
A getID() 0 3 1
A getFormatHint() 0 3 1
A __construct() 0 20 2
A getRegex() 0 21 3
A __toString() 0 3 1
A formatNumber() 0 7 1
A parseNumber() 0 13 2
A getDecimalsSeparator() 0 3 1
A makeReadable() 0 19 5
A getThousandsSeparator() 0 3 1
B tryParseNumber() 0 35 8
1
<?php
2
/**
3
 * File containing the {@link Localization_Currency} class.
4
 * @package Localization
5
 * @subpackage Currencies
6
 * @see Localization_Currency
7
 */
8
9
namespace AppLocalize;
10
11
/**
12
 * Individual currency representation.
13
 *
14
 * @package Localization
15
 * @subpackage Currencies
16
 * @author Sebastian Mordziol <[email protected]>
17
 */
18
abstract class Localization_Currency
19
{
20
    /**
21
     * @var Localization_Country
22
     */
23
    protected $country;
24
25
    /**
26
     * @var string
27
     */
28
    protected $id;
29
30
    /**
31
     * List of supported currencies
32
     * @var array
33
     */
34
    protected static $knownCurrencies = array();
35
36
    protected static $instances = array();
37
38
    /**
39
     * Creates a new currency object for the specified country.
40
     * Note that there is no need to create currency objects
41
     * youself, a country automatically creates one for itself
42
     * so the easiest way is to go through the country/locale
43
     * object.
44
     *
45
     * @param Localization_Country $country
46
     * @return Localization_Currency
47
     */
48
    public static function create($id, Localization_Country $country)
49
    {
50
        if (isset(self::$instances[$id])) {
51
            return self::$instances[$id];
52
        }
53
54
        $className = '\AppLocalize\Localization_Currency_' . $id;
55
56
        return new $className($country);
57
    }
58
59
    protected $decimalsSep;
60
61
    protected $thousandsSep;
62
63
    protected function __construct(Localization_Country $country)
64
    {
65
        $this->country = $country;
66
        
67
        $this->id = str_replace('AppLocalize\Localization_Currency_', '', get_class($this));
68
69
        if ($this->country->getCurrencyID() != $this->id) {
70
            throw new Localization_Exception(
71
                'Country and currency mismatch',
72
                sprintf(
73
                    'Tried creating the currency %1$s for the country %2$s, but that country uses %3$s.',
74
                    $this->id,
75
                    $this->country->getCode(),
76
                    $this->country->getCurrencyID()
77
                )
78
            );
79
        }
80
81
        $this->decimalsSep = $this->country->getNumberDecimalsSeparator();
82
        $this->thousandsSep = $this->country->getNumberThousandsSeparator();
83
    }
84
85
    /**
86
     * Checks whether the specified currency name is known
87
     * (supported by the application)
88
     *
89
     * @param string $currencyName
90
     * @return boolean
91
     */
92
    public static function isCurrencyKnown($currencyName)
93
    {
94
        return file_exists(__DIR__ . '/Currency/' . $currencyName . '.php');
95
    }
96
97
    /**
98
     * @return Localization_Country
99
     */
100
    public function getCountry()
101
    {
102
        return $this->country;
103
    }
104
105
    /**
106
     * The currency name, e.g. "dollar", "euro"
107
     */
108
    public function getID()
109
    {
110
        return $this->id;
111
    }
112
113
    /**
114
     * The singular label of the currency, e.g. "Dollar", "Pound"
115
     * @return string
116
     */
117
    public abstract function getSingular();
118
119
    /**
120
     * The plural label of the currency, e.g. "Dollars", "Pounds"
121
     * @return string
122
     */
123
    public abstract function getPlural();
124
125
    /**
126
     * The currency symbol, e.g. "$", "€"
127
     * @return string
128
     */
129
    public abstract function getSymbol();
130
131
    /**
132
     * Checks if the specified number string is a valid
133
     * numeric notation for this currency.
134
     * @param string|number $number
135
     * @return bool
136
     */
137
    public abstract function isNumberValid($number);
138
    
139
    public abstract function getISO();
140
141
    /**
142
     * A hint that is used in forms to tell the user how the
143
     * numeric notation of the currency should be entered.
144
     * @return string|NULL
145
     */
146
    public function getFormatHint()
147
    {
148
        return null;
149
    }
150
151
    /**
152
     * Returns examples of the currency's numeric notation, as
153
     * an indexed array with examples which are used in forms
154
     * as input help for users.
155
     *
156
     * The optional parameter sets how many decimal positions
157
     * should be included in the examples.
158
     *
159
     * @param int $decimalPositions
160
     * @return array
161
     */
162
    public abstract function getExamples($decimalPositions = 0);
163
164
    /**
165
     * Parses the specified number and returns a currency number
166
     * object which can be used to access the number and its parts
167
     * independently of the human readable notation used.
168
     *
169
     * @param string|number $number
170
     * @return Localization_Currency_Number|FALSE
171
     *
172
     * @see Localization_Currency::parseNumber()
173
     */
174
    public function tryParseNumber($number)
175
    {
176
        if (!is_integer($number)) {
177
            if (!is_string($number) || strlen($number) < 1) {
178
                return false;
179
            }
180
        }
181
182
        $normalized = $number;
0 ignored issues
show
Unused Code introduced by
The assignment to $normalized is dead and can be removed.
Loading history...
183
184
        // number uses the full notation
185
        if (strstr($number, $this->thousandsSep) && strstr($number, $this->decimalsSep)) {
186
            $normalized = str_replace($this->thousandsSep, '', $number);
187
            $normalized = str_replace($this->decimalsSep, '.', $normalized);
188
        } else {
189
            $normalized = str_replace(',', '.', $number);
190
        }
191
192
        $parts = explode('.', $normalized);
193
194
        if (count($parts) > 1) 
195
        {
196
            $decimals = array_pop($parts);
197
            $thousands = floatval(implode('', $parts));
198
            if ($decimals == '-') {
199
                $decimals = 0;
200
            }
201
        } 
202
        else 
203
        {
204
            $decimals = null;
205
            $thousands = floatval(implode('', $parts));
206
        }
207
208
        return new Localization_Currency_Number($thousands, $decimals);
209
    }
210
211
    /**
212
     * @param string|number $number
213
     * @return Localization_Currency_Number
214
     * @throws Localization_Exception
215
     *
216
     * @see Localization_Currency::tryParseNumber()
217
     */
218
    public function parseNumber($number) : Localization_Currency_Number
219
    {
220
        $parsed = $this->tryParseNumber($number);
221
222
        if ($parsed instanceof Localization_Currency_Number) {
223
            return $parsed;
224
        }
225
226
        throw new Localization_Exception(
227
            'Could not parse number',
228
            sprintf(
229
                'The number [%1$s] did not yield a currency number object.',
230
                $number
231
            )
232
        );
233
    }
234
235
    public abstract function isSymbolOnFront();
236
237
    /**
238
     * Returns the singular of the currency label.
239
     *
240
     * @return string
241
     */
242
    public function __toString()
243
    {
244
        return $this->getSingular();
245
    }
246
247
    protected $regex;
248
249
    protected $cachedRegex;
250
251
    protected function getRegex()
252
    {
253
        if (!isset($this->regex)) {
254
            throw new Localization_Exception(
255
                'No regex defined',
256
                sprintf(
257
                    'To use this method, set the regex class property for currency %1$s.',
258
                    $this->getID()
259
                )
260
            );
261
        }
262
263
        if (!isset($this->cachedRegex)) {
264
            $this->cachedRegex = sprintf(
265
                $this->regex,
266
                $this->thousandsSep,
267
                $this->decimalsSep
268
            );
269
        }
270
271
        return $this->cachedRegex;
272
    }
273
274
    public function formatNumber($number, $decimalPositions = 2)
275
    {
276
        return number_format(
277
            $number,
278
            $decimalPositions,
279
            $this->decimalsSep,
280
            $this->thousandsSep
281
        );
282
    }
283
284
    public function getThousandsSeparator()
285
    {
286
        return $this->country->getNumberThousandsSeparator();
287
    }
288
289
    public function getDecimalsSeparator()
290
    {
291
        return $this->country->getNumberDecimalsSeparator();
292
    }
293
294
    public function makeReadable($number, $decimalPositions = 2, $addSymbol=true)
295
    {
296
        if ($number === null || $number === '') {
297
            return null;
298
        }
299
300
        $parsed = $this->parseNumber($number);
301
302
        $number = $this->formatNumber($parsed->getFloat(), $decimalPositions);
303
304
        if(!$addSymbol) {
305
            return $number;
306
        }
307
        
308
        if ($this->isSymbolOnFront()) {
309
            return $this->getSymbol() . ' ' . $number;
310
        }
311
312
        return $number . ' ' . $this->getSymbol();
313
    }
314
}