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