Failed Conditions
Pull Request — master (#106)
by Simon
15:33
created

Assert::isArrayAccessible()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 9

Duplication

Lines 9
Ratio 100 %

Code Coverage

Tests 1
CRAP Score 4

Importance

Changes 0
Metric Value
dl 9
loc 9
ccs 1
cts 1
cp 1
rs 9.9666
c 0
b 0
f 0
cc 4
nc 2
nop 2
crap 4
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 nullOrIsAOf($value, $classes, $message = '')
49
 * @method static void nullOrIsAOfAny($value, $classes, $message = '')
50
 * @method static void nullOrNotAOf($value, $classes, $message = '')
51
 * @method static void nullOrIsEmpty($value, $message = '')
52
 * @method static void nullOrNotEmpty($value, $message = '')
53
 * @method static void nullOrTrue($value, $message = '')
54
 * @method static void nullOrFalse($value, $message = '')
55
 * @method static void nullOrNotFalse($value, $message = '')
56
 * @method static void nullOrIp($value, $message = '')
57
 * @method static void nullOrIpv4($value, $message = '')
58
 * @method static void nullOrIpv6($value, $message = '')
59
 * @method static void nullOrEmail($value, $message = '')
60
 * @method static void nullOrUniqueValues($values, $message = '')
61
 * @method static void nullOrEq($value, $expect, $message = '')
62
 * @method static void nullOrNotEq($value, $expect, $message = '')
63
 * @method static void nullOrSame($value, $expect, $message = '')
64
 * @method static void nullOrNotSame($value, $expect, $message = '')
65
 * @method static void nullOrGreaterThan($value, $limit, $message = '')
66
 * @method static void nullOrGreaterThanEq($value, $limit, $message = '')
67
 * @method static void nullOrLessThan($value, $limit, $message = '')
68
 * @method static void nullOrLessThanEq($value, $limit, $message = '')
69
 * @method static void nullOrRange($value, $min, $max, $message = '')
70
 * @method static void nullOrOneOf($value, $values, $message = '')
71
 * @method static void nullOrContains($value, $subString, $message = '')
72
 * @method static void nullOrNotContains($value, $subString, $message = '')
73
 * @method static void nullOrNotWhitespaceOnly($value, $message = '')
74
 * @method static void nullOrStartsWith($value, $prefix, $message = '')
75
 * @method static void nullOrStartsWithLetter($value, $message = '')
76
 * @method static void nullOrEndsWith($value, $suffix, $message = '')
77
 * @method static void nullOrRegex($value, $pattern, $message = '')
78
 * @method static void nullOrNotRegex($value, $pattern, $message = '')
79
 * @method static void nullOrUnicodeLetters($value, $message = '')
80
 * @method static void nullOrAlpha($value, $message = '')
81
 * @method static void nullOrDigits($value, $message = '')
82
 * @method static void nullOrAlnum($value, $message = '')
83
 * @method static void nullOrLower($value, $message = '')
84
 * @method static void nullOrUpper($value, $message = '')
85
 * @method static void nullOrLength($value, $length, $message = '')
86
 * @method static void nullOrMinLength($value, $min, $message = '')
87
 * @method static void nullOrMaxLength($value, $max, $message = '')
88
 * @method static void nullOrLengthBetween($value, $min, $max, $message = '')
89
 * @method static void nullOrFileExists($value, $message = '')
90
 * @method static void nullOrFile($value, $message = '')
91
 * @method static void nullOrDirectory($value, $message = '')
92
 * @method static void nullOrReadable($value, $message = '')
93
 * @method static void nullOrWritable($value, $message = '')
94
 * @method static void nullOrClassExists($value, $message = '')
95
 * @method static void nullOrSubclassOf($value, $class, $message = '')
96
 * @method static void nullOrInterfaceExists($value, $message = '')
97
 * @method static void nullOrImplementsInterface($value, $interface, $message = '')
98
 * @method static void nullOrPropertyExists($value, $property, $message = '')
99
 * @method static void nullOrPropertyNotExists($value, $property, $message = '')
100
 * @method static void nullOrMethodExists($value, $method, $message = '')
101
 * @method static void nullOrMethodNotExists($value, $method, $message = '')
102
 * @method static void nullOrKeyExists($value, $key, $message = '')
103
 * @method static void nullOrKeyNotExists($value, $key, $message = '')
104
 * @method static void nullOrValidArrayKey($value, $message = '')
105
 * @method static void nullOrCount($value, $key, $message = '')
106
 * @method static void nullOrMinCount($value, $min, $message = '')
107
 * @method static void nullOrMaxCount($value, $max, $message = '')
108
 * @method static void nullOrIsList($value, $message = '')
109
 * @method static void nullOrIsNonEmptyList($value, $message = '')
110
 * @method static void nullOrIsMap($value, $message = '')
111
 * @method static void nullOrIsNonEmptyMap($value, $message = '')
112
 * @method static void nullOrCountBetween($value, $min, $max, $message = '')
113
 * @method static void nullOrUuid($values, $message = '')
114
 * @method static void nullOrThrows($expression, $class = 'Exception', $message = '')
115
 * @method static void allString($values, $message = '')
116
 * @method static void allStringNotEmpty($values, $message = '')
117
 * @method static void allInteger($values, $message = '')
118
 * @method static void allIntegerish($values, $message = '')
119
 * @method static void allFloat($values, $message = '')
120
 * @method static void allNumeric($values, $message = '')
121
 * @method static void allNatural($values, $message = '')
122
 * @method static void allBoolean($values, $message = '')
123
 * @method static void allScalar($values, $message = '')
124
 * @method static void allObject($values, $message = '')
125
 * @method static void allResource($values, $type = null, $message = '')
126
 * @method static void allIsCallable($values, $message = '')
127
 * @method static void allIsArray($values, $message = '')
128
 * @method static void allIsTraversable($values, $message = '')
129
 * @method static void allIsArrayAccessible($values, $message = '')
130
 * @method static void allIsCountable($values, $message = '')
131
 * @method static void allIsIterable($values, $message = '')
132
 * @method static void allIsInstanceOf($values, $class, $message = '')
133
 * @method static void allNotInstanceOf($values, $class, $message = '')
134
 * @method static void allIsInstanceOfAny($values, $classes, $message = '')
135
 * @method static void allIsAOf($values, $class, $message = '')
136
 * @method static void allIsAOfAny($values, $class, $message = '')
137
 * @method static void allNotAOf($values, $class, $message = '')
138
 * @method static void allNull($values, $message = '')
139
 * @method static void allNotNull($values, $message = '')
140
 * @method static void allIsEmpty($values, $message = '')
141
 * @method static void allNotEmpty($values, $message = '')
142
 * @method static void allTrue($values, $message = '')
143
 * @method static void allFalse($values, $message = '')
144
 * @method static void allNotFalse($values, $message = '')
145
 * @method static void allIp($values, $message = '')
146
 * @method static void allIpv4($values, $message = '')
147
 * @method static void allIpv6($values, $message = '')
148
 * @method static void allEmail($values, $message = '')
149
 * @method static void allUniqueValues($values, $message = '')
150
 * @method static void allEq($values, $expect, $message = '')
151
 * @method static void allNotEq($values, $expect, $message = '')
152
 * @method static void allSame($values, $expect, $message = '')
153
 * @method static void allNotSame($values, $expect, $message = '')
154
 * @method static void allGreaterThan($values, $limit, $message = '')
155
 * @method static void allGreaterThanEq($values, $limit, $message = '')
156
 * @method static void allLessThan($values, $limit, $message = '')
157
 * @method static void allLessThanEq($values, $limit, $message = '')
158
 * @method static void allRange($values, $min, $max, $message = '')
159
 * @method static void allOneOf($values, $values, $message = '')
160
 * @method static void allContains($values, $subString, $message = '')
161
 * @method static void allNotContains($values, $subString, $message = '')
162
 * @method static void allNotWhitespaceOnly($values, $message = '')
163
 * @method static void allStartsWith($values, $prefix, $message = '')
164
 * @method static void allStartsWithLetter($values, $message = '')
165
 * @method static void allEndsWith($values, $suffix, $message = '')
166
 * @method static void allRegex($values, $pattern, $message = '')
167
 * @method static void allNotRegex($values, $pattern, $message = '')
168
 * @method static void allUnicodeLetters($values, $message = '')
169
 * @method static void allAlpha($values, $message = '')
170
 * @method static void allDigits($values, $message = '')
171
 * @method static void allAlnum($values, $message = '')
172
 * @method static void allLower($values, $message = '')
173
 * @method static void allUpper($values, $message = '')
174
 * @method static void allLength($values, $length, $message = '')
175
 * @method static void allMinLength($values, $min, $message = '')
176
 * @method static void allMaxLength($values, $max, $message = '')
177
 * @method static void allLengthBetween($values, $min, $max, $message = '')
178
 * @method static void allFileExists($values, $message = '')
179
 * @method static void allFile($values, $message = '')
180
 * @method static void allDirectory($values, $message = '')
181
 * @method static void allReadable($values, $message = '')
182
 * @method static void allWritable($values, $message = '')
183
 * @method static void allClassExists($values, $message = '')
184
 * @method static void allSubclassOf($values, $class, $message = '')
185
 * @method static void allInterfaceExists($values, $message = '')
186
 * @method static void allImplementsInterface($values, $interface, $message = '')
187
 * @method static void allPropertyExists($values, $property, $message = '')
188
 * @method static void allPropertyNotExists($values, $property, $message = '')
189
 * @method static void allMethodExists($values, $method, $message = '')
190
 * @method static void allMethodNotExists($values, $method, $message = '')
191
 * @method static void allKeyExists($values, $key, $message = '')
192
 * @method static void allKeyNotExists($values, $key, $message = '')
193
 * @method static void allValidArrayKey($values, $message = '')
194
 * @method static void allCount($values, $key, $message = '')
195
 * @method static void allMinCount($values, $min, $message = '')
196
 * @method static void allMaxCount($values, $max, $message = '')
197
 * @method static void allCountBetween($values, $min, $max, $message = '')
198
 * @method static void allIsList($values, $message = '')
199
 * @method static void allIsNonEmptyList($values, $message = '')
200
 * @method static void allIsMap($values, $message = '')
201
 * @method static void allIsNonEmptyMap($values, $message = '')
202
 * @method static void allUuid($values, $message = '')
203
 * @method static void allThrows($expressions, $class = 'Exception', $message = '')
204
 *
205
 * @since  1.0
206
 *
207
 * @author Bernhard Schussek <[email protected]>
208
 */
209
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...
210
{
211
    /**
212
     * @psalm-assert string $value
213 177
     *
214
     * @param mixed  $value
215 177
     * @param string $message
216 33
     *
217 33
     * @throws InvalidArgumentException
218 33
     */
219
    public static function string($value, $message = '')
220
    {
221 144
        if (!\is_string($value)) {
222
            static::reportInvalidArgument(\sprintf(
223
                $message ?: 'Expected a string. Got: %s',
224
                static::typeToString($value)
225
            ));
226
        }
227
    }
228
229 16
    /**
230
     * @param mixed  $value
231 16
     * @param string $message
232 12
     *
233 8
     * @throws InvalidArgumentException
234
     */
235
    public static function stringNotEmpty($value, $message = '')
236
    {
237
        static::string($value, $message);
238
        static::notEq($value, '', $message);
239
    }
240
241
    /**
242
     * @psalm-assert int $value
243 17
     *
244
     * @param mixed  $value
245 17
     * @param string $message
246 13
     *
247 13
     * @throws InvalidArgumentException
248 13
     */
249
    public static function integer($value, $message = '')
250
    {
251 4
        if (!\is_int($value)) {
252
            static::reportInvalidArgument(\sprintf(
253
                $message ?: 'Expected an integer. Got: %s',
254
                static::typeToString($value)
255
            ));
256
        }
257
    }
258
259
    /**
260
     * @psalm-assert numeric $value
261 16
     *
262
     * @param mixed  $value
263 16
     * @param string $message
264 4
     *
265 4
     * @throws InvalidArgumentException
266 4
     */
267
    public static function integerish($value, $message = '')
268
    {
269 12
        if (!\is_numeric($value) || $value != (int) $value) {
270
            static::reportInvalidArgument(\sprintf(
271
                $message ?: 'Expected an integerish value. Got: %s',
272
                static::typeToString($value)
273
            ));
274
        }
275
    }
276
277
    /**
278
     * @psalm-assert float $value
279 16
     *
280
     * @param mixed  $value
281 16
     * @param string $message
282 8
     *
283 8
     * @throws InvalidArgumentException
284 8
     */
285
    public static function float($value, $message = '')
286
    {
287 8
        if (!\is_float($value)) {
288
            static::reportInvalidArgument(\sprintf(
289
                $message ?: 'Expected a float. Got: %s',
290
                static::typeToString($value)
291
            ));
292
        }
293
    }
294
295
    /**
296
     * @psalm-assert numeric $value
297 20
     *
298
     * @param mixed  $value
299 20
     * @param string $message
300 4
     *
301 4
     * @throws InvalidArgumentException
302 4
     */
303
    public static function numeric($value, $message = '')
304
    {
305 16
        if (!\is_numeric($value)) {
306
            static::reportInvalidArgument(\sprintf(
307
                $message ?: 'Expected a numeric. Got: %s',
308
                static::typeToString($value)
309
            ));
310
        }
311
    }
312
313
    /**
314
     * @psalm-assert int $value
315 24
     *
316
     * @param mixed  $value
317 24
     * @param string $message
318 16
     *
319 16
     * @throws InvalidArgumentException
320 16
     */
321
    public static function natural($value, $message = '')
322
    {
323 8
        if (!\is_int($value) || $value < 0) {
324
            static::reportInvalidArgument(\sprintf(
325
                $message ?: 'Expected a non-negative integer. Got %s',
326
                static::valueToString($value)
327
            ));
328
        }
329
    }
330
331
    /**
332
     * @psalm-assert bool $value
333 16
     *
334
     * @param mixed  $value
335 16
     * @param string $message
336 8
     *
337 8
     * @throws InvalidArgumentException
338 8
     */
339
    public static function boolean($value, $message = '')
340
    {
341 8
        if (!\is_bool($value)) {
342
            static::reportInvalidArgument(\sprintf(
343
                $message ?: 'Expected a boolean. Got: %s',
344
                static::typeToString($value)
345
            ));
346
        }
347
    }
348
349
    /**
350
     * @psalm-assert scalar $value
351 23
     *
352
     * @param mixed  $value
353 23
     * @param string $message
354 11
     *
355 11
     * @throws InvalidArgumentException
356 11
     */
357
    public static function scalar($value, $message = '')
358
    {
359 12
        if (!\is_scalar($value)) {
360
            static::reportInvalidArgument(\sprintf(
361
                $message ?: 'Expected a scalar. Got: %s',
362
                static::typeToString($value)
363
            ));
364
        }
365
    }
366
367
    /**
368
     * @psalm-assert object $value
369 23
     *
370
     * @param mixed  $value
371 23
     * @param string $message
372 15
     *
373 15
     * @throws InvalidArgumentException
374 15
     */
375
    public static function object($value, $message = '')
376
    {
377 8
        if (!\is_object($value)) {
378
            static::reportInvalidArgument(\sprintf(
379
                $message ?: 'Expected an object. Got: %s',
380
                static::typeToString($value)
381
            ));
382
        }
383
    }
384
385
    /**
386
     * @psalm-assert resource $value
387
     *
388 16
     * @param mixed       $value
389
     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
390 16
     * @param string      $message
391 4
     *
392 4
     * @throws InvalidArgumentException
393 4
     */
394
    public static function resource($value, $type = null, $message = '')
395
    {
396
        if (!\is_resource($value)) {
397 12
            static::reportInvalidArgument(\sprintf(
398 4
                $message ?: 'Expected a resource. Got: %s',
399 4
                static::typeToString($value)
400 4
            ));
401 4
        }
402
403
        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...
404 8
            static::reportInvalidArgument(\sprintf(
405
                $message ?: 'Expected a resource of type %2$s. Got: %s',
406
                static::typeToString($value),
407
                $type
408
            ));
409
        }
410
    }
411
412
    /**
413
     * @psalm-assert callable $value
414 20
     *
415
     * @param mixed  $value
416 20
     * @param string $message
417 8
     *
418 8
     * @throws InvalidArgumentException
419 8
     */
420
    public static function isCallable($value, $message = '')
421
    {
422 12
        if (!\is_callable($value)) {
423
            static::reportInvalidArgument(\sprintf(
424
                $message ?: 'Expected a callable. Got: %s',
425
                static::typeToString($value)
426
            ));
427
        }
428
    }
429
430
    /**
431
     * @psalm-assert array $value
432 20
     *
433
     * @param mixed  $value
434 20
     * @param string $message
435 12
     *
436 12
     * @throws InvalidArgumentException
437 12
     */
438
    public static function isArray($value, $message = '')
439
    {
440 8
        if (!\is_array($value)) {
441
            static::reportInvalidArgument(\sprintf(
442
                $message ?: 'Expected an array. Got: %s',
443
                static::typeToString($value)
444
            ));
445
        }
446
    }
447
448
    /**
449
     * @psalm-assert iterable $value
450
     *
451
     * @deprecated use "isIterable" or "isInstanceOf" instead
452 20
     *
453
     * @param mixed  $value
454 20
     * @param string $message
455 20
     *
456 20
     * @throws InvalidArgumentException
457 20
     */
458
    public static function isTraversable($value, $message = '')
459 20
    {
460
        @\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...
461
            \sprintf(
462 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.',
463 8
                __METHOD__
464 8
            ),
465 8
            \E_USER_DEPRECATED
466
        );
467
468 12
        if (!\is_array($value) && !($value instanceof Traversable)) {
469
            static::reportInvalidArgument(\sprintf(
470
                $message ?: 'Expected a traversable. Got: %s',
471
                static::typeToString($value)
472
            ));
473
        }
474
    }
