Completed
Push — master ( 2055d4...deb6e5 )
by ARCANEDEV
14s
created

src/Measures/Weight.php (3 issues)

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 namespace Arcanedev\Units\Measures;
2
3
use Arcanedev\Units\Bases\UnitMeasure;
4
use Arcanedev\Units\Contracts\Measures\Weight as WeightContract;
5
use Arcanedev\Units\Traits\Calculatable;
6
use Illuminate\Support\Arr;
7
8
/**
9
 * Class     Weight
10
 *
11
 * @package  Arcanedev\Units
12
 * @author   ARCANEDEV <[email protected]>
13
 */
14
class Weight extends UnitMeasure implements WeightContract
15
{
16
    /* ------------------------------------------------------------------------------------------------
17
     |  Traits
18
     | ------------------------------------------------------------------------------------------------
19
     */
20
    use Calculatable;
21
22
    /* ------------------------------------------------------------------------------------------------
23
     |  Constructor
24
     | ------------------------------------------------------------------------------------------------
25
     */
26
    /**
27
     * Weight constructor.
28
     *
29
     * @param  float|int  $value
30
     * @param  string     $unit
31
     * @param  array      $options
32
     */
33 176
    public function __construct($value = 0, $unit = self::KG, array $options = [])
34
    {
35 176
        $this->setValue($value);
36 176
        $this->setUnit($unit);
37 176
        $this->setSymbols(Arr::get($options, 'symbols', []));
38 176
        $this->setFormat(
39 176
            Arr::get($options, 'decimals', 0),
40 176
            Arr::get($options, 'separators.decimal', ','),
41 176
            Arr::get($options, 'separators.thousands', '.')
42 132
        );
43 176
    }
44
45
    /* ------------------------------------------------------------------------------------------------
46
     |  Getters & Setters
47
     | ------------------------------------------------------------------------------------------------
48
     */
49
    /**
50
     * Get the symbol's names.
51
     *
52
     * @return array
53
     */
54 8
    public static function names()
55
    {
56 8
        return array_combine(static::units(), [
57 8
            'ton',
58 6
            'kilogram',
59 6
            'gram',
60 6
            'milligram',
61 6
        ]);
62
    }
63
64
    /**
65
     * Get the symbol name.
66
     *
67
     * @param  string  $unit
68
     *
69
     * @return string
70
     */
71 8
    public static function getSymbolName($unit)
72
    {
73 8
        static::checkUnit($unit);
74
75 8
        return Arr::get(static::names(), $unit);
76
    }
77
78
    /* ------------------------------------------------------------------------------------------------
79
     |  Main Functions
80
     | ------------------------------------------------------------------------------------------------
81
     */
82
    /**
83
     * Make a weight instance.
84
     *
85
     * @param  float|int  $value
86
     * @param  string     $unit
87
     * @param  array      $options
88
     *
89
     * @return self
90
     */
91 64
    public static function make($value = 0, $unit = self::KG, array $options = [])
92
    {
93 64
        return new static($value, $unit, $options);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new static($value, $unit, $options); (Arcanedev\Units\Measures\Weight) is incompatible with the return type declared by the interface Arcanedev\Units\Contracts\Measures\Weight::make of type Arcanedev\Units\Contracts\Weight.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
94
    }
95
96
    /**
97
     * Convert the weight to the given unit.
98
     *
99
     * @param  string  $to
100
     *
101
     * @return self
102
     */
103 64
    public function to($to)
104
    {
105 64
        if ($to === $this->unit()) return $this;
106
107 16
        $value = static::convert($this->unit(), $to, $this->value());
108
109 16
        return static::make($value, $to);
110
    }
111
112
    /**
113
     * Convert the weight.
114
     *
115
     * @param  string     $from
116
     * @param  string     $to
117
     * @param  float|int  $value
118
     *
119
     * @return float|int
120
     */
121 16
    public static function convert($from, $to, $value)
122
    {
123 16
        return $value * static::getRatio($to, $from);
124
    }
125
126
    /* ------------------------------------------------------------------------------------------------
127
     |  Calculation Functions
128
     | ------------------------------------------------------------------------------------------------
129
     */
130
    /**
131
     * Add the weight.
132
     *
133
     * @param  float|int  $value
134
     * @param  string     $unit
135
     *
136
     * @return self
137
     */
138 16
    public function addWeight($value, $unit = self::KG)
139
    {
140 16
        return $this->add(self::make($value, $unit));
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->add(self::make($value, $unit)); (Arcanedev\Units\Contracts\UnitMeasure) is incompatible with the return type declared by the interface Arcanedev\Units\Contract...sures\Weight::addWeight of type Arcanedev\Units\Contracts\Weight.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
141
    }
142
143
    /**
144
     * Sub the weight.
145
     *
146
     * @param  float|int  $value
147
     * @param  string     $unit
148
     *
149
     * @return self
150
     */
151 16
    public function subWeight($value, $unit = self::KG)
152
    {
153 16
        return $this->sub(static::make($value, $unit));
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->sub(static::make($value, $unit)); (Arcanedev\Units\Contracts\UnitMeasure) is incompatible with the return type declared by the interface Arcanedev\Units\Contract...sures\Weight::subWeight of type Arcanedev\Units\Contracts\Weight.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
154
    }
155
156
    /* ------------------------------------------------------------------------------------------------
157
     |  Other Functions
158
     | ------------------------------------------------------------------------------------------------
159
     */
160
    /**
161
     * Get the weight convert ratio.
162
     *
163
     * @param  string  $to
164
     * @param  string  $from
165
     *
166
     * @return double|float|integer
167
     */
168 16
    protected static function getRatio($to, $from)
169
    {
170 16
        static::checkUnit($from);
171 16
        static::checkUnit($to);
172
173 16
        if ($to === $from) return 1;
174
175 16
        $ratios = static::getRatios();
176
177 16
        return $ratios[$to] / $ratios[$from];
178
    }
179
180
    /**
181
     * Get all the weight ratios.
182
     *
183
     * @return array
184
     */
185 16
    protected static function getRatios()
186
    {
187 16
        $rate   = 1000;
188
        $ratios = [
189 16
            static::TON => 0,
190 16
            static::KG  => 1,
191 16
            static::G   => 2,
192 16
            static::MG  => 3,
193 12
        ];
194
195 16
        return array_map(function ($ratio) use ($rate) {
196 16
            return static::calculate($rate, '^', $ratio);
197 16
        }, $ratios);
198
    }
199
}
200