Failed Conditions
Pull Request — master (#141)
by
unknown
16:24
created

src/Assert.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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