Completed
Push — master ( 277a70...42ae0f )
by Marcin
24s queued 11s
created

Validator   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 187
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 10
Bugs 0 Features 0
Metric Value
eloc 35
c 10
b 0
f 0
dl 0
loc 187
ccs 54
cts 54
cp 1
rs 10
wmc 20

11 Methods

Rating   Name   Duplication   Size   Complexity  
A assertOkHttpCode() 0 4 1
A assertErrorHttpCode() 0 5 1
A assertInstanceOf() 0 5 2
A assertIsType() 0 6 2
A assertIsArray() 0 3 1
A assertIsString() 0 3 1
A assertIsObject() 0 3 1
A assertIsInt() 0 3 1
A assertArrayHasNoMixedKeys() 0 15 5
A assertIsIntRange() 0 12 4
A assertIsBool() 0 3 1
1
<?php
2
declare(strict_types=1);
3
4
namespace MarcinOrlowski\ResponseBuilder;
5
6
use MarcinOrlowski\ResponseBuilder\Exceptions as Ex;
7
use MarcinOrlowski\ResponseBuilder\ResponseBuilder as RB;
8
9
/**
10
 * Laravel API Response Builder
11
 *
12
 * @package   MarcinOrlowski\ResponseBuilder
13
 *
14
 * @author    Marcin Orlowski <mail (#) marcinOrlowski (.) com>
15
 * @copyright 2016-2020 Marcin Orlowski
16
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
17
 * @link      https://github.com/MarcinOrlowski/laravel-api-response-builder
18
 */
