Failed Conditions
Pull Request — master (#164)
by Ruud
02:28
created

Assert   F

Complexity

Total Complexity 298

Size/Duplication

Total Lines 1738
Duplicated Lines 18.76 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 96.45%

Importance

Changes 0
Metric Value
wmc 298
lcom 1
cbo 0
dl 326
loc 1738
ccs 624
cts 647
cp 0.9645
rs 0.8
c 0
b 0
f 0

92 Methods

Rating   Name   Duplication   Size   Complexity  
A writable() 0 9 3
A propertyNotExists() 9 9 3
A minCount() 10 10 3
A startsWithLetter() 0 20 4
A endsWith() 10 10 3
A regex() 0 9 3
A notRegex() 0 11 3
A stringNotEmpty() 0 5 1
A integer() 0 9 3
A integerish() 0 9 4
A float() 0 9 3
A numeric() 0 9 3
A natural() 0 9 4
A boolean() 0 9 3
A scalar() 0 9 3
A object() 0 9 3
A resource() 0 17 6
A isCallable() 0 9 3
A isArray() 0 9 3
A isTraversable() 0 17 4
A string() 0 9 3
A isArrayAccessible() 9 9 4
A isCountable() 0 14 6
A isIterable() 9 9 4
A isInstanceOf() 0 10 3
A notInstanceOf() 0 10 3
A isInstanceOfAny() 0 14 4
A isEmpty() 0 9 3
A notEmpty() 0 9 3
A null() 0 9 3
A notNull() 0 8 3
A true() 0 9 3
A false() 0 9 3
A notFalse() 0 8 3
A ip() 9 9 3
A ipv4() 9 9 3
A ipv6() 9 9 3
A email() 9 9 3
A uniqueValues() 0 15 4
A eq() 0 10 3
A notEq() 0 9 3
A same() 0 10 3
A notSame() 0 9 3
A greaterThan() 0 10 3
A greaterThanEq() 0 10 3
A lessThan() 0 10 3
A lessThanEq() 0 10 3
A range() 11 11 4
A oneOf() 0 10 3
A contains() 10 10 3
A notContains() 10 10 3
A notWhitespaceOnly() 0 9 3
A startsWith() 10 10 3
A unicodeLetters() 11 11 3
A alpha() 16 16 3
A digits() 14 14 3
A alnum() 14 14 3
A lower() 14 14 3
A upper() 14 14 3
A length() 0 10 3
A minLength() 0 10 3
A maxLength() 0 10 3
A lengthBetween() 13 13 4
A fileExists() 11 11 3
A file() 11 11 3
A directory() 11 11 3
A readable() 0 9 3
A classExists() 0 9 3
A subclassOf() 0 10 3
A interfaceExists() 0 9 3
A implementsInterface() 10 10 3
A propertyExists() 9 9 3
A methodExists() 9 9 3
A methodNotExists() 9 9 3
A keyExists() 9 9 4
A keyNotExists() 9 9 4
A validArrayKey() 0 9 4
A count() 0 8 2
A maxCount() 10 10 3
A countBetween() 0 13 4
A isList() 8 8 4
A isNonEmptyList() 0 5 1
A isMap() 0 11 4
A isNonEmptyMap() 0 5 1
A uuid() 0 17 4
B throws() 0 26 6
A __callStatic() 0 28 5
B valueToString() 0 36 9
A typeToString() 0 4 2
A strlen() 0 12 3
A reportInvalidArgument() 0 4 1
A __construct() 0 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Assert often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Assert, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * This file is part of the webmozart/assert package.
5
 *
6
 * (c) Bernhard Schussek <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Webmozart\Assert;
13
14
use ArrayAccess;
15
use BadMethodCallException;
16
use Closure;
17
use Countable;
18
use Exception;
19
use InvalidArgumentException;
20
use ResourceBundle;
21
use SimpleXMLElement;
22
use Throwable;
23
use Traversable;
24
25
/**
26
 * Efficient assertions to validate the input/output of your methods.
27
 *
28
 * @method static void nullOrString($value, $message = '')
29
 * @method static void nullOrStringNotEmpty($value, $message = '')
30
 * @method static void nullOrInteger($value, $message = '')
31
 * @method static void nullOrIntegerish($value, $message = '')
32
 * @method static void nullOrFloat($value, $message = '')
33
 * @method static void nullOrNumeric($value, $message = '')
34
 * @method static void nullOrNatural($value, $message = '')
35
 * @method static void nullOrBoolean($value, $message = '')
36
 * @method static void nullOrScalar($value, $message = '')
37
 * @method static void nullOrObject($value, $message = '')
38
 * @method static void nullOrResource($value, $type = null, $message = '')
39
 * @method static void nullOrIsCallable($value, $message = '')
40
 * @method static void nullOrIsArray($value, $message = '')
41
 * @method static void nullOrIsTraversable($value, $message = '')
42
 * @method static void nullOrIsArrayAccessible($value, $message = '')
43
 * @method static void nullOrIsCountable($value, $message = '')
44
 * @method static void nullOrIsIterable($value, $message = '')
45
 * @method static void nullOrIsInstanceOf($value, $class, $message = '')
46
 * @method static void nullOrNotInstanceOf($value, $class, $message = '')
47
 * @method static void nullOrIsInstanceOfAny($value, $classes, $message = '')
48
 * @method static void nullOrIsEmpty($value, $message = '')
49
 * @method static void nullOrNotEmpty($value, $message = '')
50
 * @method static void nullOrTrue($value, $message = '')
51
 * @method static void nullOrFalse($value, $message = '')
52
 * @method static void nullOrNotFalse($value, $message = '')
53
 * @method static void nullOrIp($value, $message = '')
54
 * @method static void nullOrIpv4($value, $message = '')
55
 * @method static void nullOrIpv6($value, $message = '')
56
 * @method static void nullOrEmail($value, $message = '')
57
 * @method static void nullOrUniqueValues($values, $message = '')
58
 * @method static void nullOrEq($value, $expect, $message = '')
59
 * @method static void nullOrNotEq($value, $expect, $message = '')
60
 * @method static void nullOrSame($value, $expect, $message = '')
61
 * @method static void nullOrNotSame($value, $expect, $message = '')
62
 * @method static void nullOrGreaterThan($value, $limit, $message = '')
63
 * @method static void nullOrGreaterThanEq($value, $limit, $message = '')
64
 * @method static void nullOrLessThan($value, $limit, $message = '')
65
 * @method static void nullOrLessThanEq($value, $limit, $message = '')
66
 * @method static void nullOrRange($value, $min, $max, $message = '')
67
 * @method static void nullOrOneOf($value, $values, $message = '')
68
 * @method static void nullOrContains($value, $subString, $message = '')
69
 * @method static void nullOrNotContains($value, $subString, $message = '')
70
 * @method static void nullOrNotWhitespaceOnly($value, $message = '')
71
 * @method static void nullOrStartsWith($value, $prefix, $message = '')
72
 * @method static void nullOrStartsWithLetter($value, $message = '')
73
 * @method static void nullOrEndsWith($value, $suffix, $message = '')
74
 * @method static void nullOrRegex($value, $pattern, $message = '')
75
 * @method static void nullOrNotRegex($value, $pattern, $message = '')
76
 * @method static void nullOrUnicodeLetters($value, $message = '')
77
 * @method static void nullOrAlpha($value, $message = '')
78
 * @method static void nullOrDigits($value, $message = '')
79
 * @method static void nullOrAlnum($value, $message = '')
80
 * @method static void nullOrLower($value, $message = '')
81
 * @method static void nullOrUpper($value, $message = '')
82
 * @method static void nullOrLength($value, $length, $message = '')
83
 * @method static void nullOrMinLength($value, $min, $message = '')
84
 * @method static void nullOrMaxLength($value, $max, $message = '')
85
 * @method static void nullOrLengthBetween($value, $min, $max, $message = '')
86
 * @method static void nullOrFileExists($value, $message = '')
87
 * @method static void nullOrFile($value, $message = '')
88
 * @method static void nullOrDirectory($value, $message = '')
89
 * @method static void nullOrReadable($value, $message = '')
90
 * @method static void nullOrWritable($value, $message = '')
91
 * @method static void nullOrClassExists($value, $message = '')
92
 * @method static void nullOrSubclassOf($value, $class, $message = '')
93
 * @method static void nullOrInterfaceExists($value, $message = '')
94
 * @method static void nullOrImplementsInterface($value, $interface, $message = '')
95
 * @method static void nullOrPropertyExists($value, $property, $message = '')
96
 * @method static void nullOrPropertyNotExists($value, $property, $message = '')
97
 * @method static void nullOrMethodExists($value, $method, $message = '')
98
 * @method static void nullOrMethodNotExists($value, $method, $message = '')
99
 * @method static void nullOrKeyExists($value, $key, $message = '')
100
 * @method static void nullOrKeyNotExists($value, $key, $message = '')
101
 * @method static void nullOrValidArrayKey($value, $message = '')
102
 * @method static void nullOrCount($value, $key, $message = '')
103
 * @method static void nullOrMinCount($value, $min, $message = '')
104
 * @method static void nullOrMaxCount($value, $max, $message = '')
105
 * @method static void nullOrIsList($value, $message = '')
106
 * @method static void nullOrIsNonEmptyList($value, $message = '')
107
 * @method static void nullOrIsMap($value, $message = '')
108
 * @method static void nullOrIsNonEmptyMap($value, $message = '')
109
 * @method static void nullOrCountBetween($value, $min, $max, $message = '')
110
 * @method static void nullOrUuid($values, $message = '')
111
 * @method static void nullOrThrows($expression, $class = 'Exception', $message = '')
112
 * @method static void allString($values, $message = '')
113
 * @method static void allStringNotEmpty($values, $message = '')
114
 * @method static void allInteger($values, $message = '')
115
 * @method static void allIntegerish($values, $message = '')
116
 * @method static void allFloat($values, $message = '')
117
 * @method static void allNumeric($values, $message = '')
118
 * @method static void allNatural($values, $message = '')
119
 * @method static void allBoolean($values, $message = '')
120
 * @method static void allScalar($values, $message = '')
121
 * @method static void allObject($values, $message = '')
122
 * @method static void allResource($values, $type = null, $message = '')
123
 * @method static void allIsCallable($values, $message = '')
124
 * @method static void allIsArray($values, $message = '')
125
 * @method static void allIsTraversable($values, $message = '')
126
 * @method static void allIsArrayAccessible($values, $message = '')
127
 * @method static void allIsCountable($values, $message = '')
128
 * @method static void allIsIterable($values, $message = '')
129
 * @method static void allIsInstanceOf($values, $class, $message = '')
130
 * @method static void allNotInstanceOf($values, $class, $message = '')
131
 * @method static void allIsInstanceOfAny($values, $classes, $message = '')
132
 * @method static void allNull($values, $message = '')
133
 * @method static void allNotNull($values, $message = '')
134
 * @method static void allIsEmpty($values, $message = '')
135
 * @method static void allNotEmpty($values, $message = '')
136
 * @method static void allTrue($values, $message = '')
137
 * @method static void allFalse($values, $message = '')
138
 * @method static void allNotFalse($values, $message = '')
139
 * @method static void allIp($values, $message = '')
140
 * @method static void allIpv4($values, $message = '')
141
 * @method static void allIpv6($values, $message = '')
142
 * @method static void allEmail($values, $message = '')
143
 * @method static void allUniqueValues($values, $message = '')
144
 * @method static void allEq($values, $expect, $message = '')
145
 * @method static void allNotEq($values, $expect, $message = '')
146
 * @method static void allSame($values, $expect, $message = '')
147
 * @method static void allNotSame($values, $expect, $message = '')
148
 * @method static void allGreaterThan($values, $limit, $message = '')
149
 * @method static void allGreaterThanEq($values, $limit, $message = '')
150
 * @method static void allLessThan($values, $limit, $message = '')
151
 * @method static void allLessThanEq($values, $limit, $message = '')
152
 * @method static void allRange($values, $min, $max, $message = '')
153
 * @method static void allOneOf($values, $values, $message = '')
154
 * @method static void allContains($values, $subString, $message = '')
155
 * @method static void allNotContains($values, $subString, $message = '')
156
 * @method static void allNotWhitespaceOnly($values, $message = '')
157
 * @method static void allStartsWith($values, $prefix, $message = '')
158
 * @method static void allStartsWithLetter($values, $message = '')
159
 * @method static void allEndsWith($values, $suffix, $message = '')
160
 * @method static void allRegex($values, $pattern, $message = '')
161
 * @method static void allNotRegex($values, $pattern, $message = '')
162
 * @method static void allUnicodeLetters($values, $message = '')
163
 * @method static void allAlpha($values, $message = '')
164
 * @method static void allDigits($values, $message = '')
165
 * @method static void allAlnum($values, $message = '')
166
 * @method static void allLower($values, $message = '')
167
 * @method static void allUpper($values, $message = '')
168
 * @method static void allLength($values, $length, $message = '')
169
 * @method static void allMinLength($values, $min, $message = '')
170
 * @method static void allMaxLength($values, $max, $message = '')
171
 * @method static void allLengthBetween($values, $min, $max, $message = '')
172
 * @method static void allFileExists($values, $message = '')
173
 * @method static void allFile($values, $message = '')
174
 * @method static void allDirectory($values, $message = '')
175
 * @method static void allReadable($values, $message = '')
176
 * @method static void allWritable($values, $message = '')
177
 * @method static void allClassExists($values, $message = '')
178
 * @method static void allSubclassOf($values, $class, $message = '')
179
 * @method static void allInterfaceExists($values, $message = '')
180
 * @method static void allImplementsInterface($values, $interface, $message = '')
181
 * @method static void allPropertyExists($values, $property, $message = '')
182
 * @method static void allPropertyNotExists($values, $property, $message = '')
183
 * @method static void allMethodExists($values, $method, $message = '')
184
 * @method static void allMethodNotExists($values, $method, $message = '')
185
 * @method static void allKeyExists($values, $key, $message = '')
186
 * @method static void allKeyNotExists($values, $key, $message = '')
187
 * @method static void allValidArrayKey($values, $message = '')
188
 * @method static void allCount($values, $key, $message = '')
189
 * @method static void allMinCount($values, $min, $message = '')
190
 * @method static void allMaxCount($values, $max, $message = '')
191
 * @method static void allCountBetween($values, $min, $max, $message = '')
192
 * @method static void allIsList($values, $message = '')
193
 * @method static void allIsNonEmptyList($values, $message = '')
194
 * @method static void allIsMap($values, $message = '')
195
 * @method static void allIsNonEmptyMap($values, $message = '')
196
 * @method static void allUuid($values, $message = '')
197
 * @method static void allThrows($expressions, $class = 'Exception', $message = '')
198
 *
199
 * @since  1.0
200
 *
201
 * @author Bernhard Schussek <[email protected]>
202
 */
203
class Assert
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
204
{
205
    /**
206
     * @psalm-assert string $value
207
     *
208
     * @param mixed  $value
209
     * @param string $message
210
     *
211
     * @throws InvalidArgumentException
212
     */
213 177
    public static function string($value, $message = '')
214
    {
215 177
        if (!\is_string($value)) {
216 33
            static::reportInvalidArgument(\sprintf(
217 33
                $message ?: 'Expected a string. Got: %s',
218 33
                static::typeToString($value)
219
            ));
220
        }
221 144
    }
222
223
    /**
224
     * @param mixed  $value
225
     * @param string $message
226
     *
227
     * @throws InvalidArgumentException
228
     */
229 16
    public static function stringNotEmpty($value, $message = '')
230
    {
231 16
        static::string($value, $message);
232 12
        static::notEq($value, '', $message);
233 8
    }
234
235
    /**
236
     * @psalm-assert int $value
237
     *
238
     * @param mixed  $value
239
     * @param string $message
240
     *
241
     * @throws InvalidArgumentException
242
     */
243 17
    public static function integer($value, $message = '')
244
    {
245 17
        if (!\is_int($value)) {
246 13
            static::reportInvalidArgument(\sprintf(
247 13
                $message ?: 'Expected an integer. Got: %s',
248 13
                static::typeToString($value)
249
            ));
250
        }
251 4
    }
252
253
    /**
254
     * @psalm-assert numeric $value
255
     *
256
     * @param mixed  $value
257
     * @param string $message
258
     *
259
     * @throws InvalidArgumentException
260
     */
261 16
    public static function integerish($value, $message = '')
262
    {
263 16
        if (!\is_numeric($value) || $value != (int) $value) {
264 4
            static::reportInvalidArgument(\sprintf(
265 4
                $message ?: 'Expected an integerish value. Got: %s',
266 4
                static::typeToString($value)
267
            ));
268
        }
269 12
    }
270
271
    /**
272
     * @psalm-assert float $value
273
     *
274
     * @param mixed  $value
275
     * @param string $message
276
     *
277
     * @throws InvalidArgumentException
278
     */
279 16
    public static function float($value, $message = '')
280
    {
281 16
        if (!\is_float($value)) {
282 8
            static::reportInvalidArgument(\sprintf(
283 8
                $message ?: 'Expected a float. Got: %s',
284 8
                static::typeToString($value)
285
            ));
286
        }
287 8
    }
288
289
    /**
290
     * @psalm-assert numeric $value
291
     *
292
     * @param mixed  $value
293
     * @param string $message
294
     *
295
     * @throws InvalidArgumentException
296
     */
297 20
    public static function numeric($value, $message = '')
298
    {
299 20
        if (!\is_numeric($value)) {
300 4
            static::reportInvalidArgument(\sprintf(
301 4
                $message ?: 'Expected a numeric. Got: %s',
302 4
                static::typeToString($value)
303
            ));
304
        }
305 16
    }
306
307
    /**
308
     * @psalm-assert int $value
309
     *
310
     * @param mixed  $value
311
     * @param string $message
312
     *
313
     * @throws InvalidArgumentException
314
     */
315 24
    public static function natural($value, $message = '')
316
    {
317 24
        if (!\is_int($value) || $value < 0) {
318 16
            static::reportInvalidArgument(\sprintf(
319 16
                $message ?: 'Expected a non-negative integer. Got %s',
320 16
                static::valueToString($value)
321
            ));
322
        }
323 8
    }
324
325
    /**
326
     * @psalm-assert bool $value
327
     *
328
     * @param mixed  $value
329
     * @param string $message
330
     *
331
     * @throws InvalidArgumentException
332
     */
333 16
    public static function boolean($value, $message = '')
334
    {
335 16
        if (!\is_bool($value)) {
336 8
            static::reportInvalidArgument(\sprintf(
337 8
                $message ?: 'Expected a boolean. Got: %s',
338 8
                static::typeToString($value)
339
            ));
340
        }
341 8
    }
342
343
    /**
344
     * @psalm-assert scalar $value
345
     *
346
     * @param mixed  $value
347
     * @param string $message
348
     *
349
     * @throws InvalidArgumentException
350
     */
351 23
    public static function scalar($value, $message = '')
352
    {
353 23
        if (!\is_scalar($value)) {
354 11
            static::reportInvalidArgument(\sprintf(
355 11
                $message ?: 'Expected a scalar. Got: %s',
356 11
                static::typeToString($value)
357
            ));
358
        }
359 12
    }
360
361
    /**
362
     * @psalm-assert object $value
363
     *
364
     * @param mixed  $value
365
     * @param string $message
366
     *
367
     * @throws InvalidArgumentException
368
     */
369 23
    public static function object($value, $message = '')
370
    {
371 23
        if (!\is_object($value)) {
372 15
            static::reportInvalidArgument(\sprintf(
373 15
                $message ?: 'Expected an object. Got: %s',
374 15
                static::typeToString($value)
375
            ));
376
        }
377 8
    }
378
379
    /**
380
     * @psalm-assert resource $value
381
     *
382
     * @param mixed       $value
383
     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
384
     * @param string      $message
385
     *
386
     * @throws InvalidArgumentException
387
     */
388 16
    public static function resource($value, $type = null, $message = '')
389
    {
390 16
        if (!\is_resource($value)) {
391 4
            static::reportInvalidArgument(\sprintf(
392 4
                $message ?: 'Expected a resource. Got: %s',
393 4
                static::typeToString($value)
394
            ));
395
        }
396
397 12
        if ($type && $type !== \get_resource_type($value)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $type of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
398 4
            static::reportInvalidArgument(\sprintf(
399 4
                $message ?: 'Expected a resource of type %2$s. Got: %s',
400 4
                static::typeToString($value),
401 4
                $type
402
            ));
403
        }
404 8
    }
405
406
    /**
407
     * @psalm-assert callable $value
408
     *
409
     * @param mixed  $value
410
     * @param string $message
411
     *
412
     * @throws InvalidArgumentException
413
     */
414 20
    public static function isCallable($value, $message = '')
415
    {
416 20
        if (!\is_callable($value)) {
417 8
            static::reportInvalidArgument(\sprintf(
418 8
                $message ?: 'Expected a callable. Got: %s',
419 8
                static::typeToString($value)
420
            ));
421
        }
422 12
    }
423
424
    /**
425
     * @psalm-assert array $value
426
     *
427
     * @param mixed  $value
428
     * @param string $message
429
     *
430
     * @throws InvalidArgumentException
431
     */
432 20
    public static function isArray($value, $message = '')
433
    {
434 20
        if (!\is_array($value)) {
435 12
            static::reportInvalidArgument(\sprintf(
436 12
                $message ?: 'Expected an array. Got: %s',
437 12
                static::typeToString($value)
438
            ));
439
        }
440 8
    }
441
442
    /**
443
     * @psalm-assert iterable $value
444
     *
445
     * @deprecated use "isIterable" or "isInstanceOf" instead
446
     *
447
     * @param mixed  $value
448
     * @param string $message
449
     *
450
     * @throws InvalidArgumentException
451
     */
452 20
    public static function isTraversable($value, $message = '')
453
    {
454 20
        @\trigger_error(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
455 20
            \sprintf(
456 20
                'The "%s" assertion is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "isIterable" or "isInstanceOf" instead.',
457 20
                __METHOD__
458
            ),
459 20
            \E_USER_DEPRECATED
460
        );
461
462 20
        if (!\is_array($value) && !($value instanceof Traversable)) {
463 8
            static::reportInvalidArgument(\sprintf(
464 8
                $message ?: 'Expected a traversable. Got: %s',
465 8
                static::typeToString($value)
466
            ));
467
        }
468 12
    }
469
470
    /**
471
     * @param mixed  $value
472
     * @param string $message
473
     *
474
     * @throws InvalidArgumentException
475
     */
476 20 View Code Duplication
    public static function isArrayAccessible($value, $message = '')
477
    {
478 20
        if (!\is_array($value) && !($value instanceof ArrayAccess)) {
479 8
            static::reportInvalidArgument(\sprintf(
480 8
                $message ?: 'Expected an array accessible. Got: %s',
481 8
                static::typeToString($value)
482
            ));
483
        }
484 12
    }
485
486
    /**
487
     * @psalm-assert countable $value
488
     *
489
     * @param mixed  $value
490
     * @param string $message
491
     *
492
     * @throws InvalidArgumentException
493
     */
494 28
    public static function isCountable($value, $message = '')
495
    {
496
        if (
497 28
            !\is_array($value)
498 28
            && !($value instanceof Countable)
499 28
            && !($value instanceof ResourceBundle)
0 ignored issues
show
Bug introduced by
The class ResourceBundle does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
500 28
            && !($value instanceof SimpleXMLElement)
501
        ) {
502 12
            static::reportInvalidArgument(\sprintf(
503 12
                $message ?: 'Expected a countable. Got: %s',
504 12
                static::typeToString($value)
505
            ));
506
        }
507 16
    }
508
509
    /**
510
     * @psalm-assert iterable $value
511
     *
512
     * @param mixed  $value
513
     * @param string $message
514
     *
515
     * @throws InvalidArgumentException
516
     */
517 950 View Code Duplication
    public static function isIterable($value, $message = '')
518
    {
519 950
        if (!\is_array($value) && !($value instanceof Traversable)) {
520 8
            static::reportInvalidArgument(\sprintf(
521 8
                $message ?: 'Expected an iterable. Got: %s',
522 8
                static::typeToString($value)
523
            ));
524
        }
525 946
    }
526
527
    /**
528
     * @psalm-template ExpectedType of object
529
     * @psalm-param class-string<ExpectedType> $class
530
     * @psalm-assert ExpectedType $value
531
     *
532
     * @param mixed         $value
533
     * @param string|object $class
534
     * @param string        $message
535
     *
536
     * @throws InvalidArgumentException
537
     */
538 19
    public static function isInstanceOf($value, $class, $message = '')
539
    {
540 19
        if (!($value instanceof $class)) {
541 15
            static::reportInvalidArgument(\sprintf(
542 15
                $message ?: 'Expected an instance of %2$s. Got: %s',
543 15
                static::typeToString($value),
544 15
                $class
545
            ));
546
        }
547 4
    }
548
549
    /**
550
     * @psalm-template ExpectedType of object
551
     * @psalm-param class-string<ExpectedType> $class
552
     * @psalm-assert !ExpectedType $value
553
     *
554
     * @param mixed         $value
555
     * @param string|object $class
556
     * @param string        $message
557
     *
558
     * @throws InvalidArgumentException
559
     */
560 16
    public static function notInstanceOf($value, $class, $message = '')
561
    {
562 16
        if ($value instanceof $class) {
563 4
            static::reportInvalidArgument(\sprintf(
564 4
                $message ?: 'Expected an instance other than %2$s. Got: %s',
565 4
                static::typeToString($value),
566 4
                $class
567
            ));
568
        }
569 12
    }
570
571
    /**
572
     * @param mixed                $value
573
     * @param array<object|string> $classes
574
     * @param string               $message
575
     *
576
     * @throws InvalidArgumentException
577
     */
578 20
    public static function isInstanceOfAny($value, array $classes, $message = '')
579
    {
580 20
        foreach ($classes as $class) {
581 20
            if ($value instanceof $class) {
582 8
                return;
583
            }
584
        }
585
586 12
        static::reportInvalidArgument(\sprintf(
587 12
            $message ?: 'Expected an instance of any of %2$s. Got: %s',
588 12
            static::typeToString($value),
589 12
            \implode(', ', \array_map(array('static', 'valueToString'), $classes))
590
        ));
591
    }
592
593
    /**
594
     * @psalm-assert empty $value
595
     *
596
     * @param mixed  $value
597
     * @param string $message
598
     *
599
     * @throws InvalidArgumentException
600
     */
601 23
    public static function isEmpty($value, $message = '')
602
    {
603 23
        if (!empty($value)) {
604 8
            static::reportInvalidArgument(\sprintf(
605 8
                $message ?: 'Expected an empty value. Got: %s',
606 8
                static::valueToString($value)
607
            ));
608
        }
609 15
    }
610
611
    /**
612
     * @psalm-assert !empty $value
613
     *
614
     * @param mixed  $value
615
     * @param string $message
616
     *
617
     * @throws InvalidArgumentException
618
     */
619 55
    public static function notEmpty($value, $message = '')
620
    {
621 55
        if (empty($value)) {
622 23
            static::reportInvalidArgument(\sprintf(
623 23
                $message ?: 'Expected a non-empty value. Got: %s',
624 23
                static::valueToString($value)
625
            ));
626
        }
627 32
    }
628
629
    /**
630
     * @psalm-assert null $value
631
     *
632
     * @param mixed  $value
633
     * @param string $message
634
     *
635
     * @throws InvalidArgumentException
636
     */
637 11
    public static function null($value, $message = '')
638
    {
639 11
        if (null !== $value) {
640 8
            static::reportInvalidArgument(\sprintf(
641 8
                $message ?: 'Expected null. Got: %s',
642 8
                static::valueToString($value)
643
            ));
644
        }
645 3
    }
646
647
    /**
648
     * @psalm-assert !null $value
649
     *
650
     * @param mixed  $value
651
     * @param string $message
652
     *
653
     * @throws InvalidArgumentException
654
     */
655 11
    public static function notNull($value, $message = '')
656
    {
657 11
        if (null === $value) {
658 3
            static::reportInvalidArgument(
659 3
                $message ?: 'Expected a value other than null.'
660
            );
661
        }
662 8
    }
663
664
    /**
665
     * @psalm-assert true $value
666
     *
667
     * @param mixed  $value
668
     * @param string $message
669
     *
670
     * @throws InvalidArgumentException
671
     */
672 15
    public static function true($value, $message = '')
673
    {
674 15
        if (true !== $value) {
675 11
            static::reportInvalidArgument(\sprintf(
676 11
                $message ?: 'Expected a value to be true. Got: %s',
677 11
                static::valueToString($value)
678
            ));
679
        }
680 4
    }
681
682
    /**
683
     * @psalm-assert false $value
684
     *
685
     * @param mixed  $value
686
     * @param string $message
687
     *
688
     * @throws InvalidArgumentException
689
     */
690 19
    public static function false($value, $message = '')
691
    {
692 19
        if (false !== $value) {
693 15
            static::reportInvalidArgument(\sprintf(
694 15
                $message ?: 'Expected a value to be false. Got: %s',
695 15
                static::valueToString($value)
696
            ));
697
        }
698 4
    }
699
700
    /**
701
     * @psalm-assert !falsy $value
702
     *
703
     * @param mixed  $value
704
     * @param string $message
705
     *
706
     * @throws InvalidArgumentException
707
     */
708
    public static function notFalse($value, $message = '')
709
    {
710
        if (false === $value) {
711
            static::reportInvalidArgument(
712
                $message ?: 'Expected a value other than false.'
713
            );
714
        }
715
    }
716
717
    /**
718
     * @param mixed  $value
719
     * @param string $message
720
     *
721
     * @throws InvalidArgumentException
722
     */
723 51 View Code Duplication
    public static function ip($value, $message = '')
724
    {
725 51
        if (false === \filter_var($value, \FILTER_VALIDATE_IP)) {
726 19
            static::reportInvalidArgument(\sprintf(
727 19
                $message ?: 'Expected a value to be an IP. Got: %s',
728 19
                static::valueToString($value)
729
            ));
730
        }
731 32
    }
732
733
    /**
734
     * @param mixed  $value
735
     * @param string $message
736
     *
737
     * @throws InvalidArgumentException
738
     */
739 51 View Code Duplication
    public static function ipv4($value, $message = '')
740
    {
741 51
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
742 35
            static::reportInvalidArgument(\sprintf(
743 35
                $message ?: 'Expected a value to be an IPv4. Got: %s',
744 35
                static::valueToString($value)
745
            ));
746
        }
747 16
    }
748
749
    /**
750
     * @param mixed  $value
751
     * @param string $message
752
     *
753
     * @throws InvalidArgumentException
754
     */
755 51 View Code Duplication
    public static function ipv6($value, $message = '')
756
    {
757 51
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
758 31
            static::reportInvalidArgument(\sprintf(
759 31
                $message ?: 'Expected a value to be an IPv6. Got %s',
760 31
                static::valueToString($value)
761
            ));
762
        }
763 20
    }
