Passed
Push — master ( 42ae0f...32b24a )
by Marcin
08:00 queued 11s
created

Validator::assertArrayHasNoMixedKeys()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 11
c 0
b 0
f 0
nc 5
nop 1
dl 0
loc 15
ccs 4
cts 4
cp 1
crap 5
rs 9.6111
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
	public static function assertIsBool(string $var_name, $value): void
32
	{
33
		self::assertIsType($var_name, $value, [Type::BOOLEAN], Ex\NotBooleanException::class);
34
	}
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 2
	public static function assertIsInt(string $var_name, $value): void
47
	{
48 2
		self::assertIsType($var_name, $value, [Type::INTEGER], Ex\NotBooleanException::class);
49 1
	}
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 87
	public static function assertIsArray(string $var_name, $value): void
62
	{
63 87
		self::assertIsType($var_name, $value, [Type::ARRAY], Ex\NotArrayException::class);
64 87
	}
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 2
	public static function assertIsObject(string $var_name, $value): void
77
	{
78 2
		self::assertIsType($var_name, $value, [Type::OBJECT], Ex\NotObjectException::class);
79 1
	}
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 14
	public static function assertIsString(string $var_name, $value): void
92
	{
93 14
		self::assertIsType($var_name, $value, [Type::STRING], Ex\NotStringException::class);
94 13
	}
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 13
	 */
107
	public static function assertIsIntRange(string $var_name, $value, int $min, int $max): void
108 13
	{
109 10
		self::assertIsInt($var_name, $value);
110
111
		if ($min > $max) {
112
			throw new \InvalidArgumentException(
113
				\sprintf('%s: Invalid range for "%s". Ensure bound values are not swapped.', __FUNCTION__, $var_name));
114
		}
115
116
		if (($min > $value) || ($value > $max)) {
117
			throw new \OutOfBoundsException(
118
				\sprintf('Value of "%s" (%d) is out of bounds. Must be between %d-%d inclusive.', $var_name, $value, $min, $max));
119
		}
120
	}
121
122 87
	/**
123
	 * Checks if $item (of name $key) is of type that is include in $allowed_types.
124 87
	 *
125
	 * @param string $var_name      Label or name of the variable to be used in exception message (if thrown).
126 87
	 * @param mixed  $value         Variable to be asserted.
127 1
	 * @param array  $allowed_types Array of allowed types for $value, i.e. [Type::INTEGER]
128 1
	 * @param string $ex_class      Name of exception class to thrown when assertion failed.
129
	 *
130
	 * @return void
131 87
	 *
132 4
	 * @throws \InvalidArgumentException
133 4
	 */
134
	public static function assertIsType(string $var_name, $value, array $allowed_types,
135 87
	                                    string $ex_class = Ex\InvalidTypeException::class): void
136
	{
137
		$type = \gettype($value);
138
		if (!\in_array($type, $allowed_types, true)) {
139
			throw new $ex_class($var_name, $type, $allowed_types);
140
		}
141
	}
142
143
	/**
144
	 * Ensures given $http_code is valid code for error response.
145
	 *
146
	 * @param int $http_code
147
	 */
148 87
	public static function assertErrorHttpCode(int $http_code): void
149
	{
150 87
		self::assertIsInt('http_code', $http_code);
151 87
		self::assertIsIntRange('http_code', $http_code,
152 13
			RB::ERROR_HTTP_CODE_MIN, RB::ERROR_HTTP_CODE_MAX);
153 13
	}
154 13
155
	/**
156
	 * Ensures given $http_code is valid for response indicating sucessful operation.
157 87
	 *
158
	 * @param int $http_code
159
	 */
160
	public static function assertOkHttpCode(int $http_code): void
161
	{
162
		self::assertIsInt('http_code', $http_code);
163
		self::assertIsIntRange('http_code', $http_code, 200, 299);
164 10
	}
165
166 10
	/**
167 10
	 * Ensures $obj (that is value coming from variable, which name is passed in $label) is instance of $cls class.
168 10
	 *
169 10
	 * @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
	public static function assertInstanceOf(string $var_name, object $obj, string $cls): void
174
	{
175
		if (!($obj instanceof $cls)) {
176 8
			throw new \InvalidArgumentException(
177
				\sprintf('"%s" must be instance of "%s".', $var_name, $cls)
178 8
			);
179 8
		}
180 8
	}
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 4
	 * @throws Ex\ArrayWithMixedKeysException
190
	 */
191 4
	public static function assertArrayHasNoMixedKeys(array $data): void
192 1
	{
193 1
		$string_keys_cnt = 0;
194
		$int_keys_cnt = 0;
195
		foreach (\array_keys($data) as $key) {
196 3
			if (\is_int($key)) {
197
				if ($string_keys_cnt > 0) {
198
					throw new Ex\ArrayWithMixedKeysException();
199
				}
200
				$int_keys_cnt++;
201
			} else {
202
				if ($int_keys_cnt > 0) {
203
					throw new Ex\ArrayWithMixedKeysException();
204
				}
205
				$string_keys_cnt++;
206
			}
207
		}
208
	}
209
}
210