UnitMeasure   B
last analyzed

Complexity

Total Complexity 37

Size/Duplication

Total Lines 480
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 37
lcom 1
cbo 2
dl 0
loc 480
ccs 98
cts 98
cp 1
rs 8.6
c 0
b 0
f 0

28 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A make() 0 4 1
A value() 0 4 1
A setValue() 0 6 1
A units() 0 7 1
A unit() 0 4 1
A setUnit() 0 8 1
A symbols() 0 4 1
A defaultSymbols() 0 4 1
A symbol() 0 4 1
A setSymbol() 0 8 1
A names() 0 4 1
defaultNames() 0 1 ?
A name() 0 4 1
A getName() 0 6 1
A setName() 0 8 1
A setFormat() 0 8 1
A convert() 0 4 1
A formatWithSymbol() 0 7 1
A __toString() 0 4 1
A getRatio() 0 11 2
A getRatios() 0 4 1
A init() 0 12 1
A setSymbols() 0 10 3
A setNames() 0 10 3
A to() 0 16 2
A format() 0 11 4
A checkUnit() 0 10 2
1
<?php namespace Arcanedev\Units\Bases;
2
3
use Arcanedev\Units\Contracts\UnitMeasure as UnitMeasureContract;
4
use Arcanedev\Units\Exceptions\InvalidUnitException;
5
use Illuminate\Support\Arr;
6
use ReflectionClass;
7
8
/**
9
 * Class     UnitMeasure
10
 *
11
 * @package  Arcanedev\Units\Base
12
 * @author   ARCANEDEV <[email protected]>
13
 */