764
765
    /**
766
     * @param mixed  $value
767
     * @param string $message
768
     *
769
     * @throws InvalidArgumentException
770
     */
771 20 View Code Duplication
    public static function email($value, $message = '')
772
    {
773 20
        if (false === \filter_var($value, FILTER_VALIDATE_EMAIL)) {
774 12
            static::reportInvalidArgument(\sprintf(
775 12
                $message ?: 'Expected a value to be a valid e-mail address. Got %s',
776 12
                static::valueToString($value)
777
            ));
778
        }
779 8
    }
780
781
    /**
782
     * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion.
783
     *
784
     * @param array  $values
785
     * @param string $message
786
     *
787
     * @throws InvalidArgumentException
788
     */
789 12
    public static function uniqueValues(array $values, $message = '')
790
    {
791 12
        $allValues = \count($values);
792 12
        $uniqueValues = \count(\array_unique($values));
793
794 12
        if ($allValues !== $uniqueValues) {
795 8
            $difference = $allValues - $uniqueValues;
796
797 8
            static::reportInvalidArgument(\sprintf(
798 8
                $message ?: 'Expected an array of unique values, but %s of them %s duplicated',
799 8
                $difference,
800 8
                (1 === $difference ? 'is' : 'are')
801
            ));
802
        }
803 4
    }