475
476 20
    /**
477
     * @param mixed  $value
478 20
     * @param string $message
479 8
     *
480 8
     * @throws InvalidArgumentException
481 8
     */
482 View Code Duplication
    public static function isArrayAccessible($value, $message = '')
483
    {
484 12
        if (!\is_array($value) && !($value instanceof ArrayAccess)) {
485
            static::reportInvalidArgument(\sprintf(
486
                $message ?: 'Expected an array accessible. Got: %s',
487
                static::typeToString($value)
488
            ));
489
        }
490
    }
491
492
    /**
493
     * @psalm-assert countable $value
494 28
     *
495
     * @param mixed  $value
496
     * @param string $message
497 28
     *
498 28
     * @throws InvalidArgumentException
499 28
     */
500 28
    public static function isCountable($value, $message = '')
501
    {
502 12
        if (
503 12
            !\is_array($value)
504 12
            && !($value instanceof Countable)
505
            && !($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...
506
            && !($value instanceof SimpleXMLElement)
507 16
        ) {
508
            static::reportInvalidArgument(\sprintf(
509
                $message ?: 'Expected a countable. Got: %s',
510
                static::typeToString($value)
511
            ));
512
        }
513
    }
514
515
    /**
516
     * @psalm-assert iterable $value
517 960
     *
518
     * @param mixed  $value
519 960
     * @param string $message
520 8
     *
521 8
     * @throws InvalidArgumentException
522 8
     */
523 View Code Duplication
    public static function isIterable($value, $message = '')
524
    {
525 956
        if (!\is_array($value) && !($value instanceof Traversable)) {
526
            static::reportInvalidArgument(\sprintf(
527
                $message ?: 'Expected an iterable. Got: %s',
528
                static::typeToString($value)
529
            ));
530
        }
531
    }
532
533
    /**
534
     * @psalm-template ExpectedType of object
535
     * @psalm-param class-string<ExpectedType> $class
536
     * @psalm-assert ExpectedType $value
537
     *
538 19
     * @param mixed         $value
539
     * @param string|object $class
540 19
     * @param string        $message
541 15
     *
542 15
     * @throws InvalidArgumentException
543 15
     */
544 15
    public static function isInstanceOf($value, $class, $message = '')
545
    {
546
        if (!($value instanceof $class)) {
547 4
            static::reportInvalidArgument(\sprintf(
548
                $message ?: 'Expected an instance of %2$s. Got: %s',
549
                static::typeToString($value),
550
                $class
551
            ));
552
        }
553
    }
554
555
    /**
556
     * @psalm-template ExpectedType of object
557
     * @psalm-param class-string<ExpectedType> $class
558
     * @psalm-assert !ExpectedType $value
559
     *
560 16
     * @param mixed         $value
561
     * @param string|object $class
562 16
     * @param string        $message
563 4
     *
564 4
     * @throws InvalidArgumentException
565 4
     */
566 4
    public static function notInstanceOf($value, $class, $message = '')
567
    {
568
        if ($value instanceof $class) {
569 12
            static::reportInvalidArgument(\sprintf(
570
                $message ?: 'Expected an instance other than %2$s. Got: %s',
571
                static::typeToString($value),
572
                $class
573
            ));
574
        }
575
    }
576
577
    /**
578 20
     * @param mixed                $value
579
     * @param array<object|string> $classes
580 20
     * @param string               $message
581 20
     *
582 8
     * @throws InvalidArgumentException
583
     */
584
    public static function isInstanceOfAny($value, array $classes, $message = '')
585
    {
586 12
        foreach ($classes as $class) {
587 12
            if ($value instanceof $class) {
588 12
                return;
589 12
            }
590
        }
591
592
        static::reportInvalidArgument(\sprintf(
593
            $message ?: 'Expected an instance of any of %2$s. Got: %s',
594
            static::typeToString($value),
595
            \implode(', ', \array_map(array('static', 'valueToString'), $classes))
596
        ));
597
    }
598
599 View Code Duplication
    public static function isAOf($value, $class, $message = '')
600
    {
601 23
        static::string($class, 'Expected class as a string. Got: %s');
602
603 23
        if (!is_a($value, $class, is_string($value))) {
604 8
            static::reportInvalidArgument(sprintf(
605 8
                $message ?: 'Expected an instance of this class or to this class among his parents %2$s. Got: %s',
606 8
                static::typeToString($value),
607
                $class
608
            ));
609 15
        }
610
    }
611
612 View Code Duplication
    public static function notAOf($value, $class, $message = '')
613
    {
614
        static::string($class, 'Expected class as a string. Got: %s');
615
616
        if (is_a($value, $class, is_string($value))) {
617
            static::reportInvalidArgument(sprintf(
618
                $message ?: 'Expected an instance of this class or to this class among his parents other than %2$s. Got: %s',
619 55
                static::typeToString($value),
620
                $class
621 55
            ));
622 23
        }
623 23
    }
624 23
625
    public static function isAOfAny($value, array $classes, $message = '')
626
    {
627 32
        foreach ($classes as $class) {
628
            static::string($class, 'Expected class as a string. Got: %s');
629
630
            if (is_a($value, $class, is_string($value))) {
631
                return;
632
            }
633
        }
634
635
        static::reportInvalidArgument(sprintf(
636
            $message ?: 'Expected an any of instance of this class or to this class among his parents other than %2$s. Got: %s',
637 11
            static::typeToString($value),
638
            \implode(', ', \array_map(array('static', 'valueToString'), $classes))
639 11
        ));
640 8
    }
641 8
642 8
    /**
643
     * @psalm-assert empty $value
644
     *
645 3
     * @param mixed  $value
646
     * @param string $message
647
     *
648
     * @throws InvalidArgumentException
649
     */
650
    public static function isEmpty($value, $message = '')
651
    {
652
        if (!empty($value)) {
653
            static::reportInvalidArgument(\sprintf(
654
                $message ?: 'Expected an empty value. Got: %s',
655 11
                static::valueToString($value)
656
            ));
657 11
        }
658 3
    }
659 3
660
    /**
661
     * @psalm-assert !empty $value
662 8
     *
663
     * @param mixed  $value
664
     * @param string $message
665
     *
666
     * @throws InvalidArgumentException
667
     */
668
    public static function notEmpty($value, $message = '')
669
    {
670
        if (empty($value)) {
671
            static::reportInvalidArgument(\sprintf(
672 15
                $message ?: 'Expected a non-empty value. Got: %s',
673
                static::valueToString($value)
674 15
            ));
675 11
        }
676 11
    }
677 11
678
    /**
679
     * @psalm-assert null $value
680 4
     *
681
     * @param mixed  $value
682
     * @param string $message
683
     *
684
     * @throws InvalidArgumentException
685
     */
686
    public static function null($value, $message = '')
687
    {
688
        if (null !== $value) {
689
            static::reportInvalidArgument(\sprintf(
690 19
                $message ?: 'Expected null. Got: %s',
691
                static::valueToString($value)
692 19
            ));
693 15
        }
694 15
    }
695 15
696
    /**
697
     * @psalm-assert !null $value
698 4
     *
699
     * @param mixed  $value
700
     * @param string $message
701
     *
702
     * @throws InvalidArgumentException
703
     */
704
    public static function notNull($value, $message = '')
705
    {
706
        if (null === $value) {
707
            static::reportInvalidArgument(
708 19
                $message ?: 'Expected a value other than null.'
709
            );
710 19
        }
711 4
    }
712 4
713
    /**
714
     * @psalm-assert true $value
715 15
     *
716
     * @param mixed  $value
717
     * @param string $message
718
     *
719
     * @throws InvalidArgumentException
720
     */
721
    public static function true($value, $message = '')
722
    {
723 51
        if (true !== $value) {
724
            static::reportInvalidArgument(\sprintf(
725 51
                $message ?: 'Expected a value to be true. Got: %s',
726 19
                static::valueToString($value)
727 19
            ));
728 19
        }
729
    }
730
731 32
    /**
732
     * @psalm-assert false $value
733
     *
734
     * @param mixed  $value
735
     * @param string $message
736
     *
737
     * @throws InvalidArgumentException
738
     */
739 51
    public static function false($value, $message = '')
740
    {
741 51
        if (false !== $value) {
742 35
            static::reportInvalidArgument(\sprintf(
743 35
                $message ?: 'Expected a value to be false. Got: %s',
744 35
                static::valueToString($value)
745
            ));
746
        }
747 16
    }
748
749
    /**
750
     * @psalm-assert !false $value
751
     *
752
     * @param mixed  $value
753
     * @param string $message
754
     *
755 51
     * @throws InvalidArgumentException
756
     */
757 51
    public static function notFalse($value, $message = '')
758 31
    {
759 31
        if (false === $value) {
760 31
            static::reportInvalidArgument(
761
                $message ?: 'Expected a value other than false.'
762
            );
763 20
        }
764
    }
765
766
    /**
767
     * @param mixed  $value
768
     * @param string $message
769
     *
770
     * @throws InvalidArgumentException
771 20
     */
772 View Code Duplication
    public static function ip($value, $message = '')
773 20
    {
774 12
        if (false === \filter_var($value, \FILTER_VALIDATE_IP)) {
775 12
            static::reportInvalidArgument(\sprintf(
776 12
                $message ?: 'Expected a value to be an IP. Got: %s',
777
                static::valueToString($value)
778
            ));
779 8
        }
780
    }
781
782
    /**
783
     * @param mixed  $value
784
     * @param string $message
785
     *
786
     * @throws InvalidArgumentException
787
     */
788 View Code Duplication
    public static function ipv4($value, $message = '')
789 12
    {
790
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
791 12
            static::reportInvalidArgument(\sprintf(
792 12
                $message ?: 'Expected a value to be an IPv4. Got: %s',
793
                static::valueToString($value)
794 12
            ));
795 8
        }
796
    }
