Issues (462)

src/variables/UnitsVariable.php (41 issues)

1
<?php
2
/**
3
 * Units plugin for Craft CMS
4
 *
5
 * A plugin for handling physical quantities and the units of measure in which they're represented.
6
 *
7
 * @link      https://nystudio107.com/
0 ignored issues
show
The tag in position 1 should be the @copyright tag
Loading history...
8
 * @copyright Copyright (c) nystudio107
0 ignored issues
show
@copyright tag must contain a year and the name of the copyright holder
Loading history...
9
 */
0 ignored issues
show
PHP version not specified
Loading history...
Missing @category tag in file comment
Loading history...
Missing @package tag in file comment
Loading history...
Missing @author tag in file comment
Loading history...
Missing @license tag in file comment
Loading history...
10
11
namespace nystudio107\units\variables;
12
13
use nystudio107\units\helpers\ClassHelper;
14
use nystudio107\units\models\UnitsData;
15
use PhpUnitsOfMeasure\AbstractPhysicalQuantity;
16
use PhpUnitsOfMeasure\PhysicalQuantity\Acceleration;
17
use PhpUnitsOfMeasure\PhysicalQuantity\Angle;
18
use PhpUnitsOfMeasure\PhysicalQuantity\Area;
19
use PhpUnitsOfMeasure\PhysicalQuantity\ElectricCurrent;
20
use PhpUnitsOfMeasure\PhysicalQuantity\Energy;
21
use PhpUnitsOfMeasure\PhysicalQuantity\Length;
22
use PhpUnitsOfMeasure\PhysicalQuantity\LuminousIntensity;
23
use PhpUnitsOfMeasure\PhysicalQuantity\Mass;
24
use PhpUnitsOfMeasure\PhysicalQuantity\Pressure;
25
use PhpUnitsOfMeasure\PhysicalQuantity\Quantity;
26
use PhpUnitsOfMeasure\PhysicalQuantity\SolidAngle;
27
use PhpUnitsOfMeasure\PhysicalQuantity\Temperature;
28
use PhpUnitsOfMeasure\PhysicalQuantity\Time;
29
use PhpUnitsOfMeasure\PhysicalQuantity\Velocity;
30
use PhpUnitsOfMeasure\PhysicalQuantity\Volume;
31
use PhpUnitsOfMeasure\UnitOfMeasure;
32
use yii\base\InvalidArgumentException;
33
34
/**
0 ignored issues
show
Missing short description in doc comment
Loading history...
35
 * @author    nystudio107
0 ignored issues
show
The tag in position 1 should be the @package tag
Loading history...
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
Tag value for @author tag indented incorrectly; expected 2 spaces but found 4
Loading history...
36
 * @package   Units
0 ignored issues
show
Tag value for @package tag indented incorrectly; expected 1 spaces but found 3
Loading history...
37
 * @since     1.0.0
0 ignored issues
show
The tag in position 3 should be the @author tag
Loading history...
Tag value for @since tag indented incorrectly; expected 3 spaces but found 5
Loading history...
38
 *
39
 * @method Acceleration acceleration($value, string $units)
40
 * @method Angle angle($value, string $units)
41
 * @method Area area($value, string $units)
42
 * @method ElectricCurrent electricCurrent($value, string $units)
43
 * @method Energy energy($value, string $units)
44
 * @method Length length($value, string $units)
45
 * @method LuminousIntensity luminousIntensity($value, string $units)
46
 * @method Mass mass($value, string $units)
47
 * @method Pressure pressure($value, string $units)
48
 * @method Quantity quantity($value, string $units)
49
 * @method SolidAngle solidAngle($value, string $units)
50
 * @method Temperature temperature($value, string $units)
51
 * @method Time time($value, string $units)
52
 * @method Velocity velocity($value, string $units)
53
 * @method Volume volume($value, string $units)
54
 */