804
805
    /**
806
     * @param mixed  $value
807
     * @param mixed  $expect
808
     * @param string $message
809
     *
810
     * @throws InvalidArgumentException
811
     */
812 33
    public static function eq($value, $expect, $message = '')
813
    {
814 33
        if ($expect != $value) {
815 17
            static::reportInvalidArgument(\sprintf(
816 17
                $message ?: 'Expected a value equal to %2$s. Got: %s',
817 17
                static::valueToString($value),
818 17
                static::valueToString($expect)
819
            ));
820
        }
821 16
    }
822
823
    /**
824
     * @param mixed  $value
825
     * @param mixed  $expect
826
     * @param string $message
827
     *
828
     * @throws InvalidArgumentException
829
     */
830 28
    public static function notEq($value, $expect, $message = '')
831
    {
832 28
        if ($expect == $value) {
833 16
            static::reportInvalidArgument(\sprintf(
834 16
                $message ?: 'Expected a different value than %s.',
835 16
                static::valueToString($expect)
836
            ));
837
        }
838 12
    }
839
840
    /**
841
     * @param mixed  $value
842
     * @param mixed  $expect
843
     * @param string $message
844
     *
845
     * @throws InvalidArgumentException
846
     */
847 16
    public static function same($value, $expect, $message = '')