797 8
798 8
    /**
799 8
     * @param mixed  $value
800 8
     * @param string $message
801
     *
802
     * @throws InvalidArgumentException
803 4
     */
804 View Code Duplication
    public static function ipv6($value, $message = '')
805
    {
806
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
807
            static::reportInvalidArgument(\sprintf(
808
                $message ?: 'Expected a value to be an IPv6. Got %s',
809
                static::valueToString($value)
810
            ));
811
        }
812 33
    }
813
814 33
    /**
815 17
     * @param mixed  $value
816 17
     * @param string $message
817 17
     *
818 17
     * @throws InvalidArgumentException
819
     */
820 View Code Duplication
    public static function email($value, $message = '')
821 16
    {
822
        if (false === \filter_var($value, FILTER_VALIDATE_EMAIL)) {
823
            static::reportInvalidArgument(\sprintf(
824
                $message ?: 'Expected a value to be a valid e-mail address. Got %s',
825
                static::valueToString($value)
826
            ));
827
        }
828
    }
829
830 28
    /**
831
     * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion.
832 28
     *
833 16
     * @param array  $values
834 16
     * @param string $message
835 16
     *
836
     * @throws InvalidArgumentException
837
     */
838 12
    public static function uniqueValues(array $values, $message = '')
839
    {
840
        $allValues = \count($values);
841
        $uniqueValues = \count(\array_unique($values));
842
843
        if ($allValues !== $uniqueValues) {
844
            $difference = $allValues - $uniqueValues;
845
846
            static::reportInvalidArgument(\sprintf(
847 16
                $message ?: 'Expected an array of unique values, but %s of them %s duplicated',
848
                $difference,
849 16
                (1 === $difference ? 'is' : 'are')
850 12
            ));
851 12
        }
852 12
    }
