Failed Conditions
Push — master ( 07f51c...1ca74b )
by Gert de
03:02
created

src/Assert.php (1 issue)

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