Passed
Pull Request — master (#1)
by
unknown
02:06
created

Strings::validateStringLength()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 9
nc 2
nop 3
dl 0
loc 11
c 0
b 0
f 0
cc 3
rs 9.4285
1
<?php
2
3
namespace TraderInteractive\Filter;
4
5
use TraderInteractive\Exceptions\FilterException;
6
use TypeError;
7
8
/**
9
 * A collection of filters for strings.
10
 */
11
final class Strings
12
{
13
    /**
14
     * Filter a string.
15
     *
16
     * Verify that the passed in value  is a string.  By default, nulls are not allowed, and the length is restricted
17
     * between 1 and PHP_INT_MAX.  These parameters can be overwritten for custom behavior.
18
     *
19
     * The return value is the string, as expected by the \TraderInteractive\Filterer class.
20
     *
21
     * @param mixed $value The value to filter.
22
     * @param bool $allowNull True to allow nulls through, and false (default) if nulls should not be allowed.
23
     * @param int $minLength Minimum length to allow for $value.
24
     * @param int $maxLength Maximum length to allow for $value.
25
     * @return string|null The passed in $value.
26
     *
27
     * @throws FilterException if the value did not pass validation.
28
     * @throws \InvalidArgumentException if one of the parameters was not correctly typed.
29
     */
30
    public static function filter(
31
        $value = null,
32
        bool $allowNull = false,
33
        int $minLength = 1,
34
        int $maxLength = PHP_INT_MAX
35
    ) {
36
        self::validateMinimumLength($minLength);
37
        self::validateMaximumLength($maxLength);
38
39
        if (self::valueIsNullAndValid($allowNull, $value)) {
40
            return null;
41
        }
42
43
        $value = self::enforceValueCanBeCastAsString($value);
44
45
        self::validateStringLength($value, $minLength, $maxLength);
46
47
        return $value;
48
    }
49
50
    /**
51
     * Explodes a string into an array using the given delimiter.
52
     *
53
     * For example, given the string 'foo,bar,baz', this would return the array ['foo', 'bar', 'baz'].
54
     *
55
     * @param string $value The string to explode.
56
     * @param string $delimiter The non-empty delimiter to explode on.
57
     * @return array The exploded values.
58
     *
59
     * @throws \InvalidArgumentException if the delimiter does not pass validation.
60
     */
61
    public static function explode($value, string $delimiter = ',')
62
    {
63
        self::validateIfObjectIsAString($value);
64
65
        if (empty($delimiter)) {
66
            throw new \InvalidArgumentException(
67
                "Delimiter '" . var_export($delimiter, true) . "' is not a non-empty string"
68
            );
69
        }
70
71
        return explode($delimiter, $value);
72
    }
73
74
    private static function validateMinimumLength(int $minLength)
75
    {
76
        if ($minLength < 0) {
77
            throw new \InvalidArgumentException('$minLength was not a positive integer value');
78
        }
79
    }
80
81
    private static function validateMaximumLength(int $maxLength)
82
    {
83
        if ($maxLength < 0) {
84
            throw new \InvalidArgumentException('$maxLength was not a positive integer value');
85
        }
86
    }
87
88
    private static function validateStringLength(string $value = null, int $minLength, int $maxLength)
89
    {
90
        $valueLength = strlen($value);
91
        if ($valueLength < $minLength || $valueLength > $maxLength) {
92
            throw new FilterException(
93
                sprintf(
94
                    "Value '%s' with length '%d' is less than '%d' or greater than '%d'",
95
                    $value,
96
                    $valueLength,
97
                    $minLength,
98
                    $maxLength
99
                )
100
            );
101
        }
102
    }
103
104
    private static function valueIsNullAndValid(bool $allowNull, $value = null) : bool
105
    {
106
        if ($allowNull === false && $value === null) {
107
            throw new FilterException('Value failed filtering, $allowNull is set to false');
108
        }
109
110
        return $allowNull === true && $value === null;
111
    }
112
113
    private static function checkIfScalarAndConvert(&$value)
0 ignored issues
show
Unused Code introduced by
The method checkIfScalarAndConvert() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
114
    {
115
        if (is_scalar($value)) {
116
            $value = (string)$value;
117
        }
118
    }
119
120
    private static function checkIfObjectAndConvert(&$value)
0 ignored issues
show
Unused Code introduced by
The method checkIfObjectAndConvert() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
121
    {
122
        if (is_object($value) && method_exists($value, '__toString')) {
123
            $value = (string)$value;
124
        }
125
    }
126
127
    private static function validateIfObjectIsAString($value)
128
    {
129
        if (!is_string($value)) {
130
            throw new FilterException("Value '" . var_export($value, true) . "' is not a string");
131
        }
132
    }
133
134
    private static function enforceValueCanBeCastAsString($value)
135
    {
136
        try {
137
            $value = (
138
                function (string $str) : string {
139
                    return $str;
140
                }
141
            )($value);
142
        } catch (TypeError $te) {
143
            throw new FilterException(sprintf("Value '%s' is not a string", var_export($value, true)));
144
        }
145
146
        return $value;
147
    }
148
}
149