19
class Validator
20
{
21
	/**
22
	 * Checks if given $val is of type boolean
23
	 *
24
	 * @param string $var_name Name of the key to be used if exception is thrown.
25
	 * @param mixed  $value    Variable to be asserted.
26
	 *
27
	 * @return void
28
	 *
29
	 * @throws \InvalidArgumentException
30
	 */
31 2
	public static function assertIsBool(string $var_name, $value): void
32
	{
33 2
		self::assertIsType($var_name, $value, [Type::BOOLEAN], Ex\NotBooleanException::class);
34 1
	}
35
36
	/**
37
	 * Checks if given $val is of type integer
38
	 *
39
	 * @param string $var_name Name of the key to be used if exception is thrown.
40
	 * @param mixed  $value    Variable to be asserted.
41
	 *
42
	 * @return void
43
	 *
44
	 * @throws \InvalidArgumentException
45
	 */
46 101
	public static function assertIsInt(string $var_name, $value): void
47
	{
48 101
		self::assertIsType($var_name, $value, [Type::INTEGER], Ex\NotBooleanException::class);
49 101
	}
50
51
	/**
52
	 * Checks if given $val is of type array
53
	 *
54
	 * @param string $var_name Name of the key to be used if exception is thrown.
55
	 * @param mixed  $value    Variable to be asserted.
56
	 *
57
	 * @return void
58
	 *
59
	 * @throws \InvalidArgumentException
60
	 */
61 24
	public static function assertIsArray(string $var_name, $value): void
62
	{
63 24
		self::assertIsType($var_name, $value, [Type::ARRAY], Ex\NotArrayException::class);
64 22
	}
65
66
	/**
67
	 * Checks if given $val is an object
68
	 *
69
	 * @param string $var_name Name of the key to be used if exception is thrown.
70
	 * @param mixed  $value    Variable to be asserted.
71
	 *
72
	 * @return void
73
	 *
74
	 * @throws \InvalidArgumentException
75
	 */
76 14
	public static function assertIsObject(string $var_name, $value): void
77
	{
78 14
		self::assertIsType($var_name, $value, [Type::OBJECT], Ex\NotObjectException::class);
79 13
	}
80
81
	/**
82
	 * Checks if given $val is of type string
83
	 *
84
	 * @param string $var_name Label or name of the variable to be used in exception message (if thrown).
85
	 * @param mixed  $value    Variable to be asserted.
86
	 *
87
	 * @return void
88
	 *
89
	 * @throws \InvalidArgumentException
90
	 */
91 13
	public static function assertIsString(string $var_name, $value): void
92
	{
93 13
		self::assertIsType($var_name, $value, [Type::STRING], Ex\NotStringException::class);
94 10
	}
95
96
	/**
97
	 * @param string $var_name Label or name of the variable to be used in exception message (if thrown).
98
	 * @param mixed  $value    Variable to be asserted.
99
	 * @param int    $min      Min allowed value (inclusive)
100
	 * @param int    $max      Max allowed value (inclusive)
101
	 *
102
	 * @return void
103
	 *
104
	 * @throws \InvalidArgumentException
105
	 * @throws \RuntimeException
106
	 */
107 101
	public static function assertIsIntRange(string $var_name, $value, int $min, int $max): void
108
	{
109 101
		self::assertIsInt($var_name, $value);
110
111 101
		if ($min > $max) {
112 1
			throw new \InvalidArgumentException(
113 1
				\sprintf('%s: Invalid range for "%s". Ensure bound values are not swapped.', __FUNCTION__, $var_name));
114
		}
115
116 101
		if (($min > $value) || ($value > $max)) {
117 5
			throw new \OutOfBoundsException(
118 5
				\sprintf('Value of "%s" (%d) is out of bounds. Must be between %d-%d inclusive.', $var_name, $value, $min, $max));
119
		}
120 101
	}
121
122
	/**
123
	 * Checks if $item (of name $key) is of type that is include in $allowed_types.
124
	 *
125
	 * @param string $var_name      Label or name of the variable to be used in exception message (if thrown).
126
	 * @param mixed  $value         Variable to be asserted.
127
	 * @param array  $allowed_types Array of allowed types for $value, i.e. [Type::INTEGER]
128
	 * @param string $ex_class      Name of exception class to thrown when assertion failed.
129
	 *
130
	 * @return void
131
	 *
132
	 * @throws \InvalidArgumentException
133
	 */
134 101
	public static function assertIsType(string $var_name, $value, array $allowed_types,
135
	                                    string $ex_class = Ex\InvalidTypeException::class): void
136
	{
137 101
		$type = \gettype($value);
138 101
		if (!\in_array($type, $allowed_types, true)) {
139 11
			throw new $ex_class($var_name, $type, $allowed_types);
140
		}
141 101
	}
142
143
	/**
144
	 * Ensures given $http_code is valid code for error response.
145
	 *
146
	 * @param int $http_code
147
	 */
148 10
	public static function assertErrorHttpCode(int $http_code): void
149
	{
150 10
		self::assertIsInt('http_code', $http_code);
151 10
		self::assertIsIntRange('http_code', $http_code,
152 10
			RB::ERROR_HTTP_CODE_MIN, RB::ERROR_HTTP_CODE_MAX);
153 10
	}
154
155
	/**
156
	 * Ensures given $http_code is valid for response indicating sucessful operation.
157
	 *
158
	 * @param int $http_code
159
	 */
160 13
	public static function assertOkHttpCode(int $http_code): void
161
	{
162 13
		self::assertIsInt('http_code', $http_code);
163 13
		self::assertIsIntRange('http_code', $http_code, 200, 299);
164 13
	}
165
166
	/**
167
	 * Ensures $obj (that is value coming from variable, which name is passed in $label) is instance of $cls class.
168
	 *
169
	 * @param string $var_name Name of variable that the $obj value is coming from. Used for exception message.
170
	 * @param object $obj      Object to check instance of
171
	 * @param string $cls      Target class we want to check $obj agains.
172
	 */
173 4
	public static function assertInstanceOf(string $var_name, object $obj, string $cls): void
174
	{
175 4
		if (!($obj instanceof $cls)) {
176 1
			throw new \InvalidArgumentException(
177 1
				\sprintf('"%s" must be instance of "%s".', $var_name, $cls)
178
			);
179
		}
180 3
	}
181
182
	/**
183
	 * Ensure that we either have array with user provided keys i.e. ['foo'=>'bar'], which will then
184
	 * be turned into JSON object or array without user specified keys (['bar']) which we would return as JSON
185
	 * array. But you can't mix these two as the final JSON would not produce predictable results.
186
	 *
187
	 * @param array $data
188
	 *
189
	 * @throws Ex\ArrayWithMixedKeysException
190
	 */
191 11
	public static function assertArrayHasNoMixedKeys(array $data): void
192
	{
193 11
		$string_keys_cnt = 0;
194 11
		$int_keys_cnt = 0;
195 11
		foreach (\array_keys($data) as $key) {
196 11
			if (\is_int($key)) {
197 7
				if ($string_keys_cnt > 0) {
198 1
					throw new Ex\ArrayWithMixedKeysException();
199
				}
200 6
				$int_keys_cnt++;
201
			} else {
202 7
				if ($int_keys_cnt > 0) {
203 1
					throw new Ex\ArrayWithMixedKeysException();
204
				}
205 6
				$string_keys_cnt++;
206
			}
207
		}
208 9
	}
209
}
210