14
abstract class UnitMeasure implements UnitMeasureContract
15
{
16
    /* -----------------------------------------------------------------
17
     |  Properties
18
     | -----------------------------------------------------------------
19
     */
20
21
    /**
22
     * The unit.
23
     *
24
     * @var string
25
     */
26
    protected $unit;
27
28
    /**
29
     * The value.
30
     *
31
     * @var float|int
32
     */
33
    protected $value;
34
35
    /**
36
     * The unit symbols.
37
     *
38
     * @var array
39
     */
40
    protected $symbols  = [];
41
42
    /**
43
     * The unit names.
44
     *
45
     * @var array
46
     */
47
    protected $names  = [];
48
49
    /**
50
     * The number of decimals to format.
51
     *
52
     * @var int
53
     */
54
    protected $decimals = 0;
55
56
    /**
57
     * The decimal separator.
58
     *
59
     * @var string
60
     */
61
    protected $decimalSeparator = '.';
62
63
    /**
64
     * The thousands separator.
65
     *
66
     * @var string
67
     */
68
    protected $thousandsSeparator = ',';
69
70
    /* -----------------------------------------------------------------
71
     |  Constructor
72
     | -----------------------------------------------------------------
73
     */
74
75
    /**
76
     * UnitMeasure constructor.
77
     *
78
     * @param  float|int  $value
79
     * @param  string     $unit
80
     * @param  array      $options
81
     */
82 267
    public function __construct($value = 0, $unit = '', array $options = [])
83
    {
84 267
        $this->init($value, $unit, $options);
85 267
    }
86
87
    /* -----------------------------------------------------------------
88
     |  Main Methods
89
     | -----------------------------------------------------------------
90
     */
91
92
    /**
93
     * Make a distance instance.
94
     *
95
     * @param  float|int  $value
96
     * @param  string     $unit
97
     * @param  array      $options
98
     *
99
     * @return static
100
     */
101 105
    public static function make($value = 0, $unit = null, array $options = [])
102
    {
103 105
        return new static($value, $unit, $options);
104
    }
105
106
    /**
107
     * Initialize the unit.
108
     *
109
     * @param  float|int  $value
110
     * @param  string     $unit
111
     * @param  array      $options
112
     */
113 267
    protected function init($value, $unit, array $options)
114
    {
115 267
        $this->setValue($value);
116 267
        $this->setUnit($unit);
117 267
        $this->setSymbols(Arr::get($options, 'symbols', []));
118 267
        $this->setNames(Arr::get($options, 'names', []));
119 267
        $this->setFormat(
120 267
            Arr::get($options, 'format.decimals', 0),
121 267
            Arr::get($options, 'format.decimal-separator', ','),
122 267
            Arr::get($options, 'format.thousands-separator', '.')
123
        );
124 267
    }
125
126
    /* ------------------------------------------------------------------------------------------------
127
     |  Getters & Setters
128
     | ------------------------------------------------------------------------------------------------
129
     */
130
    /**
131
     * Get the unit value.
132
     *
133
     * @return float|int
134
     */
135 204
    public function value()
136
    {
137 204
        return $this->value;
138
    }
139
140
    /**
141
     * Set the unit value.
142
     *
143
     * @param  float|int  $value
144
     *
145
     * @return static
146
     */
147 267
    public function setValue($value)
148
    {
149 267
        $this->value = $value;
150
151 267
        return $this;
152
    }
153
154
    /**
155
     * Get the default units.
156
     *
157
     * @return array
158
     */
159 267
    public static function units()
160
    {
161 267
        $constants = (new ReflectionClass(get_called_class()))
162 267
            ->getConstants();
163
164 267
        return array_values($constants);
165
    }
166
167
    /**
168
     * Get the unit key.
169
     *
170
     * @return string
171
     */
172 144
    public function unit()
173
    {
174 144
        return $this->unit;
175
    }
176
177
    /**
178
     * Set the unit key.
179
     *
180
     * @param  string  $unit
181
     *
182
     * @return static
183
     */
184 267
    public function setUnit($unit)
185
    {
186 267
        static::checkUnit($unit);
187
188 267
        $this->unit = $unit;
189
190 267
        return $this;
191
    }
192
193
    /**
194
     * Get the unit symbols.
195
     *
196
     * @return array
197
     */
198 72
    public function symbols()
199
    {
200 72
        return $this->symbols;
201
    }
202
203
    /**
204
     * Get the default symbols.
205
     *
206
     * @return array
207
     */
208 252
    protected static function defaultSymbols()
209
    {
210 252
        return array_combine(static::units(), static::units());
211
    }
212
213
    /**
214
     * Set the unit symbols.
215
     *
216
     * @param  array  $symbols
217
     *
218
     * @return static
219
     */
220 267
    public function setSymbols(array $symbols)
221
    {
222 267
        if (empty($symbols)) $symbols = static::defaultSymbols();
223
224 267
        foreach ($symbols as $unit => $symbol) {
225 267
            $this->setSymbol($unit, $symbol);
226
        }
227
228 267
        return $this;
229
    }
230
231
    /**
232
     * Get the unit symbol.
233
     *
234
     * @return string
235
     */
236 36
    public function symbol()
237
    {
238 36
        return Arr::get($this->symbols(), $this->unit());
239
    }
240
241
    /**
242
     * Set the unit symbol.
243
     *
244
     * @param  string  $unit
245
     * @param  string  $symbol
246
     *
247
     * @return static
248
     */
249 267
    public function setSymbol($unit, $symbol)
250
    {
251 267
        static::checkUnit($unit);
252
253 267
        $this->symbols[$unit] = $symbol;
254
255 267
        return $this;
256
    }
257
258
    /**
259
     * Get the unit names.
260
     *
261
     * @return array
262
     */
263 57
    public function names()
264
    {
265 57
        return $this->names;
266
    }
267
268
    /**
269
     * Get the default names.
270
     *
271
     * @return array
272
     */
273
    abstract public function defaultNames();
274
275
    /**
276
     * Set the unit names.
277
     *
278
     * @param  array  $names
279
     *
280
     * @return static
281
     */
282 267
    public function setNames(array $names)
283
    {
284 267
        if (empty($names)) $names = $this->defaultNames();
285
286 267
        foreach ($names as $unit => $name) {
287 267
            $this->setName($unit, $name);
288
        }
289
290 267
        return $this;
291
    }
292
293
    /**
294
     * Get the unit name.
295
     *
296
     * @return string
297
     */
298 12
    public function name()
299
    {
300 12
        return $this->getName($this->unit());
301
    }
302
303
    /**
304
     * Get the name by a given unit.
305
     *
306
     * @param  string  $unit
307
     *
308
     * @return string
309
     */
310 24
    public function getName($unit)
311
    {
312 24
        static::checkUnit($unit);
313
314 24
        return Arr::get($this->names(), $unit);
315
    }
316
317
    /**
318
     * Set the unit name.
319
     *
320
     * @param  string  $unit
321
     * @param  string  $name
322
     *
323
     * @return static
324
     */
325 267
    public function setName($unit, $name)
326
    {
327 267
        static::checkUnit($unit);
328
329 267
        $this->names[$unit] = $name;
330
331 267
        return $this;
332
    }
333
334
    /**
335
     * Set the format.
336
     *
337
     * @param  int     $decimals
338
     * @param  string  $decimalSeparator
339
     * @param  string  $thousandsSeparator
340
     *
341
     * @return static
342
     */
343 267
    public function setFormat($decimals = 0, $decimalSeparator = ',', $thousandsSeparator = '.')
344
    {
345 267
        $this->decimals           = $decimals;
346 267
        $this->decimalSeparator   = $decimalSeparator;
347 267
        $this->thousandsSeparator = $thousandsSeparator;
348
349 267
        return $this;
350
    }
351
352
    /* ------------------------------------------------------------------------------------------------
353
     |  Main Functions
354
     | ------------------------------------------------------------------------------------------------
355
     */
356
    /**
357
     * Convert the unit to the given unit key.
358
     *
359
     * @param  string  $to
360
     *
361
     * @return \Arcanedev\Units\Contracts\UnitMeasure
362
     */
363 105
    public function to($to)
364
    {
365 105
        if ($to === $this->unit()) return $this;
366
367 33
        $value = static::convert($this->unit(), $to, $this->value());
368
369 33
        return static::make($value, $to, [
370 33
            'symbols' => $this->symbols(),
371 33
            'names'   => $this->names(),
372
            'format'  => [
373 33
                'decimals'            => $this->decimals,
374 33
                'decimal-separator'   => $this->decimalSeparator,
375 33
                'thousands-separator' => $this->thousandsSeparator,
376
            ],
377
        ]);
378
    }
379
380
    /**
381
     * Convert the unit.
382
     *
383
     * @param  string     $from
384
     * @param  string     $to
385
     * @param  float|int  $value
386
     *
387
     * @return float|int
388
     */
389 33
    public static function convert($from, $to, $value)
390
    {
391 33
        return $value * static::getRatio($to, $from);
392
    }
393
394
    /**
395
     * Format the unit.
396
     *
397
     * @param  int|null     $decimals
398
     * @param  string|null  $decimalSeparator
399
     * @param  string|null  $thousandsSeparator
400
     *
401
     * @return string
402
     */
403 36
    public function format(
404
        $decimals = null,
405
        $decimalSeparator = null,
406
        $thousandsSeparator = null
407
    ) {
408 36
        return number_format($this->value(),
409 36
            is_null($decimals)           ? $this->decimals           : $decimals,
410 36
            is_null($decimalSeparator)   ? $this->decimalSeparator   : $decimalSeparator,
411 36
            is_null($thousandsSeparator) ? $this->thousandsSeparator : $thousandsSeparator
412
        );
413
    }
414
415
    /**
416
     * Format the unit with symbol.
417
     *
418
     * @param  int|null     $decimals
419
     * @param  string|null  $decimalSeparator
420
     * @param  string|null  $thousandsSeparator
421
     *
422
     * @return string
423
     */
424 24
    public function formatWithSymbol(
425
        $decimals = null,
426
        $decimalSeparator = null,
427
        $thousandsSeparator = null
428
    ) {
429 24
        return $this->format($decimals, $decimalSeparator, $thousandsSeparator).' '.$this->symbol();
430
    }
431
432
    /**
433
     * Convert object to string.
434
     *
435
     * @return string
436
     */
437 12
    public function __toString()
438
    {
439 12
        return $this->formatWithSymbol();
440
    }
441
442
    /* ------------------------------------------------------------------------------------------------
443
     |  Check Functions
444
     | ------------------------------------------------------------------------------------------------
445
     */
446
    /**
447
     * Get the unit ratio.
448
     *
449
     * @param  string  $to
450
     * @param  string  $from
451
     *
452
     * @return float|int
453
     */
454 18
    protected static function getRatio($to, $from)
455
    {
456 18
        static::checkUnit($from);
457 18
        static::checkUnit($to);
458
459 18
        if ($to === $from) return 1;
460
461 18
        $ratios = static::getRatios();
462
463 18
        return $ratios[$to] / $ratios[$from];
464
    }
465
466
    /**
467
     * Get all the unit ratios.
468
     *
469
     * @codeCoverageIgnore
470
     *
471
     * @return array
472
     */
473
    protected static function getRatios()
474
    {
475
        return [];
476
    }
477
478
    /**
479
     * Check the weight unit.
480
     *
481
     * @param  string  $unit
482
     */
483 267
    protected static function checkUnit($unit)
484
    {
485 267
        if ( ! in_array($unit, static::units())) {
486 12
            $class = static::class;
487
488 12
            throw new InvalidUnitException(
489 12
                "Invalid unit of measurement [{$unit}] in $class."
490
            );
491
        }
492 267
    }
493
}
494