853 12
854
    /**
855
     * @param mixed  $value
856 4
     * @param mixed  $expect
857
     * @param string $message
858
     *
859
     * @throws InvalidArgumentException
860
     */
861
    public static function eq($value, $expect, $message = '')
862
    {
863
        if ($expect != $value) {
864
            static::reportInvalidArgument(\sprintf(
865 16
                $message ?: 'Expected a value equal to %2$s. Got: %s',
866
                static::valueToString($value),
867 16
                static::valueToString($expect)
868 4
            ));
869 4
        }
870 4
    }
871
872
    /**
873 12
     * @param mixed  $value
874
     * @param mixed  $expect
875
     * @param string $message
876
     *
877
     * @throws InvalidArgumentException
878
     */
879
    public static function notEq($value, $expect, $message = '')
880
    {
881
        if ($expect == $value) {
882 8
            static::reportInvalidArgument(\sprintf(
883
                $message ?: 'Expected a different value than %s.',
884 8
                static::valueToString($expect)
885 4
            ));
886 4
        }
887 4
    }
888 4
889
    /**
890
     * @param mixed  $value
891 4
     * @param mixed  $expect
892
     * @param string $message
893
     *
894
     * @throws InvalidArgumentException
895
     */
896
    public static function same($value, $expect, $message = '')
897
    {
898
        if ($expect !== $value) {
899
            static::reportInvalidArgument(\sprintf(
900 12
                $message ?: 'Expected a value identical to %2$s. Got: %s',
901
                static::valueToString($value),
902 12
                static::valueToString($expect)
903 4
            ));
904 4
        }
905 4
    }
906 4
907
    /**
908
     * @param mixed  $value
909 8
     * @param mixed  $expect
910
     * @param string $message
911
     *
912
     * @throws InvalidArgumentException
913
     */
914
    public static function notSame($value, $expect, $message = '')
915
    {
916
        if ($expect === $value) {
917
            static::reportInvalidArgument(\sprintf(
918 8
                $message ?: 'Expected a value not identical to %s.',
919
                static::valueToString($expect)
920 8
            ));
921 4
        }
922 4
    }
923 4
924 4
    /**
925
     * @param mixed  $value
926
     * @param mixed  $limit
927 4
     * @param string $message
928
     *
929
     * @throws InvalidArgumentException
930
     */
931
    public static function greaterThan($value, $limit, $message = '')
932
    {
933
        if ($value <= $limit) {
934
            static::reportInvalidArgument(\sprintf(
935
                $message ?: 'Expected a value greater than %2$s. Got: %s',
936 12
                static::valueToString($value),
937
                static::valueToString($limit)
938 12
            ));
939 4
        }
940 4
    }
941 4
942 4
    /**
943
     * @param mixed  $value
944
     * @param mixed  $limit
945 8
     * @param string $message
946
     *
947
     * @throws InvalidArgumentException
948
     */
949
    public static function greaterThanEq($value, $limit, $message = '')
950
    {
951
        if ($value < $limit) {
952
            static::reportInvalidArgument(\sprintf(
953
                $message ?: 'Expected a value greater than or equal to %2$s. Got: %s',
954
                static::valueToString($value),
955
                static::valueToString($limit)
956
            ));
957 16
        }
958
    }
959 16
960 8
    /**
961 8
     * @param mixed  $value
962 8
     * @param mixed  $limit
963 8
     * @param string $message
964 8
     *
965
     * @throws InvalidArgumentException
966
     */