848
    {
849 16
        if ($expect !== $value) {
850 12
            static::reportInvalidArgument(\sprintf(
851 12
                $message ?: 'Expected a value identical to %2$s. Got: %s',
852 12
                static::valueToString($value),
853 12
                static::valueToString($expect)
854
            ));
855
        }
856 4
    }
857
858
    /**
859
     * @param mixed  $value
860
     * @param mixed  $expect
861
     * @param string $message
862
     *
863
     * @throws InvalidArgumentException
864
     */
865 16
    public static function notSame($value, $expect, $message = '')
866
    {
867 16
        if ($expect === $value) {
868 4
            static::reportInvalidArgument(\sprintf(
869 4
                $message ?: 'Expected a value not identical to %s.',
870 4
                static::valueToString($expect)
871
            ));
872
        }
873 12
    }
874
875
    /**
876
     * @param mixed  $value
877
     * @param mixed  $limit
878
     * @param string $message
879
     *
880
     * @throws InvalidArgumentException
881
     */
882 8
    public static function greaterThan($value, $limit, $message = '')
883
    {
884 8
        if ($value <= $limit) {
885 4
            static::reportInvalidArgument(\sprintf(
886 4
                $message ?: 'Expected a value greater than %2$s. Got: %s',
887 4
                static::valueToString($value),
888 4
                static::valueToString($limit)
889
            ));
890
        }
891 4
    }
