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

src/Measures/LiquidVolume.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\LiquidVolume as LiquidVolumeContract;
5
use Arcanedev\Units\Traits\Calculatable;
6
use Illuminate\Support\Arr;
7
8
/**
9
 * Class     LiquidVolume
10
 *
11
 * @package  Arcanedev\Units\Measures
12
 * @author   ARCANEDEV <[email protected]>
13
 */
14
class LiquidVolume extends UnitMeasure implements LiquidVolumeContract
15
{
16
    /* ------------------------------------------------------------------------------------------------
17
     |  Traits
18
     | ------------------------------------------------------------------------------------------------
19
     */
20
    use Calculatable;
21
22
    /* ------------------------------------------------------------------------------------------------
23
     |  Constructor
24
     | ------------------------------------------------------------------------------------------------
25
     */
26
    /**
27
     * Volume 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::L, 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
            'kilolitre',
58 6
            'hectolitre',
59 6
            'decalitre',
60 6
            'litre',
61 6
            'decilitre',
62 6
            'centilitre',
63 6
            'millilitre',
64 6
        ]);
65
    }
66
67
    /**
68
     * Get the symbol name.
69
     *
70
     * @param  string  $unit
71
     *
72
     * @return string
73
     */
74 8
    public static function getSymbolName($unit)
75
    {
76 8
        static::checkUnit($unit);
77
78 8
        return Arr::get(static::names(), $unit);
79
    }
80
81
    /* ------------------------------------------------------------------------------------------------
82
     |  Main Functions
83
     | ------------------------------------------------------------------------------------------------
84
     */
85
    /**
86
     * Make a volume instance.
87
     *
88
     * @param  float|int  $value
89
     * @param  string     $unit
90
     * @param  array      $options
91
     *
92
     * @return \Arcanedev\Units\Contracts\Measures\LiquidVolume
93
     */
94 72
    public static function make($value = 0, $unit = self::L, array $options = [])
95
    {
96 72
        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\LiquidVolume) is incompatible with the return type declared by the interface Arcanedev\Units\Contract...ures\LiquidVolume::make of type Arcanedev\Units\Contracts\LiquidVolume.

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...
97
    }
98
99
    /**
100
     * Convert the volume to the given unit.
101
     *
102
     * @param  string  $to
103
     *
104
     * @return \Arcanedev\Units\Contracts\Measures\LiquidVolume
105
     */
106 72
    public function to($to)
107
    {
108 72
        if ($to === $this->unit()) return $this;
109
110 24
        $value = static::convert($this->unit(), $to, $this->value());
111
112 24
        return static::make($value, $to);
113
    }
114
115
    /**
116
     * Convert the volume.
117
     *
118
     * @param  string     $from
119
     * @param  string     $to
120
     * @param  float|int  $value
121
     *
122
     * @return float|int
123
     */
124 24
    public static function convert($from, $to, $value)
125
    {
126 24
        return $value * static::getRatio($to, $from);
127
    }
128
129
    /* ------------------------------------------------------------------------------------------------
130
     |  Calculation Functions
131
     | ------------------------------------------------------------------------------------------------
132
     */
133
    /**
134
     * Add the volume.
135
     *
136
     * @param  float|int  $value
137
     * @param  string     $unit
138
     *
139
     * @return \Arcanedev\Units\Contracts\Measures\LiquidVolume
140
     */
141 16
    public function addVolume($value, $unit = self::L)
142
    {
143 16
        return $this->add(
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...LiquidVolume::addVolume of type Arcanedev\Units\Contracts\LiquidVolume.

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...
144 16
            self::make($value, $unit)
145 12
        );
146
    }
147
148
    /**
149
     * Sub the volume.
150
     *
151
     * @param  float|int  $value
152
     * @param  string     $unit
153
     *
154
     * @return \Arcanedev\Units\Contracts\Measures\LiquidVolume
155
     */
156 16
    public function subVolume($value, $unit = self::L)
157
    {
158 16
        return $this->sub(
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...LiquidVolume::subVolume of type Arcanedev\Units\Contracts\LiquidVolume.

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...
159 16
            static::make($value, $unit)
160 12
        );
161
    }
162
163
    /* ------------------------------------------------------------------------------------------------
164
     |  Other Functions
165
     | ------------------------------------------------------------------------------------------------
166
     */
167
    /**
168
     * Get the volume convert ratio.
169
     *
170
     * @param  string  $to
171
     * @param  string  $from
172
     *
173
     * @return float|int
174
     */
175 24
    protected static function getRatio($to, $from)
176
    {
177 24
        static::checkUnit($from);
178 24
        static::checkUnit($to);
179
180 24
        if ($to === $from) return 1;
181
182 24
        $ratios = static::getRatios();
183
184 24
        return $ratios[$to] / $ratios[$from];
185
    }
186
187
    /**
188
     * Get all the volume ratios.
189
     *
190
     * @return array
191
     */
192 24
    protected static function getRatios()
193
    {
194 24
        $rate   = 10;
195
        $ratios = [
196 24
            static::KL  => 0,
197 24
            static::HL  => 1,
198 24
            static::DAL => 2,
199 24
            static::L   => 3,
200 24
            static::DL  => 4,
201 24
            static::CL  => 5,
202 24
            static::ML  => 6,
203 18
        ];
204
205 24
        return array_map(function ($ratio) use ($rate) {
206 24
            return static::calculate($rate, '^', $ratio);
207 24
        }, $ratios);
208
    }
209
}
210