967 8
    public static function lessThan($value, $limit, $message = '')
968
    {
969
        if ($value >= $limit) {
970
            static::reportInvalidArgument(\sprintf(
971
                $message ?: 'Expected a value less than %2$s. Got: %s',
972
                static::valueToString($value),
973
                static::valueToString($limit)
974
            ));
975
        }
976
    }
977
978 8
    /**
979
     * @param mixed  $value
980 8
     * @param mixed  $limit
981 4
     * @param string $message
982 4
     *
983 4
     * @throws InvalidArgumentException
984 4
     */
985
    public static function lessThanEq($value, $limit, $message = '')
986
    {
987 4
        if ($value > $limit) {
988
            static::reportInvalidArgument(\sprintf(
989
                $message ?: 'Expected a value less than or equal to %2$s. Got: %s',
990
                static::valueToString($value),
991
                static::valueToString($limit)
992
            ));
993
        }
994
    }
995
996 80
    /**
997
     * Inclusive range, so Assert::(3, 3, 5) passes.
998 80
     *
999 32
     * @param mixed  $value
1000 32
     * @param mixed  $min
1001 32
     * @param mixed  $max
1002 32
     * @param string $message
1003
     *
1004
     * @throws InvalidArgumentException
1005 48
     */
1006 View Code Duplication
    public static function range($value, $min, $max, $message = '')
1007
    {
1008
        if ($value < $min || $value > $max) {
1009
            static::reportInvalidArgument(\sprintf(
1010
                $message ?: 'Expected a value between %2$s and %3$s. Got: %s',
1011
                static::valueToString($value),
1012
                static::valueToString($min),
1013
                static::valueToString($max)
1014 80
            ));
1015
        }
1016 80
    }
1017 48
1018 48
    /**
1019 48
     * Does strict comparison, so Assert::oneOf(3, ['3']) does not pass the assertion.
1020 48
     *
1021
     * @param mixed  $value
1022
     * @param array  $values
1023 32
     * @param string $message
1024
     *
1025
     * @throws InvalidArgumentException
1026
     */
1027
    public static function oneOf($value, array $values, $message = '')
1028
    {
1029
        if (!\in_array($value, $values, true)) {
1030
            static::reportInvalidArgument(\sprintf(
1031 40
                $message ?: 'Expected one of: %2$s. Got: %s',
1032
                static::valueToString($value),
1033 40
                \implode(', ', \array_map(array('static', 'valueToString'), $values))
1034 24
            ));
1035 24
        }
1036 24
    }
1037
1038
    /**
1039 16
     * @param mixed  $value
1040
     * @param string $subString
1041
     * @param string $message
1042
     *
1043
     * @throws InvalidArgumentException
1044
     */
1045 View Code Duplication
    public static function contains($value, $subString, $message = '')
1046
    {
1047
        if (false === \strpos($value, $subString)) {
1048 48
            static::reportInvalidArgument(\sprintf(
1049
                $message ?: 'Expected a value to contain %2$s. Got: %s',
1050 48
                static::valueToString($value),
1051 32
                static::valueToString($subString)
1052 32
            ));
1053 32
        }
1054 32
    }
1055
1056
    /**
1057 16
     * @param mixed  $value
1058
     * @param string $subString
1059
     * @param string $message
1060
     *
1061
     * @throws InvalidArgumentException
1062
     */
1063 View Code Duplication
    public static function notContains($value, $subString, $message = '')
1064
    {
1065 35
        if (false !== \strpos($value, $subString)) {
1066
            static::reportInvalidArgument(\sprintf(
1067 35
                $message ?: '%2$s was not expected to be contained in a value. Got: %s',
1068
                static::valueToString($value),
1069 24
                static::valueToString($subString)
1070
            ));
1071 24
        }
1072 20
    }
1073 20
1074 20
    /**
1075 20
     * @param mixed  $value
1076
     * @param string $message
1077
     *
1078 24
     * @throws InvalidArgumentException
1079 12
     */
1080 12
    public static function notWhitespaceOnly($value, $message = '')
1081 12
    {
1082
        if (\preg_match('/^\s*$/', $value)) {
1083
            static::reportInvalidArgument(\sprintf(
1084 12
                $message ?: 'Expected a non-whitespace string. Got: %s',
1085
                static::valueToString($value)
1086
            ));
1087
        }
1088
    }
1089
1090
    /**
1091
     * @param mixed  $value
1092
     * @param string $prefix
1093 48
     * @param string $message
1094
     *
1095 48
     * @throws InvalidArgumentException
1096 32
     */
1097 32 View Code Duplication
    public static function startsWith($value, $prefix, $message = '')
1098 32
    {
1099 32
        if (0 !== \strpos($value, $prefix)) {
1100
            static::reportInvalidArgument(\sprintf(
1101
                $message ?: 'Expected a value to start with %2$s. Got: %s',
1102 16
                static::valueToString($value),
1103
                static::valueToString($prefix)
1104
            ));
1105
        }
1106
    }
1107
1108
    /**
1109
     * @param mixed  $value
1110
     * @param string $message
1111 12
     *
1112
     * @throws InvalidArgumentException
1113 12
     */
1114 8
    public static function startsWithLetter($value, $message = '')
1115 8
    {
1116 8
        static::string($value);
1117
1118
        $valid = isset($value[0]);
1119 4
1120
        if ($valid) {
1121
            $locale = \setlocale(LC_CTYPE, 0);
1122
            \setlocale(LC_CTYPE, 'C');
1123
            $valid = \ctype_alpha($value[0]);
1124
            \setlocale(LC_CTYPE, $locale);
1125
        }
1126
1127
        if (!$valid) {
1128 12
            static::reportInvalidArgument(\sprintf(
1129
                $message ?: 'Expected a value to start with a letter. Got: %s',
1130 12
                static::valueToString($value)
1131 4
            ));
1132 4
        }
1133 4
    }
1134 4
1135 4
    /**
1136
     * @param mixed  $value
1137
     * @param string $suffix
1138 8
     * @param string $message
1139
     *
1140
     * @throws InvalidArgumentException
1141
     */
1142 View Code Duplication
    public static function endsWith($value, $suffix, $message = '')
1143
    {
1144
        if ($suffix !== \substr($value, -\strlen($suffix))) {
1145
            static::reportInvalidArgument(\sprintf(
1146 28
                $message ?: 'Expected a value to end with %2$s. Got: %s',
1147
                static::valueToString($value),
1148 28
                static::valueToString($suffix)
1149
            ));
1150 28
        }
1151 16
    }
1152 16
1153 16
    /**
1154
     * @param mixed  $value
1155
     * @param mixed  $pattern
1156 12
     * @param string $message
1157
     *
1158
     * @throws InvalidArgumentException
1159
     */
1160
    public static function regex($value, $pattern, $message = '')
1161
    {
1162
        if (!\preg_match($pattern, $value)) {
1163
            static::reportInvalidArgument(\sprintf(
1164 20
                $message ?: 'The value %s does not match the expected pattern.',
1165
                static::valueToString($value)
1166 20
            ));
1167
        }
1168 12
    }
1169 12
1170 12
    /**
1171 12
     * @param mixed  $value
1172
     * @param mixed  $pattern
1173 12
     * @param string $message
1174 8
     *
1175 8
     * @throws InvalidArgumentException
1176 8
     */
1177
    public static function notRegex($value, $pattern, $message = '')
1178
    {
1179 4
        if (\preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) {
1180
            static::reportInvalidArgument(\sprintf(
1181
                $message ?: 'The value %s matches the pattern %s (at offset %d).',
1182
                static::valueToString($value),
1183
                static::valueToString($pattern),
1184
                $matches[0][1]
1185
            ));
1186
        }
1187 12
    }
1188
1189 12
    /**
1190 12
     * @param mixed  $value
1191 12
     * @param string $message
1192 12
     *
1193
     * @throws InvalidArgumentException
1194 12
     */
1195 8 View Code Duplication
    public static function unicodeLetters($value, $message = '')
1196 8
    {
1197 8
        static::string($value);
1198
1199
        if (!\preg_match('/^\p{L}+$/u', $value)) {
1200 4
            static::reportInvalidArgument(\sprintf(
1201
                $message ?: 'Expected a value to contain only Unicode letters. Got: %s',
1202
                static::valueToString($value)
1203
            ));
1204
        }
1205
    }
