Completed
Push — master ( 2a7a8a...bafaf6 )
by ARCANEDEV
06:19
created

Weight   B

Complexity

Total Complexity 37

Size/Duplication

Total Lines 505
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 37
c 2
b 0
f 0
lcom 1
cbo 3
dl 0
loc 505
ccs 125
cts 125
cp 1
rs 8.6

29 Methods

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