892
893
    /**
894
     * @param mixed  $value
895
     * @param mixed  $limit
896
     * @param string $message
897
     *
898
     * @throws InvalidArgumentException
899
     */
900 12
    public static function greaterThanEq($value, $limit, $message = '')
901
    {
902 12
        if ($value < $limit) {
903 4
            static::reportInvalidArgument(\sprintf(
904 4
                $message ?: 'Expected a value greater than or equal to %2$s. Got: %s',
905 4
                static::valueToString($value),
906 4
                static::valueToString($limit)
907
            ));
908
        }
909 8
    }
910
911
    /**
912
     * @param mixed  $value
913
     * @param mixed  $limit
914
     * @param string $message
915
     *
916
     * @throws InvalidArgumentException
917
     */
918 8
    public static function lessThan($value, $limit, $message = '')
919
    {
920 8
        if ($value >= $limit) {
921 4
            static::reportInvalidArgument(\sprintf(
922 4
                $message ?: 'Expected a value less than %2$s. Got: %s',
923 4
                static::valueToString($value),
924 4
                static::valueToString($limit)
925
            ));
926
        }
927 4
    }
928
929
    /**
930
     * @param mixed  $value
931
     * @param mixed  $limit
932
     * @param string $message
933
     *
934
     * @throws InvalidArgumentException
935
     */
936 12
    public static function lessThanEq($value, $limit, $message = '')
937
    {
938 12
        if ($value > $limit) {
939 4
            static::reportInvalidArgument(\sprintf(
940 4
                $message ?: 'Expected a value less than or equal to %2$s. Got: %s',
941 4
                static::valueToString($value),
942 4
                static::valueToString($limit)
943
            ));
944
        }
945 8
    }
946
947
    /**
948
     * Inclusive range, so Assert::(3, 3, 5) passes.
949
     *
950
     * @param mixed  $value
951
     * @param mixed  $min
952
     * @param mixed  $max
953
     * @param string $message
954
     *
955
     * @throws InvalidArgumentException
956
     */
957 16 View Code Duplication
    public static function range($value, $min, $max, $message = '')
958
    {
959 16
        if ($value < $min || $value > $max) {
960 8
            static::reportInvalidArgument(\sprintf(
961 8
                $message ?: 'Expected a value between %2$s and %3$s. Got: %s',
962 8
                static::valueToString($value),
963 8
                static::valueToString($min),
964 8
                static::valueToString($max)
965
            ));
966
        }
967 8
    }
968
969
    /**
970
     * Does strict comparison, so Assert::oneOf(3, ['3']) does not pass the assertion.
971
     *
972
     * @param mixed  $value
973
     * @param array  $values
974
     * @param string $message
975
     *
976
     * @throws InvalidArgumentException
977
     */
978 8
    public static function oneOf($value, array $values, $message = '')
979
    {
980 8
        if (!\in_array($value, $values, true)) {
981 4
            static::reportInvalidArgument(\sprintf(
982 4
                $message ?: 'Expected one of: %2$s. Got: %s',
983 4
                static::valueToString($value),
984 4
                \implode(', ', \array_map(array('static', 'valueToString'), $values))
985
            ));
986
        }
987 4
    }
988
989
    /**
990
     * @param mixed  $value
991
     * @param string $subString
992
     * @param string $message
993
     *
994
     * @throws InvalidArgumentException
995
     */
996 80 View Code Duplication
    public static function contains($value, $subString, $message = '')
997
    {
998 80
        if (false === \strpos($value, $subString)) {
999 32
            static::reportInvalidArgument(\sprintf(
1000 32
                $message ?: 'Expected a value to contain %2$s. Got: %s',
1001 32
                static::valueToString($value),
1002 32
                static::valueToString($subString)
1003
            ));
1004
        }
1005 48
    }
1006
1007
    /**
1008
     * @param mixed  $value
1009
     * @param string $subString
1010
     * @param string $message
1011
     *
1012
     * @throws InvalidArgumentException
1013
     */
1014 80 View Code Duplication
    public static function notContains($value, $subString, $message = '')
1015
    {
1016 80
        if (false !== \strpos($value, $subString)) {
1017 48
            static::reportInvalidArgument(\sprintf(
1018 48
                $message ?: '%2$s was not expected to be contained in a value. Got: %s',
1019 48
                static::valueToString($value),
1020 48
                static::valueToString($subString)
1021
            ));
1022
        }
1023 32
    }
1024
1025
    /**
1026
     * @param mixed  $value
1027
     * @param string $message
1028
     *
1029
     * @throws InvalidArgumentException
1030
     */
1031 40
    public static function notWhitespaceOnly($value, $message = '')
1032
    {
1033 40
        if (\preg_match('/^\s*$/', $value)) {
1034 24
            static::reportInvalidArgument(\sprintf(
1035 24
                $message ?: 'Expected a non-whitespace string. Got: %s',
1036 24
                static::valueToString($value)
1037
            ));
1038
        }
1039 16
    }
1040
1041
    /**
1042
     * @param mixed  $value
1043
     * @param string $prefix
1044
     * @param string $message
1045
     *
1046
     * @throws InvalidArgumentException
1047
     */
1048 48 View Code Duplication
    public static function startsWith($value, $prefix, $message = '')
1049
    {
1050 48
        if (0 !== \strpos($value, $prefix)) {
1051 32
            static::reportInvalidArgument(\sprintf(
1052 32
                $message ?: 'Expected a value to start with %2$s. Got: %s',
1053 32
                static::valueToString($value),
1054 32
                static::valueToString($prefix)
1055
            ));
1056
        }
1057 16
    }
1058
1059
    /**
1060
     * @param mixed  $value
1061
     * @param string $message
1062
     *
1063
     * @throws InvalidArgumentException
1064
     */
1065 35
    public static function startsWithLetter($value, $message = '')
1066
    {
1067 35
        static::string($value);
1068
1069 24
        $valid = isset($value[0]);
1070
1071 24
        if ($valid) {
1072 20
            $locale = \setlocale(LC_CTYPE, 0);
1073 20
            \setlocale(LC_CTYPE, 'C');
1074 20
            $valid = \ctype_alpha($value[0]);
1075 20
            \setlocale(LC_CTYPE, $locale);
1076
        }
1077
1078 24
        if (!$valid) {
1079 12
            static::reportInvalidArgument(\sprintf(
1080 12
                $message ?: 'Expected a value to start with a letter. Got: %s',
1081 12
                static::valueToString($value)
1082
            ));
1083
        }
1084 12
    }
1085
1086
    /**
1087
     * @param mixed  $value
1088
     * @param string $suffix
1089
     * @param string $message
1090
     *
1091
     * @throws InvalidArgumentException
1092
     */
1093 48 View Code Duplication
    public static function endsWith($value, $suffix, $message = '')
1094
    {
1095 48
        if ($suffix !== \substr($value, -\strlen($suffix))) {
1096 32
            static::reportInvalidArgument(\sprintf(
1097 32
                $message ?: 'Expected a value to end with %2$s. Got: %s',
1098 32
                static::valueToString($value),
1099 32
                static::valueToString($suffix)
1100
            ));
1101
        }
1102 16
    }
1103
1104
    /**
1105
     * @param mixed  $value
1106
     * @param mixed  $pattern
1107
     * @param string $message
1108
     *
1109
     * @throws InvalidArgumentException
1110
     */
1111 12
    public static function regex($value, $pattern, $message = '')
1112
    {
1113 12
        if (!\preg_match($pattern, $value)) {
1114 8
            static::reportInvalidArgument(\sprintf(
1115 8
                $message ?: 'The value %s does not match the expected pattern.',
1116 8
                static::valueToString($value)
1117
            ));
1118
        }
1119 4
    }
1120
1121
    /**
1122
     * @param mixed  $value
1123
     * @param mixed  $pattern
1124
     * @param string $message
1125
     *
1126
     * @throws InvalidArgumentException
1127
     */
1128 12
    public static function notRegex($value, $pattern, $message = '')