1206
1207
    /**
1208 12
     * @param mixed  $value
1209
     * @param string $message
1210 12
     *
1211 12
     * @throws InvalidArgumentException
1212 12
     */
1213 12 View Code Duplication
    public static function alpha($value, $message = '')
1214
    {
1215 12
        static::string($value);
1216 8
1217 8
        $locale = \setlocale(LC_CTYPE, 0);
1218 8
        \setlocale(LC_CTYPE, 'C');
1219
        $valid = !\ctype_alpha($value);
1220
        \setlocale(LC_CTYPE, $locale);
1221 4
1222
        if ($valid) {
1223
            static::reportInvalidArgument(\sprintf(
1224
                $message ?: 'Expected a value to contain only letters. Got: %s',
1225
                static::valueToString($value)
1226
            ));
1227
        }
1228
    }
1229 16
1230
    /**
1231 16
     * @param mixed  $value
1232 16
     * @param string $message
1233 16
     *
1234 16
     * @throws InvalidArgumentException
1235
     */
1236 16 View Code Duplication
    public static function digits($value, $message = '')
1237 12
    {
1238 12
        $locale = \setlocale(LC_CTYPE, 0);
1239 12
        \setlocale(LC_CTYPE, 'C');
1240
        $valid = !\ctype_digit($value);
1241
        \setlocale(LC_CTYPE, $locale);
1242 4
1243
        if ($valid) {
1244
            static::reportInvalidArgument(\sprintf(
1245
                $message ?: 'Expected a value to contain digits only. Got: %s',
1246
                static::valueToString($value)
1247
            ));
1248
        }
1249
    }
1250 16
1251
    /**
1252 16
     * @param mixed  $value
1253 16
     * @param string $message
1254 16
     *
1255 16
     * @throws InvalidArgumentException
1256
     */
1257 16 View Code Duplication
    public static function alnum($value, $message = '')
1258 12
    {
1259 12
        $locale = \setlocale(LC_CTYPE, 0);
1260 12
        \setlocale(LC_CTYPE, 'C');
1261
        $valid = !\ctype_alnum($value);
1262
        \setlocale(LC_CTYPE, $locale);
1263 4
1264
        if ($valid) {
1265
            static::reportInvalidArgument(\sprintf(
1266
                $message ?: 'Expected a value to contain letters and digits only. Got: %s',
1267
                static::valueToString($value)
1268
            ));
1269
        }
1270
    }
1271
1272 36
    /**
1273
     * @param mixed  $value
1274 36
     * @param string $message
1275 24
     *
1276 24
     * @throws InvalidArgumentException
1277 24
     */
1278 24 View Code Duplication
    public static function lower($value, $message = '')
1279
    {
1280
        $locale = \setlocale(LC_CTYPE, 0);
1281 12
        \setlocale(LC_CTYPE, 'C');
1282
        $valid = !\ctype_lower($value);
1283
        \setlocale(LC_CTYPE, $locale);
1284
1285
        if ($valid) {
1286
            static::reportInvalidArgument(\sprintf(
1287
                $message ?: 'Expected a value to contain lowercase characters only. Got: %s',
1288
                static::valueToString($value)
1289
            ));
1290
        }
1291
    }
1292 36
1293
    /**
1294 36
     * @param mixed  $value
1295 12
     * @param string $message
1296 12
     *
1297 12
     * @throws InvalidArgumentException
1298 12
     */
1299 View Code Duplication
    public static function upper($value, $message = '')
1300
    {
1301 24
        $locale = \setlocale(LC_CTYPE, 0);
1302
        \setlocale(LC_CTYPE, 'C');
1303
        $valid = !\ctype_upper($value);
1304
        \setlocale(LC_CTYPE, $locale);
1305
1306
        if ($valid) {
1307
            static::reportInvalidArgument(\sprintf(
1308
                $message ?: 'Expected a value to contain uppercase characters only. Got: %s',
1309
                static::valueToString($value)
1310
            ));
1311
        }
1312 36
    }
1313
1314 36
    /**
1315 12
     * @param mixed  $value
1316 12
     * @param mixed  $length
1317 12
     * @param string $message
1318 12
     *
1319
     * @throws InvalidArgumentException
1320
     */
1321 24
    public static function length($value, $length, $message = '')
1322
    {
1323
        if ($length !== static::strlen($value)) {
1324
            static::reportInvalidArgument(\sprintf(
1325
                $message ?: 'Expected a value to contain %2$s characters. Got: %s',
1326
                static::valueToString($value),
1327
                $length
1328
            ));
1329
        }
1330
    }
1331
1332
    /**
1333 60
     * Inclusive min.
1334
     *
1335 60
     * @param mixed  $value
1336
     * @param mixed  $min
1337 60
     * @param string $message
1338 24
     *
1339 24
     * @throws InvalidArgumentException
1340 24
     */
1341 24
    public static function minLength($value, $min, $message = '')
1342 24
    {
1343
        if (static::strlen($value) < $min) {
1344
            static::reportInvalidArgument(\sprintf(
1345 36
                $message ?: 'Expected a value to contain at least %2$s characters. Got: %s',
1346
                static::valueToString($value),
1347
                $min
1348
            ));
1349
        }
1350
    }
1351
1352
    /**
1353
     * Inclusive max.
1354
     *
1355 36
     * @param mixed  $value
1356
     * @param mixed  $max
1357 36
     * @param string $message
1358
     *
1359 36
     * @throws InvalidArgumentException
1360 12
     */
1361 12
    public static function maxLength($value, $max, $message = '')
1362 12
    {
1363
        if (static::strlen($value) > $max) {
1364
            static::reportInvalidArgument(\sprintf(
1365 24
                $message ?: 'Expected a value to contain at most %2$s characters. Got: %s',
1366
                static::valueToString($value),
1367
                $max
1368
            ));
1369
        }
1370
    }
1371
1372
    /**
1373 12
     * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion.
1374
     *
1375 12
     * @param mixed  $value
1376
     * @param mixed  $min
1377 8
     * @param mixed  $max
1378 4
     * @param string $message
1379 4
     *
1380 4
     * @throws InvalidArgumentException
1381
     */
1382 View Code Duplication
    public static function lengthBetween($value, $min, $max, $message = '')
1383 4
    {
1384
        $length = static::strlen($value);
1385
1386
        if ($length < $min || $length > $max) {
1387
            static::reportInvalidArgument(\sprintf(
1388
                $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s',
1389
                static::valueToString($value),
1390
                $min,
1391 12
                $max
1392
            ));
1393 12
        }
1394
    }
1395 8
1396 4
    /**
1397 4
     * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file.
1398 4
     *
1399
     * @param mixed  $value
1400
     * @param string $message
1401 4
     *
1402
     * @throws InvalidArgumentException
1403
     */
1404 View Code Duplication
    public static function fileExists($value, $message = '')
1405
    {
1406
        static::string($value);
1407
1408
        if (!\file_exists($value)) {
1409
            static::reportInvalidArgument(\sprintf(
1410
                $message ?: 'The file %s does not exist.',
1411
                static::valueToString($value)
1412
            ));
1413
        }
1414
    }
1415
1416
    /**
1417
     * @param mixed  $value
1418
     * @param string $message
1419
     *
1420
     * @throws InvalidArgumentException
1421
     */
1422 View Code Duplication
    public static function file($value, $message = '')
1423
    {
1424
        static::fileExists($value, $message);
1425
1426
        if (!\is_file($value)) {
1427
            static::reportInvalidArgument(\sprintf(
1428
                $message ?: 'The path %s is not a file.',
1429
                static::valueToString($value)
1430
            ));
1431
        }
1432
    }
1433
1434
    /**
1435
     * @param mixed  $value
1436
     * @param string $message
1437
     *
1438
     * @throws InvalidArgumentException
1439
     */
1440 View Code Duplication
    public static function directory($value, $message = '')
1441
    {
1442
        static::fileExists($value, $message);
1443 8
1444
        if (!\is_dir($value)) {
1445 8
            static::reportInvalidArgument(\sprintf(
1446 4
                $message ?: 'The path %s is no directory.',
1447 4
                static::valueToString($value)
1448 4
            ));
1449
        }
1450
    }
1451 4
1452
    /**
1453
     * @param mixed  $value
1454
     * @param string $message
1455
     *
1456
     * @throws InvalidArgumentException
1457
     */
