Failed Conditions
Pull Request — master (#214)
by Marco
02:50
created

Assert::numeric()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.9666
c 0
b 0
f 0
cc 3
nc 2
nop 2
crap 3
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 DateTime;
19
use DateTimeImmutable;
20
use Exception;
21
use InvalidArgumentException;
22
use ResourceBundle;
23
use SimpleXMLElement;
24
use Throwable;
25
use Traversable;
26
27
/**
28
 * Efficient assertions to validate the input/output of your methods.
29
 *
30
 * @mixin Mixin
31
 *
32
 * @since  1.0
33
 *
34
 * @author Bernhard Schussek <[email protected]>
35
 */
36
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...
37
{
38
    /**
39
     * @psalm-pure
40
     * @psalm-assert string $value
41
     *
42
     * @param mixed  $value
43
     * @param string $message
44
     *
45
     * @throws InvalidArgumentException
46
     */
47 241
    public static function string($value, $message = '')
48
    {
49 241
        if (!\is_string($value)) {
50 45
            static::reportInvalidArgument(\sprintf(
51 45
                $message ?: 'Expected a string. Got: %s',
52 45
                static::typeToString($value)
53
            ));
54
        }
55 196
    }
56
57
    /**
58
     * @psalm-pure
59
     * @psalm-assert non-empty-string $value
60
     *
61
     * @param mixed  $value
62
     * @param string $message
63
     *
64
     * @throws InvalidArgumentException
65
     */
66 16
    public static function stringNotEmpty($value, $message = '')
67
    {
68 16
        static::string($value, $message);
69 12
        static::notEq($value, '', $message);
70 8
    }
71
72
    /**
73
     * @psalm-pure
74
     * @psalm-assert int $value
75
     *
76
     * @param mixed  $value
77
     * @param string $message
78
     *
79
     * @throws InvalidArgumentException
80
     */
81 17
    public static function integer($value, $message = '')
82
    {
83 17
        if (!\is_int($value)) {
84 13
            static::reportInvalidArgument(\sprintf(
85 13
                $message ?: 'Expected an integer. Got: %s',
86 13
                static::typeToString($value)
87
            ));
88
        }
89 4
    }
90
91
    /**
92
     * @psalm-pure
93
     * @psalm-assert numeric $value
94
     *
95
     * @param mixed  $value
96
     * @param string $message
97
     *
98
     * @throws InvalidArgumentException
99
     */
100 16
    public static function integerish($value, $message = '')
101
    {
102 16
        if (!\is_numeric($value) || $value != (int) $value) {
103 4
            static::reportInvalidArgument(\sprintf(
104 4
                $message ?: 'Expected an integerish value. Got: %s',
105 4
                static::typeToString($value)
106
            ));
107
        }
108 12
    }
109
110
    /**
111
     * @psalm-pure
112
     * @psalm-assert positive-int $value
113
     *
114
     * @param mixed  $value
115
     * @param string $message
116
     *
117
     * @throws InvalidArgumentException
118
     */
119 40
    public static function positiveInteger($value, $message = '')
120
    {
121 40
        if (! (\is_int($value) && $value > 0)) {
122 32
            static::reportInvalidArgument(\sprintf(
123 32
                $message ?: 'Expected a positive integer. Got: %s',
124 32
                static::valueToString($value)
125
            ));
126
        }
127 8
    }
128
129
    /**
130
     * @psalm-pure
131
     * @psalm-assert float $value
132
     *
133
     * @param mixed  $value
134
     * @param string $message
135
     *
136
     * @throws InvalidArgumentException
137
     */
138 16
    public static function float($value, $message = '')
139
    {
140 16
        if (!\is_float($value)) {
141 8
            static::reportInvalidArgument(\sprintf(
142 8
                $message ?: 'Expected a float. Got: %s',
143 8
                static::typeToString($value)
144
            ));
145
        }
146 8
    }
147
148
    /**
149
     * @psalm-pure
150
     * @psalm-assert numeric $value
151
     *
152
     * @param mixed  $value
153
     * @param string $message
154
     *
155
     * @throws InvalidArgumentException
156
     */
157 20
    public static function numeric($value, $message = '')
158
    {
159 20
        if (!\is_numeric($value)) {
160 4
            static::reportInvalidArgument(\sprintf(
161 4
                $message ?: 'Expected a numeric. Got: %s',
162 4
                static::typeToString($value)
163
            ));
164
        }
165 16
    }
166
167
    /**
168
     * @psalm-pure
169
     * @psalm-assert int $value
170
     *
171
     * @param mixed  $value
172
     * @param string $message
173
     *
174
     * @throws InvalidArgumentException
175
     */
176 24
    public static function natural($value, $message = '')
177
    {
178 24
        if (!\is_int($value) || $value < 0) {
179 16
            static::reportInvalidArgument(\sprintf(
180 16
                $message ?: 'Expected a non-negative integer. Got: %s',
181 16
                static::valueToString($value)
182
            ));
183
        }
184 8
    }
185
186
    /**
187
     * @psalm-pure
188
     * @psalm-assert bool $value
189
     *
190
     * @param mixed  $value
191
     * @param string $message
192
     *
193
     * @throws InvalidArgumentException
194
     */
195 16
    public static function boolean($value, $message = '')
196
    {
197 16
        if (!\is_bool($value)) {
198 8
            static::reportInvalidArgument(\sprintf(
199 8
                $message ?: 'Expected a boolean. Got: %s',
200 8
                static::typeToString($value)
201
            ));
202
        }
203 8
    }
204
205
    /**
206
     * @psalm-pure
207
     * @psalm-assert scalar $value
208
     *
209
     * @param mixed  $value
210
     * @param string $message
211
     *
212
     * @throws InvalidArgumentException
213
     */
214 23
    public static function scalar($value, $message = '')
215
    {
216 23
        if (!\is_scalar($value)) {
217 11
            static::reportInvalidArgument(\sprintf(
218 11
                $message ?: 'Expected a scalar. Got: %s',
219 11
                static::typeToString($value)
220
            ));
221
        }
222 12
    }
223
224
    /**
225
     * @psalm-pure
226
     * @psalm-assert object $value
227
     *
228
     * @param mixed  $value
229
     * @param string $message
230
     *
231
     * @throws InvalidArgumentException
232
     */
233 23
    public static function object($value, $message = '')
234
    {
235 23
        if (!\is_object($value)) {
236 15
            static::reportInvalidArgument(\sprintf(
237 15
                $message ?: 'Expected an object. Got: %s',
238 15
                static::typeToString($value)
239
            ));
240
        }
241 8
    }
242
243
    /**
244
     * @psalm-pure
245
     * @psalm-assert resource $value
246
     *
247
     * @param mixed       $value
248
     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
249
     * @param string      $message
250
     *
251
     * @throws InvalidArgumentException
252
     */
253 16
    public static function resource($value, $type = null, $message = '')
254
    {
255 16
        if (!\is_resource($value)) {
256 4
            static::reportInvalidArgument(\sprintf(
257 4
                $message ?: 'Expected a resource. Got: %s',
258 4
                static::typeToString($value)
259
            ));
260
        }
261
262 12
        if ($type && $type !== \get_resource_type($value)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $type of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

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

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

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

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
263 4
            static::reportInvalidArgument(\sprintf(
264 4
                $message ?: 'Expected a resource of type %2$s. Got: %s',
265 4
                static::typeToString($value),
266 4
                $type
267
            ));
268
        }
269 8
    }
270
271
    /**
272
     * @psalm-pure
273
     * @psalm-assert callable $value
274
     *
275
     * @param mixed  $value
276
     * @param string $message
277
     *
278
     * @throws InvalidArgumentException
279
     */
280 20
    public static function isCallable($value, $message = '')
281
    {
282 20
        if (!\is_callable($value)) {
283 8
            static::reportInvalidArgument(\sprintf(
284 8
                $message ?: 'Expected a callable. Got: %s',
285 8
                static::typeToString($value)
286
            ));
287
        }
288 12
    }
289
290
    /**
291
     * @psalm-pure
292
     * @psalm-assert array $value
293
     *
294
     * @param mixed  $value
295
     * @param string $message
296
     *
297
     * @throws InvalidArgumentException
298
     */
299 20
    public static function isArray($value, $message = '')
300
    {
301 20
        if (!\is_array($value)) {
302 12
            static::reportInvalidArgument(\sprintf(
303 12
                $message ?: 'Expected an array. Got: %s',
304 12
                static::typeToString($value)
305
            ));
306
        }
307 8
    }
308
309
    /**
310
     * @psalm-pure
311
     * @psalm-assert iterable $value
312
     *
313
     * @deprecated use "isIterable" or "isInstanceOf" instead
314
     *
315
     * @param mixed  $value
316
     * @param string $message
317
     *
318
     * @throws InvalidArgumentException
319
     */
320 20
    public static function isTraversable($value, $message = '')
321
    {
322 20
        @\trigger_error(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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

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

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