1129
    {
1130 12
        if (\preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) {
1131 4
            static::reportInvalidArgument(\sprintf(
1132 4
                $message ?: 'The value %s matches the pattern %s (at offset %d).',
1133 4
                static::valueToString($value),
1134 4
                static::valueToString($pattern),
1135 4
                $matches[0][1]
1136
            ));
1137
        }
1138 8
    }
1139
1140
    /**
1141
     * @param mixed  $value
1142
     * @param string $message
1143
     *
1144
     * @throws InvalidArgumentException
1145
     */
1146 28 View Code Duplication
    public static function unicodeLetters($value, $message = '')
1147
    {
1148 28
        static::string($value);
1149
1150 28
        if (!\preg_match('/^\p{L}+$/u', $value)) {
1151 16
            static::reportInvalidArgument(\sprintf(
1152 16
                $message ?: 'Expected a value to contain only Unicode letters. Got: %s',
1153 16
                static::valueToString($value)
1154
            ));
1155
        }
1156 12
    }
1157
1158
    /**
1159
     * @param mixed  $value
1160
     * @param string $message
1161
     *
1162
     * @throws InvalidArgumentException
1163
     */
1164 20 View Code Duplication
    public static function alpha($value, $message = '')
1165
    {
1166 20
        static::string($value);
1167
1168 12
        $locale = \setlocale(LC_CTYPE, 0);
1169 12
        \setlocale(LC_CTYPE, 'C');
1170 12
        $valid = !\ctype_alpha($value);
1171 12
        \setlocale(LC_CTYPE, $locale);
1172
1173 12
        if ($valid) {
1174 8
            static::reportInvalidArgument(\sprintf(
1175 8
                $message ?: 'Expected a value to contain only letters. Got: %s',
1176 8
                static::valueToString($value)
1177
            ));
1178
        }
1179 4
    }
1180
1181
    /**
1182
     * @param mixed  $value
1183
     * @param string $message
1184
     *
1185
     * @throws InvalidArgumentException
1186
     */
1187 12 View Code Duplication
    public static function digits($value, $message = '')
1188
    {
1189 12
        $locale = \setlocale(LC_CTYPE, 0);
1190 12
        \setlocale(LC_CTYPE, 'C');
1191 12
        $valid = !\ctype_digit($value);
1192 12
        \setlocale(LC_CTYPE, $locale);
1193
1194 12
        if ($valid) {
1195 8
            static::reportInvalidArgument(\sprintf(
1196 8
                $message ?: 'Expected a value to contain digits only. Got: %s',
1197 8
                static::valueToString($value)
1198
            ));
1199
        }
1200 4
    }
1201
1202
    /**
1203
     * @param mixed  $value
1204
     * @param string $message
1205
     *
1206
     * @throws InvalidArgumentException
1207
     */
1208 12 View Code Duplication
    public static function alnum($value, $message = '')
1209
    {
1210 12
        $locale = \setlocale(LC_CTYPE, 0);
1211 12
        \setlocale(LC_CTYPE, 'C');
1212 12
        $valid = !\ctype_alnum($value);
1213 12
        \setlocale(LC_CTYPE, $locale);
1214
1215 12
        if ($valid) {
1216 8
            static::reportInvalidArgument(\sprintf(
1217 8
                $message ?: 'Expected a value to contain letters and digits only. Got: %s',
1218 8
                static::valueToString($value)
1219
            ));
1220
        }
1221 4
    }
1222
1223
    /**
1224
     * @param mixed  $value
1225
     * @param string $message
1226
     *
1227
     * @throws InvalidArgumentException
1228
     */
1229 16 View Code Duplication
    public static function lower($value, $message = '')
1230
    {
1231 16
        $locale = \setlocale(LC_CTYPE, 0);
1232 16
        \setlocale(LC_CTYPE, 'C');
1233 16
        $valid = !\ctype_lower($value);
1234 16
        \setlocale(LC_CTYPE, $locale);
1235
1236 16
        if ($valid) {
1237 12
            static::reportInvalidArgument(\sprintf(
1238 12
                $message ?: 'Expected a value to contain lowercase characters only. Got: %s',
1239 12
                static::valueToString($value)
1240
            ));
1241
        }
1242 4
    }
1243
1244
    /**
1245
     * @param mixed  $value
1246
     * @param string $message
1247
     *
1248
     * @throws InvalidArgumentException
1249
     */
1250 16 View Code Duplication
    public static function upper($value, $message = '')
1251
    {
1252 16
        $locale = \setlocale(LC_CTYPE, 0);
1253 16
        \setlocale(LC_CTYPE, 'C');
1254 16
        $valid = !\ctype_upper($value);
1255 16
        \setlocale(LC_CTYPE, $locale);
1256
1257 16
        if ($valid) {
1258 12
            static::reportInvalidArgument(\sprintf(
1259 12
                $message ?: 'Expected a value to contain uppercase characters only. Got: %s',
1260 12
                static::valueToString($value)
1261
            ));
1262
        }
1263 4
    }
1264
1265
    /**
1266
     * @param mixed  $value
1267
     * @param mixed  $length
1268
     * @param string $message
1269
     *
1270
     * @throws InvalidArgumentException
1271
     */
1272 36
    public static function length($value, $length, $message = '')
1273
    {
1274 36
        if ($length !== static::strlen($value)) {
1275 24
            static::reportInvalidArgument(\sprintf(
1276 24
                $message ?: 'Expected a value to contain %2$s characters. Got: %s',
1277 24
                static::valueToString($value),
1278 24
                $length
1279
            ));
1280
        }
1281 12
    }
1282
1283
    /**
1284
     * Inclusive min.
1285
     *
1286
     * @param mixed  $value
1287
     * @param mixed  $min
1288
     * @param string $message
1289
     *
1290
     * @throws InvalidArgumentException
1291
     */
1292 36
    public static function minLength($value, $min, $message = '')
1293
    {
1294 36
        if (static::strlen($value) < $min) {
1295 12
            static::reportInvalidArgument(\sprintf(
1296 12
                $message ?: 'Expected a value to contain at least %2$s characters. Got: %s',
1297 12
                static::valueToString($value),
1298 12
                $min
1299
            ));
1300
        }
1301 24
    }
1302
1303
    /**
1304
     * Inclusive max.
1305
     *
1306
     * @param mixed  $value
1307
     * @param mixed  $max
1308
     * @param string $message
1309
     *
1310
     * @throws InvalidArgumentException
1311
     */
1312 36
    public static function maxLength($value, $max, $message = '')
1313
    {
1314 36
        if (static::strlen($value) > $max) {
1315 12
            static::reportInvalidArgument(\sprintf(
1316 12
                $message ?: 'Expected a value to contain at most %2$s characters. Got: %s',
1317 12
                static::valueToString($value),
1318 12
                $max
1319
            ));
1320
        }
1321 24
    }
1322
1323
    /**
1324
     * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion.
1325
     *
1326
     * @param mixed  $value
1327
     * @param mixed  $min
1328
     * @param mixed  $max
1329
     * @param string $message
1330
     *
1331
     * @throws InvalidArgumentException
1332
     */
1333 60 View Code Duplication
    public static function lengthBetween($value, $min, $max, $message = '')
1334
    {
1335 60
        $length = static::strlen($value);
1336
1337 60
        if ($length < $min || $length > $max) {
1338 24
            static::reportInvalidArgument(\sprintf(
1339 24
                $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s',
1340 24
                static::valueToString($value),
1341 24
                $min,
1342 24
                $max
1343
            ));
1344
        }
1345 36
    }
1346
1347
    /**
1348
     * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file.
1349
     *
1350
     * @param mixed  $value
1351
     * @param string $message
1352
     *
1353
     * @throws InvalidArgumentException
1354
     */
1355 36 View Code Duplication
    public static function fileExists($value, $message = '')
1356
    {
1357 36
        static::string($value);
1358
1359 36
        if (!\file_exists($value)) {
1360 12
            static::reportInvalidArgument(\sprintf(
1361 12
                $message ?: 'The file %s does not exist.',
1362 12
                static::valueToString($value)
1363
            ));
1364
        }
1365 24
    }
1366
1367
    /**
1368
     * @param mixed  $value
1369
     * @param string $message
1370
     *
1371
     * @throws InvalidArgumentException
1372
     */
1373 12 View Code Duplication
    public static function file($value, $message = '')
1374
    {
1375 12
        static::fileExists($value, $message);
1376
1377 8
        if (!\is_file($value)) {
1378 4
            static::reportInvalidArgument(\sprintf(
1379 4
                $message ?: 'The path %s is not a file.',
1380 4
                static::valueToString($value)
1381
            ));
1382
        }
1383 4
    }