1458
    public static function readable($value, $message = '')
1459
    {
1460 8
        if (!\is_readable($value)) {
1461
            static::reportInvalidArgument(\sprintf(
1462 8
                $message ?: 'The path %s is not readable.',
1463 4
                static::valueToString($value)
1464 4
            ));
1465 4
        }
1466 4
    }
1467
1468
    /**
1469 4
     * @param mixed  $value
1470
     * @param string $message
1471
     *
1472
     * @throws InvalidArgumentException
1473
     */
1474
    public static function writable($value, $message = '')
1475
    {
1476
        if (!\is_writable($value)) {
1477
            static::reportInvalidArgument(\sprintf(
1478
                $message ?: 'The path %s is not writable.',
1479 8
                static::valueToString($value)
1480
            ));
1481 8
        }
1482 4
    }
1483 4
1484 4
    /**
1485
     * @psalm-assert class-string $value
1486
     *
1487 4
     * @param mixed  $value
1488
     * @param string $message
1489
     *
1490
     * @throws InvalidArgumentException
1491
     */
1492
    public static function classExists($value, $message = '')
1493
    {
1494
        if (!\class_exists($value)) {
1495
            static::reportInvalidArgument(\sprintf(
1496 8
                $message ?: 'Expected an existing class name. Got: %s',
1497
                static::valueToString($value)
1498 8
            ));
1499 4
        }
1500 4
    }
1501 4
1502 4
    /**
1503
     * @param mixed         $value
1504
     * @param string|object $class
1505 4
     * @param string        $message
1506
     *
1507
     * @throws InvalidArgumentException
1508
     */
1509
    public static function subclassOf($value, $class, $message = '')
1510
    {
1511
        if (!\is_subclass_of($value, $class)) {
1512
            static::reportInvalidArgument(\sprintf(
1513
                $message ?: 'Expected a sub-class of %2$s. Got: %s',
1514 12
                static::valueToString($value),
1515
                static::valueToString($class)
1516 12
            ));
1517 4
        }
1518 4
    }
1519 4
1520
    /**
1521
     * @psalm-assert class-string $value
1522 8
     *
1523
     * @param mixed  $value
1524
     * @param string $message
1525
     *
1526
     * @throws InvalidArgumentException
1527
     */
1528
    public static function interfaceExists($value, $message = '')
1529
    {
1530
        if (!\interface_exists($value)) {
1531 12
            static::reportInvalidArgument(\sprintf(
1532
                $message ?: 'Expected an existing interface name. got %s',
1533 12
                static::valueToString($value)
1534 8
            ));
1535 8
        }
1536 8
    }
1537
1538
    /**
1539 4
     * @param mixed  $value
1540
     * @param mixed  $interface
1541
     * @param string $message
1542
     *
1543
     * @throws InvalidArgumentException
1544
     */
1545 View Code Duplication
    public static function implementsInterface($value, $interface, $message = '')
1546
    {
1547
        if (!\in_array($interface, \class_implements($value))) {
1548 27
            static::reportInvalidArgument(\sprintf(
1549
                $message ?: 'Expected an implementation of %2$s. Got: %s',
1550 27
                static::valueToString($value),
1551 19
                static::valueToString($interface)
1552 19
            ));
1553 19
        }
1554
    }
1555
1556 8
    /**
1557
     * @param string|object $classOrObject
1558
     * @param mixed         $property
1559
     * @param string        $message
1560
     *
1561
     * @throws InvalidArgumentException
1562
     */
1563 View Code Duplication
    public static function propertyExists($classOrObject, $property, $message = '')
1564
    {
1565 27
        if (!\property_exists($classOrObject, $property)) {
1566
            static::reportInvalidArgument(\sprintf(
1567 27
                $message ?: 'Expected the property %s to exist.',
1568 8
                static::valueToString($property)
1569 8
            ));
1570 8
        }
1571
    }
1572
1573 19
    /**
1574
     * @param string|object $classOrObject
1575
     * @param mixed         $property
1576
     * @param string        $message
1577
     *
1578
     * @throws InvalidArgumentException
1579
     */
1580 View Code Duplication
    public static function propertyNotExists($classOrObject, $property, $message = '')
1581
    {
1582 12
        if (\property_exists($classOrObject, $property)) {
1583
            static::reportInvalidArgument(\sprintf(
1584 12
                $message ?: 'Expected the property %s to not exist.',
1585 4
                static::valueToString($property)
1586 4
            ));
1587 4
        }
1588
    }
1589
1590 8
    /**
1591
     * @param string|object $classOrObject
1592
     * @param mixed         $method
1593
     * @param string        $message
1594
     *
1595
     * @throws InvalidArgumentException
1596
     */
1597 View Code Duplication
    public static function methodExists($classOrObject, $method, $message = '')
1598
    {
1599 12
        if (!\method_exists($classOrObject, $method)) {
1600
            static::reportInvalidArgument(\sprintf(
1601 12
                $message ?: 'Expected the method %s to exist.',
1602 8
                static::valueToString($method)
1603 8
            ));
1604 8
        }
1605
    }
1606
1607 4
    /**
1608
     * @param string|object $classOrObject
1609
     * @param mixed         $method
1610
     * @param string        $message
1611
     *
1612
     * @throws InvalidArgumentException
1613
     */
1614 View Code Duplication
    public static function methodNotExists($classOrObject, $method, $message = '')
1615
    {
1616
        if (\method_exists($classOrObject, $method)) {
1617
            static::reportInvalidArgument(\sprintf(
1618
                $message ?: 'Expected the method %s to not exist.',
1619 28
                static::valueToString($method)
1620
            ));
1621 28
        }
1622 20
    }
1623 20
1624 20
    /**
1625
     * @param array      $array
1626
     * @param string|int $key
1627 8
     * @param string     $message
1628
     *
1629
     * @throws InvalidArgumentException
1630
     */
1631 View Code Duplication
    public static function keyExists($array, $key, $message = '')
1632
    {
1633
        if (!(isset($array[$key]) || \array_key_exists($key, $array))) {
1634
            static::reportInvalidArgument(\sprintf(
1635
                $message ?: 'Expected the key %s to exist.',
1636
                static::valueToString($key)
1637
            ));
1638 8
        }
1639
    }
1640 8
1641 8
    /**
1642
     * @param array      $array
1643 8
     * @param string|int $key
1644
     * @param string     $message
1645 4
     *
1646
     * @throws InvalidArgumentException
1647
     */
1648 View Code Duplication
    public static function keyNotExists($array, $key, $message = '')
1649
    {
1650
        if (isset($array[$key]) || \array_key_exists($key, $array)) {
1651
            static::reportInvalidArgument(\sprintf(
1652
                $message ?: 'Expected the key %s to not exist.',
1653
                static::valueToString($key)
1654
            ));
1655
        }
1656 12
    }
1657
1658 12
    /**
1659 4
     * Checks if a value is a valid array key (int or string).
1660 4
     *
1661 4
     * @psalm-assert array-key $value
1662 4
     *
1663
     * @param mixed  $value
1664
     * @param string $message
1665 8
     *
1666
     * @throws InvalidArgumentException
1667
     */
1668
    public static function validArrayKey($value, $message = '')
1669
    {
1670
        if (!(\is_int($value) || \is_string($value))) {
1671
            static::reportInvalidArgument(\sprintf(
1672
                $message ?: 'Expected string or integer. Got: %s',
1673
                static::typeToString($value)
1674
            ));
1675
        }
1676 12
    }
1677
1678 12
    /**
1679 4
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1680 4
     *
1681 4
     * @param mixed  $array
1682 4
     * @param mixed  $number
1683
     * @param string $message
1684
     *
1685 8
     * @throws InvalidArgumentException
1686
     */
1687
    public static function count($array, $number, $message = '')
1688
    {
1689
        static::eq(
1690
            \count($array),
1691
            $number,
1692
            $message ?: \sprintf('Expected an array to contain %d elements. Got: %d.', $number, \count($array))
1693
        );
1694
    }
1695
1696
    /**
1697 20
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1698
     *
1699 20
     * @param mixed  $array
1700
     * @param mixed  $min
1701 20
     * @param string $message
1702 8
     *
1703 8
     * @throws InvalidArgumentException
1704 8
     */
