Failed Conditions
Pull Request — master (#1)
by Chad
02:07
created

Floats::ensureValueInRange()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 3
nop 3
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace TraderInteractive\Filter;
4
5
use TraderInteractive\Exceptions\FilterException;
6
7
/**
8
 * A collection of filters for floats.
9
 */
10
final class Floats
11
{
12
    /**
13
     * Filters $value to a float strictly.
14
     *
15
     * The return value is the float, as expected by the \TraderInteractive\Filterer class.
16
     *
17
     * @param mixed $value     The value to filter to a float.
18
     * @param bool  $allowNull Set to true if NULL values are allowed. The filtered result of a NULL value is NULL.
19
     * @param float $minValue  The minimum acceptable value.
20
     * @param float $maxValue  The maximum acceptable value.
21
     * @param bool  $castInts  Flag to cast $value to float if it is an integer.
22
     *
23
     * @return float|null The filtered value
24
     *
25
     * @throws FilterException Thrown if the given value cannot be filtered to a float.
26
     */
27
    public static function filter(
28
        $value,
29
        bool $allowNull = false,
30
        float $minValue = null,
31
        float $maxValue = null,
32
        bool $castInts = false
33
    ) {
34
        if ($allowNull === true && $value === null) {
35
            return null;
36
        }
37
38
        $valueFloat = null;
39
        if (is_float($value)) {
40
            $valueFloat = $value;
41
        } elseif (is_int($value) && $castInts) {
42
            $valueFloat = (float)$value;
43
        } elseif (is_string($value)) {
44
            $valueFloat = self::fromString($value);
45
        } else {
46
            throw new FilterException('"' . var_export($value, true) . '" $value is not a string');
47
        }
48
49
        if (is_infinite($valueFloat)) {
50
            throw new FilterException("{$value} overflow");
51
        }
52
53
        return self::ensureValueInRange($valueFloat, $minValue ?? -INF, $maxValue ?? INF);
54
    }
55
56
    private static function fromString(string $value) : float
57
    {
58
        $value = strtolower(trim($value));
59
        if (!is_numeric($value)) {
60
            throw new FilterException("{$value} does not pass is_numeric");
61
        }
62
63
        //This is the only case (that we know of) where is_numeric does not return correctly cast-able float
64
        if (strpos($value, 'x') !== false) {
65
            throw new FilterException("{$value} is hex format");
66
        }
67
68
        return (float)$value;
69
    }
70
71
    private static function ensureValueInRange(float $value, float $minValue, float $maxValue) : float
72
    {
73
        if ($value < $minValue) {
74
            throw new FilterException("{$value} is less than {$minValue}");
75
        }
76
77
        if ($value > $maxValue) {
78
            throw new FilterException("{$value} is greater than {$maxValue}");
79
        }
80
81
        return $value;
82
    }
83
}
84