1384
1385
    /**
1386
     * @param mixed  $value
1387
     * @param string $message
1388
     *
1389
     * @throws InvalidArgumentException
1390
     */
1391 12 View Code Duplication
    public static function directory($value, $message = '')
1392
    {
1393 12
        static::fileExists($value, $message);
1394
1395 8
        if (!\is_dir($value)) {
1396 4
            static::reportInvalidArgument(\sprintf(
1397 4
                $message ?: 'The path %s is no directory.',
1398 4
                static::valueToString($value)
1399
            ));
1400
        }
1401 4
    }
1402
1403
    /**
1404
     * @param mixed  $value
1405
     * @param string $message
1406
     *
1407
     * @throws InvalidArgumentException
1408
     */
1409
    public static function readable($value, $message = '')
1410
    {
1411
        if (!\is_readable($value)) {
1412
            static::reportInvalidArgument(\sprintf(
1413
                $message ?: 'The path %s is not readable.',
1414
                static::valueToString($value)
1415
            ));
1416
        }
1417
    }
1418
1419
    /**
1420
     * @param mixed  $value
1421
     * @param string $message
1422
     *
1423
     * @throws InvalidArgumentException
1424
     */
1425
    public static function writable($value, $message = '')
1426
    {
1427
        if (!\is_writable($value)) {
1428
            static::reportInvalidArgument(\sprintf(
1429
                $message ?: 'The path %s is not writable.',
1430
                static::valueToString($value)
1431
            ));
1432
        }
1433
    }
1434
1435
    /**
1436
     * @psalm-assert class-string $value
1437
     *
1438
     * @param mixed  $value
1439
     * @param string $message
1440
     *
1441
     * @throws InvalidArgumentException
1442
     */
1443 8
    public static function classExists($value, $message = '')
1444
    {
1445 8
        if (!\class_exists($value)) {
1446 4
            static::reportInvalidArgument(\sprintf(
1447 4
                $message ?: 'Expected an existing class name. Got: %s',
1448 4
                static::valueToString($value)
1449
            ));
1450
        }
1451 4
    }
1452
1453
    /**
1454
     * @param mixed         $value
1455
     * @param string|object $class
1456
     * @param string        $message
1457
     *
1458
     * @throws InvalidArgumentException
1459
     */
1460 8
    public static function subclassOf($value, $class, $message = '')
1461
    {
1462 8
        if (!\is_subclass_of($value, $class)) {
1463 4
            static::reportInvalidArgument(\sprintf(
1464 4
                $message ?: 'Expected a sub-class of %2$s. Got: %s',
1465 4
                static::valueToString($value),
1466 4
                static::valueToString($class)
1467
            ));
1468
        }
1469 4
    }
1470
1471
    /**
1472
     * @psalm-assert class-string $value
1473
     *
1474
     * @param mixed  $value
1475
     * @param string $message
1476
     *
1477
     * @throws InvalidArgumentException
1478
     */
1479 8
    public static function interfaceExists($value, $message = '')
1480
    {
1481 8
        if (!\interface_exists($value)) {
1482 4
            static::reportInvalidArgument(\sprintf(
1483 4
                $message ?: 'Expected an existing interface name. got %s',
1484 4
                static::valueToString($value)
1485
            ));
1486
        }
1487 4
    }
1488
1489
    /**
1490
     * @param mixed  $value
1491
     * @param mixed  $interface
1492
     * @param string $message
1493
     *
1494
     * @throws InvalidArgumentException
1495
     */
1496 8 View Code Duplication
    public static function implementsInterface($value, $interface, $message = '')
1497
    {
1498 8
        if (!\in_array($interface, \class_implements($value))) {
1499 4
            static::reportInvalidArgument(\sprintf(
1500 4
                $message ?: 'Expected an implementation of %2$s. Got: %s',
1501 4
                static::valueToString($value),
1502 4
                static::valueToString($interface)
1503
            ));
1504
        }
1505 4
    }
1506
1507
    /**
1508
     * @param string|object $classOrObject
1509
     * @param mixed         $property
1510
     * @param string        $message
1511
     *
1512
     * @throws InvalidArgumentException
1513
     */
1514 12 View Code Duplication
    public static function propertyExists($classOrObject, $property, $message = '')
1515
    {
1516 12
        if (!\property_exists($classOrObject, $property)) {
1517 4
            static::reportInvalidArgument(\sprintf(
1518 4
                $message ?: 'Expected the property %s to exist.',
1519 4
                static::valueToString($property)
1520
            ));
1521
        }
1522 8
    }
1523
1524
    /**
1525
     * @param string|object $classOrObject
1526
     * @param mixed         $property
1527
     * @param string        $message
1528
     *
1529
     * @throws InvalidArgumentException
1530
     */
1531 12 View Code Duplication
    public static function propertyNotExists($classOrObject, $property, $message = '')
1532
    {
1533 12
        if (\property_exists($classOrObject, $property)) {
1534 8
            static::reportInvalidArgument(\sprintf(
1535 8
                $message ?: 'Expected the property %s to not exist.',
1536 8
                static::valueToString($property)
1537
            ));
1538
        }
1539 4
    }
1540
1541
    /**
1542
     * @param string|object $classOrObject
1543
     * @param mixed         $method
1544
     * @param string        $message
1545
     *
1546
     * @throws InvalidArgumentException
1547
     */
1548 27 View Code Duplication
    public static function methodExists($classOrObject, $method, $message = '')
1549
    {
1550 27
        if (!\method_exists($classOrObject, $method)) {
1551 19
            static::reportInvalidArgument(\sprintf(
1552 19
                $message ?: 'Expected the method %s to exist.',
1553 19
                static::valueToString($method)
1554
            ));
1555
        }
1556 8
    }
1557
1558
    /**
1559
     * @param string|object $classOrObject
1560
     * @param mixed         $method
1561
     * @param string        $message
1562
     *
1563
     * @throws InvalidArgumentException
1564
     */
1565 27 View Code Duplication
    public static function methodNotExists($classOrObject, $method, $message = '')
1566
    {
1567 27
        if (\method_exists($classOrObject, $method)) {
1568 8
            static::reportInvalidArgument(\sprintf(
1569 8
                $message ?: 'Expected the method %s to not exist.',
1570 8
                static::valueToString($method)
1571
            ));
1572
        }
1573 19
    }
1574
1575
    /**
1576
     * @param array      $array
1577
     * @param string|int $key
1578
     * @param string     $message
1579
     *
1580
     * @throws InvalidArgumentException
1581
     */
1582 12 View Code Duplication
    public static function keyExists($array, $key, $message = '')
1583
    {
1584 12
        if (!(isset($array[$key]) || \array_key_exists($key, $array))) {
1585 4
            static::reportInvalidArgument(\sprintf(
1586 4
                $message ?: 'Expected the key %s to exist.',
1587 4
                static::valueToString($key)
1588
            ));
1589
        }
1590 8
    }
1591
1592
    /**
1593
     * @param array      $array
1594
     * @param string|int $key
1595
     * @param string     $message
1596
     *
1597
     * @throws InvalidArgumentException
1598
     */
1599 12 View Code Duplication
    public static function keyNotExists($array, $key, $message = '')
1600
    {
1601 12
        if (isset($array[$key]) || \array_key_exists($key, $array)) {
1602 8
            static::reportInvalidArgument(\sprintf(
1603 8
                $message ?: 'Expected the key %s to not exist.',
1604 8
                static::valueToString($key)
1605
            ));
1606
        }
1607 4
    }
1608
1609
    /**
1610
     * Checks if a value is a valid array key (int or string).
1611
     *
1612
     * @psalm-assert array-key $value
1613
     *
1614
     * @param mixed  $value
1615
     * @param string $message
1616
     *
1617
     * @throws InvalidArgumentException
1618
     */
1619 28
    public static function validArrayKey($value, $message = '')
1620
    {
1621 28
        if (!(\is_int($value) || \is_string($value))) {
1622 20
            static::reportInvalidArgument(\sprintf(
1623 20
                $message ?: 'Expected string or integer. Got: %s',
1624 20
                static::typeToString($value)
1625
            ));
1626
        }
1627 8
    }
1628
1629
    /**
1630
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1631
     *
1632
     * @param mixed  $array
1633
     * @param mixed  $number
1634
     * @param string $message
1635
     *
1636
     * @throws InvalidArgumentException
1637
     */
1638 8
    public static function count($array, $number, $message = '')
1639
    {
1640 8
        static::eq(
1641 8
            \count($array),
1642
            $number,
1643 8
            $message ?: \sprintf('Expected an array to contain %d elements. Got: %d.', $number, \count($array))
1644
        );
1645 4
    }