1705 8 View Code Duplication
    public static function minCount($array, $min, $message = '')
1706 8
    {
1707
        if (\count($array) < $min) {
1708
            static::reportInvalidArgument(\sprintf(
1709 12
                $message ?: 'Expected an array to contain at least %2$d elements. Got: %d',
1710
                \count($array),
1711
                $min
1712
            ));
1713
        }
1714
    }
1715
1716
    /**
1717
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1718
     *
1719 80
     * @param mixed  $array
1720
     * @param mixed  $max
1721 80
     * @param string $message
1722 32
     *
1723 32
     * @throws InvalidArgumentException
1724
     */
1725 View Code Duplication
    public static function maxCount($array, $max, $message = '')
1726 48
    {
1727
        if (\count($array) > $max) {
1728
            static::reportInvalidArgument(\sprintf(
1729
                $message ?: 'Expected an array to contain at most %2$d elements. Got: %d',
1730
                \count($array),
1731
                $max
1732
            ));
1733
        }
1734
    }
1735
1736 40
    /**
1737
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1738 40
     *
1739 24
     * @param mixed  $array
1740 20
     * @param mixed  $min
1741
     * @param mixed  $max
1742
     * @param string $message
1743
     *
1744
     * @throws InvalidArgumentException
1745
     */
1746
    public static function countBetween($array, $min, $max, $message = '')
1747
    {
1748 32
        $count = \count($array);
1749
1750
        if ($count < $min || $count > $max) {
1751 32
            static::reportInvalidArgument(\sprintf(
1752 32
                $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d',
1753
                $count,
1754 16
                $min,
1755 16
                $max
1756
            ));
1757
        }
1758 16
    }
1759
1760
    /**
1761
     * @psalm-assert list $array
1762
     *
1763
     * @param mixed  $array
1764
     * @param string $message
1765
     *
1766 16
     * @throws InvalidArgumentException
1767
     */
1768 16 View Code Duplication
    public static function isList($array, $message = '')
1769 8
    {
1770 4
        if (!\is_array($array) || $array !== \array_values($array)) {
1771
            static::reportInvalidArgument(
1772
                $message ?: 'Expected list - non-associative array.'
1773
            );
1774
        }
1775
    }
1776
1777
    /**
1778 56
     * @psalm-assert non-empty-list $array
1779
     *
1780 56
     * @param mixed  $array
1781
     * @param string $message
1782
     *
1783
     * @throws InvalidArgumentException
1784 56
     */
1785 4
    public static function isNonEmptyList($array, $message = '')
1786
    {
1787
        static::isList($array, $message);
1788 52
        static::notEmpty($array, $message);
1789 20
    }
1790 20
1791 20
    /**
1792
     * @param mixed  $array
1793
     * @param string $message
1794 32
     *
1795
     * @throws InvalidArgumentException
1796
     */
1797
    public static function isMap($array, $message = '')
1798
    {
1799
        if (
1800
            !\is_array($array) ||
1801
            \array_keys($array) !== \array_filter(\array_keys($array), '\is_string')
1802
        ) {
1803 24
            static::reportInvalidArgument(
1804
                $message ?: 'Expected map - associative array with string keys.'
1805 24
            );
1806
        }
1807 24
    }
1808
1809
    /**
1810 24
     * @param mixed  $array
1811 24
     * @param string $message
1812 20
     *
1813 20
     * @throws InvalidArgumentException
1814 20
     */
1815
    public static function isNonEmptyMap($array, $message = '')
1816 4
    {
1817 4
        static::isMap($array, $message);
1818 4
        static::notEmpty($array, $message);
1819 4
    }
1820
1821
    /**
1822
     * @param mixed  $value
1823 8
     * @param string $message
1824 8
     *
1825 8
     * @throws InvalidArgumentException
1826 8
     */
1827
    public static function uuid($value, $message = '')
1828
    {
1829
        $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
1830
1831
        // The nil UUID is special form of UUID that is specified to have all
1832
        // 128 bits set to zero.
1833 1510
        if ('00000000-0000-0000-0000-000000000000' === $value) {
1834
            return;
1835 1510
        }
1836 559
1837 459
        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)) {
1838 459
            static::reportInvalidArgument(\sprintf(
1839
                $message ?: 'Value %s is not a valid UUID.',
1840
                static::valueToString($value)
1841 325
            ));
1842
        }
1843
    }
1844 951
1845 950
    /**
1846
     * @param Closure       $expression
1847 950
     * @param string|object $class
1848 950
     * @param string        $message
1849
     *
1850 950
     * @throws InvalidArgumentException
1851 950
     */
1852
    public static function throws(Closure $expression, $class = 'Exception', $message = '')
1853 950
    {
1854
        static::string($class);
1855
1856 458
        $actual = 'none';
1857
1858
        try {
1859 1
            $expression();
1860
        } catch (Exception $e) {
1861
            $actual = \get_class($e);
1862
            if ($e instanceof $class) {
1863
                return;
1864
            }
1865
        } 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...
1866
            $actual = \get_class($e);
1867 702
            if ($e instanceof $class) {
1868
                return;
1869 702
            }
1870 20
        }
1871
1872
        static::reportInvalidArgument($message ?: \sprintf(
1873 684
            'Expected to throw "%s", got "%s"',
1874 15
            $class,
1875
            $actual
1876
        ));
1877 674
    }
1878 25
1879
    /**
1880
     * @throws BadMethodCallException
1881 649
     */
1882 21
    public static function __callStatic($name, $arguments)
1883
    {
1884
        if ('nullOr' === \substr($name, 0, 6)) {
1885 628
            if (null !== $arguments[0]) {
1886 2
                $method = \lcfirst(\substr($name, 6));
1887 1
                \call_user_func_array(array('static', $method), $arguments);
1888
            }
1889
1890 1
            return;
1891
        }
1892
1893 627
        if ('all' === \substr($name, 0, 3)) {
1894 1
            static::isIterable($arguments[0]);
1895
1896
            $method = \lcfirst(\substr($name, 3));
1897 627
            $args = $arguments;
1898 525
1899
            foreach ($arguments[0] as $entry) {
1900
                $args[0] = $entry;
1901 110
1902
                \call_user_func_array(array('static', $method), $args);
1903
            }
1904
1905
            return;
1906
        }
1907
1908
        throw new BadMethodCallException('No such method: '.$name);
1909 211
    }
1910
1911 211
    /**
1912
     * @param mixed $value
1913
     *
1914 168
     * @return string
1915
     */
1916 168
    protected static function valueToString($value)
1917
    {
1918
        if (null === $value) {
1919
            return 'null';
1920 168
        }
1921
1922
        if (true === $value) {
1923
            return 'true';
1924 168
        }
1925
1926
        if (false === $value) {
1927
            return 'false';
1928
        }
1929
1930
        if (\is_array($value)) {
1931
            return 'array';
1932 988
        }
1933
1934 988
        if (\is_object($value)) {
1935
            if (\method_exists($value, '__toString')) {
1936
                return \get_class($value).': '.self::valueToString($value->__toString());
1937
            }
1938
1939
            return \get_class($value);
1940
        }
1941
1942
        if (\is_resource($value)) {
1943
            return 'resource';
1944
        }
1945
1946
        if (\is_string($value)) {
1947
            return '"'.$value.'"';
1948
        }
1949
1950
        return (string) $value;
1951
    }
1952
1953
    /**
1954
     * @param mixed $value
1955
     *
1956
     * @return string
1957
     */
1958
    protected static function typeToString($value)
1959
    {
1960
        return \is_object($value) ? \get_class($value) : \gettype($value);
1961
    }
1962
1963
    protected static function strlen($value)
1964
    {
1965
        if (!\function_exists('mb_detect_encoding')) {
1966
            return \strlen($value);
1967
        }
1968
1969
        if (false === $encoding = \mb_detect_encoding($value)) {
1970
            return \strlen($value);
1971
        }
1972
1973
        return \mb_strlen($value, $encoding);
1974
    }
1975
1976
    /**
1977
     * @param string $message
1978
     *
1979
     * @throws InvalidArgumentException
1980
     */
1981
    protected static function reportInvalidArgument($message)
1982
    {
1983
        throw new InvalidArgumentException($message);
1984
    }
1985
1986
    private function __construct()
1987
    {
1988
    }
1989
}
1990