Completed
Pull Request — master (#7)
by ARCANEDEV
07:42
created

UnitMeasure   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 461
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 36
c 3
b 0
f 0
lcom 1
cbo 2
dl 0
loc 461
ccs 102
cts 102
cp 1
rs 8.8

27 Methods

Rating   Name   Duplication   Size   Complexity  
A make() 0 4 1
A init() 0 12 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 setSymbols() 0 10 3
A symbol() 0 4 1
A setSymbol() 0 8 1
A names() 0 4 1
defaultNames() 0 1 ?
A setNames() 0 10 3
A name() 0 4 1
A getName() 0 6 1
A setName() 0 8 1
A setFormat() 0 8 1
A to() 0 16 2
A convert() 0 4 1
A format() 0 11 4
A formatWithSymbol() 0 7 1
A __toString() 0 4 1
A getRatio() 0 11 2
A getRatios() 0 4 1
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
     * The unit.
22
     *
23
     * @var string
24
     */
25
    protected $unit;
26
27
    /**
28
     * The value.
29
     *
30
     * @var float|int
31
     */
32
    protected $value;
33
34
    /**
35
     * The unit symbols.
36
     *
37
     * @var array
38
     */
39
    protected $symbols  = [];
40
41
    /**
42
     * The unit names.
43
     *
44
     * @var array
45
     */
46
    protected $names  = [];
47
48
    /**
49
     * The number of decimals to format.
50
     *
51
     * @var int
52
     */
53
    protected $decimals = 0;
54
55
    /**
56
     * The decimal separator.
57
     *
58
     * @var string
59
     */
60
    protected $decimalSeparator = '.';
61
62
    /**
63
     * The thousands separator.
64
     *
65
     * @var string
66
     */
67
    protected $thousandsSeparator = ',';
68
69
    /* ------------------------------------------------------------------------------------------------
70
     |  Init Functions
71
     | ------------------------------------------------------------------------------------------------
72
     */
73
    /**
74
     * Make a distance instance.
75
     *
76
     * @param  float|int  $value
77
     * @param  string     $unit
78
     * @param  array      $options
79
     *
80
     * @return static
81
     */
82 384
    public static function make($value = 0, $unit = null, array $options = [])
83
    {
84 384
        return new static($value, $unit, $options);
0 ignored issues
show
Unused Code introduced by
The call to UnitMeasure::__construct() has too many arguments starting with $value.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
85
    }
86
87
    /**
88
     * Initialize the unit.
89
     *
90
     * @param  float|int  $value
91
     * @param  string     $unit
92
     * @param  array      $options
93
     */
94 960
    protected function init($value, $unit, array $options)
95
    {
96 960
        $this->setValue($value);
97 960
        $this->setUnit($unit);
98 960
        $this->setSymbols(Arr::get($options, 'symbols', []));
99 960
        $this->setNames(Arr::get($options, 'names', []));
100 960
        $this->setFormat(
101 960
            Arr::get($options, 'format.decimals', 0),
102 960
            Arr::get($options, 'format.decimal-separator', ','),
103 960
            Arr::get($options, 'format.thousands-separator', '.')
104 720
        );
105 960
    }
106
107
    /* ------------------------------------------------------------------------------------------------
108
     |  Getters & Setters
109
     | ------------------------------------------------------------------------------------------------
110
     */
111
    /**
112
     * Get the unit value.
113
     *
114
     * @return float|int
115
     */
116 784
    public function value()
117
    {
118 784
        return $this->value;
119
    }
120
121
    /**
122
     * Set the unit value.
123
     *
124
     * @param  float|int  $value
125
     *
126
     * @return static
127
     */
128 960
    public function setValue($value)
129
    {
130 960
        $this->value = $value;
131
132 960
        return $this;
133
    }
134
135
    /**
136
     * Get the default units.
137
     *
138
     * @return array
139
     */
140 960
    public static function units()
141
    {
142 960
        $constants = (new ReflectionClass(get_called_class()))
143 960
            ->getConstants();
144
145 960
        return array_values($constants);
146
    }
147
148
    /**
149
     * Get the unit key.
150
     *
151
     * @return string
152
     */
153 544
    public function unit()
154
    {
155 544
        return $this->unit;
156
    }
157
158
    /**
159
     * Set the unit key.
160
     *
161
     * @param  string  $unit
162
     *
163
     * @return static
164
     */
165 960
    public function setUnit($unit)
166
    {
167 960
        static::checkUnit($unit);
168
169 960
        $this->unit = $unit;
170
171 960
        return $this;
172
    }
173
174
    /**
175
     * Get the unit symbols.
176
     *
177
     * @return array
178
     */
179 264
    public function symbols()
180
    {
181 264
        return $this->symbols;
182
    }
183
184
    /**
185
     * Get the default symbols.
186
     *
187
     * @return array
188
     */
189 664
    protected static function defaultSymbols()
190
    {
191 664
        return array_combine(static::units(), static::units());
192
    }
193
194
    /**
195
     * Set the unit symbols.
196
     *
197
     * @param  array  $symbols
198
     *
199
     * @return static
200
     */
201 960
    public function setSymbols(array $symbols)
202
    {
203 960
        if (empty($symbols)) $symbols = static::defaultSymbols();
204
205 960
        foreach ($symbols as $unit => $symbol) {
206 960
            $this->setSymbol($unit, $symbol);
207 720
        }
208
209 960
        return $this;
210
    }
211
212
    /**
213
     * Get the unit symbol.
214
     *
215
     * @return string
216
     */
217 144
    public function symbol()
218
    {
219 144
        return Arr::get($this->symbols(), $this->unit());
220
    }
221
222
    /**
223
     * Set the unit symbol.
224
     *
225
     * @param  string  $unit
226
     * @param  string  $symbol
227
     *
228
     * @return static
229
     */
230 960
    public function setSymbol($unit, $symbol)
231
    {
232 960
        static::checkUnit($unit);
233
234 960
        $this->symbols[$unit] = $symbol;
235
236 960
        return $this;
237
    }
238
239
    /**
240
     * Get the unit names.
241
     *
242
     * @return array
243
     */
244 216
    public function names()
245
    {
246 216
        return $this->names;
247
    }
248
249
    /**
250
     * Get the default names.
251
     *
252
     * @return array
253
     */
254
    abstract protected function defaultNames();
255
256
    /**
257
     * Set the unit names.
258
     *
259
     * @param  array  $names
260
     *
261
     * @return static
262
     */
263 960
    public function setNames(array $names)
264
    {
265 960
        if (empty($names)) $names = $this->defaultNames();
266
267 960
        foreach ($names as $unit => $name) {
268 960
            $this->setName($unit, $name);
269 720
        }
270
271 960
        return $this;
272
    }
273
274
    /**
275
     * Get the unit name.
276
     *
277
     * @return string
278
     */
279 48
    public function name()
280
    {
281 48
        return $this->getName($this->unit());
282
    }
283
284
    /**
285
     * Get the name by a given unit.
286
     *
287
     * @param  string  $unit
288
     *
289
     * @return string
290
     */
291 96
    public function getName($unit)
292
    {
293 96
        static::checkUnit($unit);
294
295 96
        return Arr::get($this->names(), $unit);
296
    }
297
298
    /**
299
     * Set the unit name.
300
     *
301
     * @param  string  $unit
302
     * @param  string  $name
303
     *
304
     * @return static
305
     */
306 960
    public function setName($unit, $name)
307
    {
308 960
        static::checkUnit($unit);
309
310 960
        $this->names[$unit] = $name;
311
312 960
        return $this;
313
    }
314
315
    /**
316
     * Set the format.
317
     *
318
     * @param  int     $decimals
319
     * @param  string  $decimalSeparator
320
     * @param  string  $thousandsSeparator
321
     *
322
     * @return static
323
     */
324 960
    public function setFormat($decimals = 0, $decimalSeparator = ',', $thousandsSeparator = '.')
325
    {
326 960
        $this->decimals           = $decimals;
327 960
        $this->decimalSeparator   = $decimalSeparator;
328 960
        $this->thousandsSeparator = $thousandsSeparator;
329
330 960
        return $this;
331
    }
332
333
    /* ------------------------------------------------------------------------------------------------
334
     |  Main Functions
335
     | ------------------------------------------------------------------------------------------------
336
     */
337
    /**
338
     * Convert the unit to the given unit key.
339
     *
340
     * @param  string  $to
341
     *
342
     * @return \Arcanedev\Units\Contracts\UnitMeasure
343
     */
344 408
    public function to($to)
345
    {
346 408
        if ($to === $this->unit()) return $this;
347
348 120
        $value = static::convert($this->unit(), $to, $this->value());
349
350 120
        return static::make($value, $to, [
351 120
            'symbols' => $this->symbols(),
352 120
            'names'   => $this->names(),
353
            'format'  => [
354 120
                'decimals'            => $this->decimals,
355 120
                'decimal-separator'   => $this->decimalSeparator,
356 120
                'thousands-separator' => $this->thousandsSeparator,
357 90
            ],
358 90
        ]);
359
    }
360
361
    /**
362
     * Convert the unit.
363
     *
364
     * @param  string     $from
365
     * @param  string     $to
366
     * @param  float|int  $value
367
     *
368
     * @return float|int
369
     */
370 120
    public static function convert($from, $to, $value)
371
    {
372 120
        return $value * static::getRatio($to, $from);
373
    }
374
375
    /**
376
     * Format the unit.
377
     *
378
     * @param  int|null     $decimals
379
     * @param  string|null  $decimalSeparator
380
     * @param  string|null  $thousandsSeparator
381
     *
382
     * @return string
383
     */
384 144
    public function format(
385
        $decimals = null,
386
        $decimalSeparator = null,
387
        $thousandsSeparator = null
388
    ) {
389 144
        return number_format($this->value(),
390 144
            is_null($decimals)           ? $this->decimals           : $decimals,
391 144
            is_null($decimalSeparator)   ? $this->decimalSeparator   : $decimalSeparator,
392 144
            is_null($thousandsSeparator) ? $this->thousandsSeparator : $thousandsSeparator
393 108
        );
394
    }
395
396
    /**
397
     * Format the unit with symbol.
398
     *
399
     * @param  int|null     $decimals
400
     * @param  string|null  $decimalSeparator
401
     * @param  string|null  $thousandsSeparator
402
     *
403
     * @return string
404
     */
405 96
    public function formatWithSymbol(
406
        $decimals = null,
407
        $decimalSeparator = null,
408
        $thousandsSeparator = null
409
    ) {
410 96
        return $this->format($decimals, $decimalSeparator, $thousandsSeparator).' '.$this->symbol();
411
    }
412
413
    /**
414
     * Convert object to string.
415
     *
416
     * @return string
417
     */
418 48
    public function __toString()
419
    {
420 48
        return $this->formatWithSymbol();
421
    }
422
423
    /* ------------------------------------------------------------------------------------------------
424
     |  Check Functions
425
     | ------------------------------------------------------------------------------------------------
426
     */
427
    /**
428
     * Get the unit ratio.
429
     *
430
     * @param  string  $to
431
     * @param  string  $from
432
     *
433
     * @return float|int
434
     */
435 48
    protected static function getRatio($to, $from)
436
    {
437 48
        static::checkUnit($from);
438 48
        static::checkUnit($to);
439
440 48
        if ($to === $from) return 1;
441
442 48
        $ratios = static::getRatios();
443
444 48
        return $ratios[$to] / $ratios[$from];
445
    }
446
447
    /**
448
     * Get all the unit ratios.
449
     *
450
     * @codeCoverageIgnore
451
     *
452
     * @return array
453
     */
454
    protected static function getRatios()
455
    {
456
        return [];
457
    }
458
459
    /**
460
     * Check the weight unit.
461
     *
462
     * @param  string  $unit
463
     */
464 960
    protected static function checkUnit($unit)
465
    {
466 960
        if ( ! in_array($unit, static::units())) {
467 48
            $class = static::class;
468
469 48
            throw new InvalidUnitException(
470 48
                "Invalid unit of measurement [{$unit}] in $class."
471 36
            );
472
        }
473 960
    }
474
}
475