1646
1647
    /**
1648
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1649
     *
1650
     * @param mixed  $array
1651
     * @param mixed  $min
1652
     * @param string $message
1653
     *
1654
     * @throws InvalidArgumentException
1655
     */
1656 12 View Code Duplication
    public static function minCount($array, $min, $message = '')
1657
    {
1658 12
        if (\count($array) < $min) {
1659 4
            static::reportInvalidArgument(\sprintf(
1660 4
                $message ?: 'Expected an array to contain at least %2$d elements. Got: %d',
1661 4
                \count($array),
1662 4
                $min
1663
            ));
1664
        }
1665 8
    }
1666
1667
    /**
1668
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1669
     *
1670
     * @param mixed  $array
1671
     * @param mixed  $max
1672
     * @param string $message
1673
     *
1674
     * @throws InvalidArgumentException
1675
     */
1676 12 View Code Duplication
    public static function maxCount($array, $max, $message = '')
1677
    {
1678 12
        if (\count($array) > $max) {
1679 4
            static::reportInvalidArgument(\sprintf(
1680 4
                $message ?: 'Expected an array to contain at most %2$d elements. Got: %d',
1681 4
                \count($array),
1682 4
                $max
1683
            ));
1684
        }
1685 8
    }
1686
1687
    /**
1688
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1689
     *
1690
     * @param mixed  $array
1691
     * @param mixed  $min
1692
     * @param mixed  $max
1693
     * @param string $message
1694
     *
1695
     * @throws InvalidArgumentException
1696
     */
1697 20
    public static function countBetween($array, $min, $max, $message = '')
1698
    {
1699 20
        $count = \count($array);
1700
1701 20
        if ($count < $min || $count > $max) {
1702 8
            static::reportInvalidArgument(\sprintf(
1703 8
                $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d',
1704 8
                $count,
1705 8
                $min,
1706 8
                $max
1707
            ));
1708
        }
1709 12
    }
1710
1711
    /**
1712
     * @psalm-assert list $array
1713
     *
1714
     * @param mixed  $array
1715
     * @param string $message
1716
     *
1717
     * @throws InvalidArgumentException
1718
     */
1719 80 View Code Duplication
    public static function isList($array, $message = '')
1720
    {
1721 80
        if (!\is_array($array) || $array !== \array_values($array)) {
1722 32
            static::reportInvalidArgument(
1723 32
                $message ?: 'Expected list - non-associative array.'
1724
            );
1725
        }
1726 48
    }
1727
1728
    /**
1729
     * @psalm-assert non-empty-list $array
1730
     *
1731
     * @param mixed  $array
1732
     * @param string $message
1733
     *
1734
     * @throws InvalidArgumentException
1735
     */
1736 40
    public static function isNonEmptyList($array, $message = '')
1737
    {
1738 40
        static::isList($array, $message);
1739 24
        static::notEmpty($array, $message);
1740 20
    }
1741
1742
    /**
1743
     * @param mixed  $array
1744
     * @param string $message
1745
     *
1746
     * @throws InvalidArgumentException
1747
     */
1748 32
    public static function isMap($array, $message = '')
1749
    {
1750
        if (
1751 32
            !\is_array($array) ||
1752 32
            \array_keys($array) !== \array_filter(\array_keys($array), '\is_string')
1753
        ) {
1754 16
            static::reportInvalidArgument(
1755 16
                $message ?: 'Expected map - associative array with string keys.'
1756
            );
1757
        }
1758 16
    }
1759
1760
    /**
1761
     * @param mixed  $array
1762
     * @param string $message
1763
     *
1764
     * @throws InvalidArgumentException
1765
     */
1766 16
    public static function isNonEmptyMap($array, $message = '')
1767
    {
1768 16
        static::isMap($array, $message);
1769 8
        static::notEmpty($array, $message);
1770 4
    }
1771
1772
    /**
1773
     * @param mixed  $value
1774
     * @param string $message
1775
     *
1776
     * @throws InvalidArgumentException
1777
     */
1778 56
    public static function uuid($value, $message = '')
1779
    {
1780 56
        $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
1781
1782
        // The nil UUID is special form of UUID that is specified to have all
1783
        // 128 bits set to zero.
1784 56
        if ('00000000-0000-0000-0000-000000000000' === $value) {
1785 4
            return;
1786
        }
1787
1788 52
        if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) {
1789 20
            static::reportInvalidArgument(\sprintf(
1790 20
                $message ?: 'Value %s is not a valid UUID.',
1791 20
                static::valueToString($value)
1792
            ));
1793
        }
1794 32
    }
1795
1796
    /**
1797
     * @param Closure       $expression
1798
     * @param string|object $class
1799
     * @param string        $message
1800
     *
1801
     * @throws InvalidArgumentException
1802
     */
1803 24
    public static function throws(Closure $expression, $class = 'Exception', $message = '')
1804
    {
1805 24
        static::string($class);
1806
1807 24
        $actual = 'none';
1808
1809
        try {
1810 24
            $expression();
1811 24
        } catch (Exception $e) {
1812 20
            $actual = \get_class($e);
1813 20
            if ($e instanceof $class) {
1814 20
                return;
1815
            }
1816 4
        } catch (Throwable $e) {
0 ignored issues
show
Bug introduced by
The class Throwable does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
1817 4
            $actual = \get_class($e);
1818 4
            if ($e instanceof $class) {
1819 4
                return;
1820
            }
1821
        }
1822
1823 8
        static::reportInvalidArgument($message ?: \sprintf(
1824 8
            'Expected to throw "%s", got "%s"',
1825 8
            $class,
1826 8
            $actual
1827
        ));
1828
    }
1829
1830
    /**
1831
     * @throws BadMethodCallException
1832
     */
1833 1494
    public static function __callStatic($name, $arguments)
1834
    {
1835 1494
        if ('nullOr' === \substr($name, 0, 6)) {
1836 553
            if (null !== $arguments[0]) {
1837 455
                $method = \lcfirst(\substr($name, 6));
1838 455
                \call_user_func_array(array('static', $method), $arguments);
1839
            }
1840
1841 320
            return;
1842
        }
1843
1844 941
        if ('all' === \substr($name, 0, 3)) {
1845 940
            static::isIterable($arguments[0]);
1846
1847 940
            $method = \lcfirst(\substr($name, 3));
1848 940
            $args = $arguments;
1849
1850 940
            foreach ($arguments[0] as $entry) {
1851 940
                $args[0] = $entry;
1852
1853 940
                \call_user_func_array(array('static', $method), $args);
1854
            }
1855
1856 450
            return;
1857
        }
1858
1859 1
        throw new BadMethodCallException('No such method: '.$name);
1860
    }
1861
1862
    /**
1863
     * @param mixed $value
1864
     *
1865
     * @return string
1866
     */
1867 702
    protected static function valueToString($value)
1868
    {
1869 702
        if (null === $value) {
1870 20
            return 'null';
1871
        }
1872
1873 684
        if (true === $value) {
1874 15
            return 'true';
1875
        }
1876
1877 674
        if (false === $value) {
1878 25
            return 'false';
1879
        }
1880
1881 649
        if (\is_array($value)) {
1882 21
            return 'array';
1883
        }
1884
1885 628
        if (\is_object($value)) {
1886 2
            if (\method_exists($value, '__toString')) {
1887 1
                return \get_class($value).': '.self::valueToString($value->__toString());
1888
            }
1889
1890 1
            return \get_class($value);
1891
        }
1892
1893 627
        if (\is_resource($value)) {
1894 1
            return 'resource';
1895
        }
1896
1897 627
        if (\is_string($value)) {
1898 525
            return '"'.$value.'"';
1899
        }
1900
1901 110
        return (string) $value;
1902
    }
1903
1904
    /**
1905
     * @param mixed $value
1906
     *
1907
     * @return string
1908
     */
1909 211
    protected static function typeToString($value)
1910
    {
1911 211
        return \is_object($value) ? \get_class($value) : \gettype($value);
1912
    }
1913
1914 168
    protected static function strlen($value)
1915
    {
1916 168
        if (!\function_exists('mb_detect_encoding')) {
1917
            return \strlen($value);
1918
        }
1919
1920 168
        if (false === $encoding = \mb_detect_encoding($value)) {
1921
            return \strlen($value);
1922
        }
1923
1924 168
        return \mb_strlen($value, $encoding);
1925
    }
1926
1927
    /**
1928
     * @param string $message
1929
     *
1930
     * @throws InvalidArgumentException
1931
     */
1932 984
    protected static function reportInvalidArgument($message)
1933
    {
1934 984
        throw new InvalidArgumentException($message);
1935
    }
1936
1937
    private function __construct()
1938
    {
1939
    }
1940
}
1941