0 ignored issues
show
Missing @category tag in class comment
Loading history...
Missing @license tag in class comment
Loading history...
Missing @link tag in class comment
Loading history...
55
class UnitsVariable
56
{
57
    // Public Properties
58
    // =========================================================================
59
60
    /**
0 ignored issues
show
Missing short description in doc comment
Loading history...
61
     * @var array
62
     */
63
    public array $unitsClassMap = [];
64
65
    // Public Methods
66
    // =========================================================================
67
68
    /**
69
     * If the passed in class exists in PhpUnitsOfMeasure\PhysicalQuantity
70
     * return a new instance of the unit of measure
71
     *
72
     * @param $method
0 ignored issues
show
Missing parameter comment
Loading history...
73
     * @param $args
0 ignored issues
show
Missing parameter comment
Loading history...
74
     *
75
     * @return UnitsData
76
     * @throws InvalidArgumentException
77
     */
78
    public function __call($method, $args): UnitsData
79
    {
80
        if (empty($this->unitsClassMap)) {
81
            $this->unitsClassMap = ClassHelper::getClassesInNamespace(Length::class);
82
        }
83
        $unitsClassKey = ucfirst($method);
84
        if (isset($this->unitsClassMap[$unitsClassKey])) {
85
            [$value, $units] = $args;
86
            $config = [
87
                'unitsClass' => $this->unitsClassMap[$unitsClassKey],
88
                'value' => $value,
89
                'units' => $units,
90
            ];
91
92
            return new UnitsData($config);
93
        }
94
95
        throw new InvalidArgumentException("Method {$method} doesn't exist");
96
    }
97
98
    /**
99
     * Outputs a floating point number as a fraction
100
     *
101
     * @param float $value
0 ignored issues
show
Missing parameter comment
Loading history...
102
     *
103
     * @return string
104
     */
105
    public function fraction(float $value): string
106
    {
107
        [$whole, $decimal] = $this->float2parts($value);
108
109
        return $whole . ' ' . $this->float2ratio($decimal);
110
    }
111
112
    /**
113
     * Convert a floating point number to the whole and the decimal
114
     *
115
     * @param float $number
0 ignored issues
show
Missing parameter comment
Loading history...
116
     * @param bool $returnUnsigned
0 ignored issues
show
Expected 2 spaces after parameter type; 1 found
Loading history...
Missing parameter comment
Loading history...
117
     *
118
     * @return array
119
     */
120
    public function float2parts(float $number, bool $returnUnsigned = false): array
121
    {
122
        $negative = 1;
123
        if ($number < 0) {
124
            $negative = -1;
125
            $number *= -1;
126
        }
127
128
        if ($returnUnsigned) {
129
            return [
130
                floor($number),
131
                $number - floor($number),
132
            ];
133
        }
134
135
        return [
136
            floor($number) * $negative,
137
            ($number - floor($number)) * $negative,
138
        ];
139
    }
140
141
    /**
142
     * Convert a floating point number to a ratio
143
     *
144
     * @param float $n
0 ignored issues
show
Missing parameter comment
Loading history...
145
     * @param float $tolerance
0 ignored issues
show
Missing parameter comment
Loading history...
146
     *
147
     * @return string
148
     */
149
    public function float2ratio(float $n, float $tolerance = 1.e-6): string
150
    {
151
        if ($n === 0.0) {
0 ignored issues
show
The condition $n === 0.0 is always false.
Loading history...
152
            return '';
153
        }
154
        $h1 = 1;
155
        $h2 = 0;
156
        $k1 = 0;
157
        $k2 = 1;
158
        $b = 1 / $n;
159
        do {
160
            $b = 1 / $b;
161
            $a = floor($b);
162
            $aux = $h1;
163
            $h1 = $a * $h1 + $h2;
164
            $h2 = $aux;
165
            $aux = $k1;
166
            $k1 = $a * $k1 + $k2;
167
            $k2 = $aux;
168
            $b -= $a;
169
        } while (abs($n - $h1 / $k1) > $n * $tolerance);
170
171
        return "$h1/$k1";
172
    }
173
174
    /**
175
     * Return all of the available units
176
     *
177
     * @param bool $includeAliases whether to include aliases or not
178
     *
179
     * @return array
180
     */
181
    public function allAvailableUnits(bool $includeAliases = false): array
182
    {
183
        $unitsList = [];
184
        $units = ClassHelper::getClassesInNamespace(Length::class);
185
        foreach ($units as $key => $value) {
186
            /** @var AbstractPhysicalQuantity $value */
0 ignored issues
show
The open comment tag must be the only content on the line
Loading history...
Missing short description in doc comment
Loading history...
The close comment tag must be the only content on the line
Loading history...
187
            $unitsList[$key] = $this->availableUnits($value, $includeAliases);
188
        }
189
        ksort($unitsList);
190
191
        return $unitsList;
192
    }
193
194
    /**
195
     * Return the available units for a given AbstractPhysicalQuantity
196
     *
197
     * @param string $unitsClass
0 ignored issues
show
Missing parameter comment
Loading history...
198
     * @param bool $includeAliases whether to include aliases or not
0 ignored issues
show
Expected 3 spaces after parameter type; 1 found
Loading history...
199
     *
200
     * @return array
201
     */
202
    public function availableUnits(string $unitsClass, bool $includeAliases = false): array
203
    {
204
        $availableUnits = [];
205
        if (is_subclass_of($unitsClass, AbstractPhysicalQuantity::class)) {
206
            /** @var array $units */
0 ignored issues
show
The open comment tag must be the only content on the line
Loading history...
Missing short description in doc comment
Loading history...
The close comment tag must be the only content on the line
Loading history...
207
            /** @var AbstractPhysicalQuantity $unitsClass */
0 ignored issues
show
The open comment tag must be the only content on the line
Loading history...
Missing short description in doc comment
Loading history...
The close comment tag must be the only content on the line
Loading history...
208
            $units = $unitsClass::getUnitDefinitions();
209
            /** @var UnitOfMeasure $unit */
0 ignored issues
show
The open comment tag must be the only content on the line
Loading history...
Missing short description in doc comment
Loading history...
The close comment tag must be the only content on the line
Loading history...
210
            foreach ($units as $unit) {
211
                $name = $unit->getName();
212
                $aliases = $unit->getAliases();
213
                $availableUnits[$name] = $includeAliases ? $aliases : $aliases[0] ?? $name;
214
            }
215
        }
216
217
        return $availableUnits;
218
    }
219
}
220