Ints   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 132
Duplicated Lines 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
eloc 43
c 2
b 1
f 0
dl 0
loc 132
rs 10
wmc 28

11 Methods

Rating   Name   Duplication   Size   Complexity  
A enforceMaximumValue() 0 4 2
A enforcePhpIntMax() 0 4 3
A enforceMinimumValue() 0 4 3
A enforcePhpIntMin() 0 4 3
A enforceStringLength() 0 4 2
A filter() 0 12 2
A valueIsNullAndValid() 0 6 4
A getValueInt() 0 12 3
A castAndEnforceValidIntegerSize() 0 9 1
A handleStringValues() 0 9 1
A checkDigits() 0 12 4
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
        self::enforceMinimumValue($minValue, $valueInt);
45
        self::enforceMaximumValue($maxValue, $valueInt);
46
47
        return $valueInt;
48
    }
49
50
    private static function valueIsNullAndValid(bool $allowNull, $value = null) : bool
51
    {
52
        if ($allowNull === false && $value === null) {
53
            throw new FilterException('Value failed filtering, $allowNull is set to false');
54
        }
55
        return $allowNull === true && $value === null;
56
    }
57
58
    private static function getValueInt($value) : int
59
    {
60
        $valueInt = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $valueInt is dead and can be removed.
Loading history...
61
        if (is_int($value)) {
62
            return $value;
63
        }
64
65
        if (is_string($value)) {
66
            return self::handleStringValues($value);
67
        }
68
69
        throw new FilterException('"' . var_export($value, true) . '" $value is not a string');
70
    }
71
72
    private static function handleStringValues(string $value) : int
73
    {
74
        $value = trim($value);
75
76
        self::enforceStringLength($value);
77
        self::checkDigits($value);
78
        $casted = self::castAndEnforceValidIntegerSize($value);
79
80
        return $casted;
81
    }
82
83
    private static function enforceStringLength(string $value)
84
    {
85
        if (strlen($value) === 0) {
86
            throw new FilterException('$value string length is zero');
87
        }
88
    }
89
90
    private static function checkDigits(string $value)
91
    {
92
        $stringToCheckDigits = $value;
93
94
        if ($value[0] === '-' || $value[0] === '+') {
95
            $stringToCheckDigits = substr($value, 1);
96
        }
97
98
        if (!ctype_digit($stringToCheckDigits)) {
99
            throw new FilterException(
100
                "{$value} does not contain all digits, optionally prepended by a '+' or '-' and optionally "
101
                . "surrounded by whitespace"
102
            );
103
        }
104
    }
105
106
    private static function castAndEnforceValidIntegerSize(string $value) : int
107
    {
108
        $phpIntMin = ~PHP_INT_MAX;
109
        $casted = (int)$value;
110
111
        self::enforcePhpIntMax($value, $casted);
112
        self::enforcePhpIntMin($value, $casted, $phpIntMin);
113
114
        return $casted;
115
    }
116
117
    private static function enforceMinimumValue(int $minValue = null, int $valueInt)
118
    {
119
        if ($minValue !== null && $valueInt < $minValue) {
120
            throw new FilterException("{$valueInt} is less than {$minValue}");
121
        }
122
    }
123
124
    private static function enforceMaximumValue(int $maxValue = null, int $valueInt)
125
    {
126
        if ($valueInt > $maxValue) {
127
            throw new FilterException("{$valueInt} is greater than {$maxValue}");
128
        }
129
    }
130
131
    private static function enforcePhpIntMax(string $value, int $casted)
132
    {
133
        if ($casted === PHP_INT_MAX && $value !== (string)PHP_INT_MAX) {
134
            throw new FilterException("{$value} was greater than a max int of " . PHP_INT_MAX);
135
        }
136
    }
137
138
    private static function enforcePhpIntMin(string $value, int $casted, int $phpIntMin)
139
    {
140
        if ($casted === $phpIntMin && $value !== (string)$phpIntMin) {
141
            throw new FilterException("{$value} was less than a min int of {$phpIntMin}");
142
        }
143
    }
144
}
145