Failed Conditions
Pull Request — master (#1)
by
unknown
01:55
created

Ints::handleStringValues()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 9
rs 9.6666
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 integers.
9
 */
10
final class Ints
11
{
12
    /**
13
     * Filters $value to an integer strictly.
14
     *
15
     * $value must be an int or contain all digits, optionally prepended by a '+' or '-' and optionally surrounded by
16
     * whitespace to pass the filter.
17
     *
18
     * The return value is the int, as expected by the \TraderInteractive\Filterer class.
19
     *
20
     * @param string|int $value     the value to make an integer
21
     * @param bool       $allowNull Set to true if NULL values are allowed. The filtered result of a NULL value is NULL
22
     * @param int        $minValue  The minimum acceptable value
23
     * @param int        $maxValue  The maximum acceptable value
24
     *
25
     * @return int|null The filtered value
26
     *
27
     * @throws FilterException if $value string length is zero
28
     * @throws FilterException if $value does not contain all digits, optionally prepended by a '+' or '-' and
29
     *                         optionally surrounded by whitespace
30
     * @throws FilterException if $value was greater than a max int of PHP_INT_MAX
31
     * @throws FilterException if $value was less than a min int of ~PHP_INT_MAX
32
     * @throws FilterException if $value is not a string
33
     * @throws FilterException if $value is less than $minValue
34
     * @throws FilterException if $value is greater than $maxValue
35
     */
36
    public static function filter($value, bool $allowNull = false, int $minValue = null, int $maxValue = PHP_INT_MAX)
37
    {
38
        if (self::valueIsNullAndValid($allowNull, $value)) {
39
            return null;
40
        }
41
42
        $valueInt = self::getValueInt($value);
43
44
        if ($minValue !== null && $valueInt < $minValue) {
45
            throw new FilterException("{$valueInt} is less than {$minValue}");
46
        }
47
48
        if ($valueInt > $maxValue) {
49
            throw new FilterException("{$valueInt} is greater than {$maxValue}");
50
        }
51
52
        return $valueInt;
53
    }
54
55
    private static function valueIsNullAndValid(bool $allowNull, $value = null) : bool
56
    {
57
        if ($allowNull === false && $value === null) {
58
            throw new FilterException('Value failed filtering, $allowNull is set to false');
59
        }
60
        return $allowNull === true && $value === null;
61
    }
62
63
    private static function getValueInt($value) : int
64
    {
65
        $valueInt = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $valueInt is dead and can be removed.
Loading history...
66
        if (is_int($value)) {
67
            return $value;
68
        }
69
70
        if (is_string($value)) {
71
            return self::handleStringValues($value);
72
        }
73
74
        throw new FilterException('"' . var_export($value, true) . '" $value is not a string');
75
    }
76
77
    private static function handleStringValues(string $value) : int
78
    {
79
        $value = trim($value);
80
81
        self::enforceStringLength($value);
82
        self::checkDigits($value);
83
        $casted = self::castAndEnforceValidIntegerSize($value);
84
85
        return $casted;
86
    }
87
88
    private static function enforceStringLength(string $value)
89
    {
90
        if (strlen($value) === 0) {
91
            throw new FilterException('$value string length is zero');
92
        }
93
    }
94
95
    private static function checkDigits(string $value)
96
    {
97
        $stringToCheckDigits = $value;
98
99
        if ($value[0] === '-' || $value[0] === '+') {
100
            $stringToCheckDigits = substr($value, 1);
101
        }
102
103
        if (!ctype_digit($stringToCheckDigits)) {
104
            throw new FilterException(
105
                "{$value} does not contain all digits, optionally prepended by a '+' or '-' and optionally "
106
                . "surrounded by whitespace"
107
            );
108
        }
109
    }
110
111
    private static function castAndEnforceValidIntegerSize(string $value) : int
112
    {
113
        $phpIntMin = ~PHP_INT_MAX;
114
        $casted = (int)$value;
115
        if ($casted === PHP_INT_MAX && $value !== (string)PHP_INT_MAX) {
116
            throw new FilterException("{$value} was greater than a max int of " . PHP_INT_MAX);
117
        }
118
119
        if ($casted === $phpIntMin && $value !== (string)$phpIntMin) {
120
            throw new FilterException("{$value} was less than a min int of {$phpIntMin}");
121
        }
122
123
        return $casted;
124
    }
125
}
126