Failed Conditions
Pull Request — master (#118)
by Gert de
03:12 queued 02: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 $value
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
     * @psalm-assert iterable $value
410
     *
411
     * @deprecated use "isIterable" or "isInstanceOf" instead
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
     * @param mixed                $value
522
     * @param array<object|string> $classes
523
     * @param string               $message
524
     */
525 20
    public static function isInstanceOfAny($value, array $classes, $message = '')
526
    {
527 20
        foreach ($classes as $class) {
528 20
            if ($value instanceof $class) {
529 8
                return;
530
            }
531
        }
532
533 12
        static::reportInvalidArgument(\sprintf(
534 12
            $message ?: 'Expected an instance of any of %2$s. Got: %s',
535 12
            static::typeToString($value),
536 12
            \implode(', ', \array_map(array('static', 'valueToString'), $classes))
537
        ));
538
    }
539
540
    /**
541
     * @psalm-assert empty $value
542
     *
543
     * @param mixed  $value
544
     * @param string $message
545
     */
546 23
    public static function isEmpty($value, $message = '')
547
    {
548 23
        if (!empty($value)) {
549 8
            static::reportInvalidArgument(\sprintf(
550 8
                $message ?: 'Expected an empty value. Got: %s',
551 8
                static::valueToString($value)
552
            ));
553
        }
554 15
    }
555
556
    /**
557
     * @psalm-assert !empty $value
558
     *
559
     * @param mixed  $value
560
     * @param string $message
561
     */
562 23
    public static function notEmpty($value, $message = '')
563
    {
564 23
        if (empty($value)) {
565 15
            static::reportInvalidArgument(\sprintf(
566 15
                $message ?: 'Expected a non-empty value. Got: %s',
567 15
                static::valueToString($value)
568
            ));
569
        }
570 8
    }
571
572
    /**
573
     * @psalm-assert null $value
574
     *
575
     * @param mixed  $value
576
     * @param string $message
577
     */
578 11
    public static function null($value, $message = '')
579
    {
580 11
        if (null !== $value) {
581 8
            static::reportInvalidArgument(\sprintf(
582 8
                $message ?: 'Expected null. Got: %s',
583 8
                static::valueToString($value)
584
            ));
585
        }
586 3
    }
587
588
    /**
589
     * @psalm-assert !null $value
590
     *
591
     * @param mixed  $value
592
     * @param string $message
593
     */
594 11
    public static function notNull($value, $message = '')
595
    {
596 11
        if (null === $value) {
597 3
            static::reportInvalidArgument(
598 3
                $message ?: 'Expected a value other than null.'
599
            );
600
        }
601 8
    }
602
603
    /**
604
     * @psalm-assert true $value
605
     *
606
     * @param mixed  $value
607
     * @param string $message
608
     */
609 15
    public static function true($value, $message = '')
610
    {
611 15
        if (true !== $value) {
612 11
            static::reportInvalidArgument(\sprintf(
613 11
                $message ?: 'Expected a value to be true. Got: %s',
614 11
                static::valueToString($value)
615
            ));
616
        }
617 4
    }
618
619
    /**
620
     * @psalm-assert false $value
621
     *
622
     * @param mixed  $value
623
     * @param string $message
624
     */
625 19
    public static function false($value, $message = '')
626
    {
627 19
        if (false !== $value) {
628 15
            static::reportInvalidArgument(\sprintf(
629 15
                $message ?: 'Expected a value to be false. Got: %s',
630 15
                static::valueToString($value)
631
            ));
632
        }
633 4
    }
634
635
    /**
636
     * @param mixed  $value
637
     * @param string $message
638
     */
639 47 View Code Duplication
    public static function ip($value, $message = '')
640
    {
641 47
        if (false === \filter_var($value, \FILTER_VALIDATE_IP)) {
642 19
            static::reportInvalidArgument(\sprintf(
643 19
                $message ?: 'Expected a value to be an IP. Got: %s',
644 19
                static::valueToString($value)
645
            ));
646
        }
647 28
    }
648
649
    /**
650
     * @param mixed  $value
651
     * @param string $message
652
     */
653 47 View Code Duplication
    public static function ipv4($value, $message = '')
654
    {
655 47
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
656 35
            static::reportInvalidArgument(\sprintf(
657 35
                $message ?: 'Expected a value to be an IPv4. Got: %s',
658 35
                static::valueToString($value)
659
            ));
660
        }
661 12
    }
662
663
    /**
664
     * @param mixed  $value
665
     * @param string $message
666
     */
667 47 View Code Duplication
    public static function ipv6($value, $message = '')
668
    {
669 47
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
670 31
            static::reportInvalidArgument(\sprintf(
671 31
                $message ?: 'Expected a value to be an IPv6. Got %s',
672 31
                static::valueToString($value)
673
            ));
674
        }
675 16
    }
676
677
    /**
678
     * @param mixed  $value
679
     * @param string $message
680
     */
681 16 View Code Duplication
    public static function email($value, $message = '')
682
    {
683 16
        if (false === \filter_var($value, FILTER_VALIDATE_EMAIL)) {
684 12
            static::reportInvalidArgument(\sprintf(
685 12
                $message ?: 'Expected a value to be a valid e-mail address. Got %s',
686 12
                static::valueToString($value)
687
            ));
688
        }
689 4
    }
690
691
    /**
692
     * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion.
693
     *
694
     * @param array  $values
695
     * @param string $message
696
     */
697 12
    public static function uniqueValues(array $values, $message = '')
698
    {
699 12
        $allValues = \count($values);
700 12
        $uniqueValues = \count(\array_unique($values));
701
702 12
        if ($allValues !== $uniqueValues) {
703 8
            $difference = $allValues - $uniqueValues;
704
705 8
            static::reportInvalidArgument(\sprintf(
706 8
                $message ?: 'Expected an array of unique values, but %s of them %s duplicated',
707 8
                $difference,
708 8
                (1 === $difference ? 'is' : 'are')
709
            ));
710
        }
711 4
    }
712
713
    /**
714
     * @param mixed  $value
715
     * @param mixed  $expect
716
     * @param string $message
717
     */
718 33
    public static function eq($value, $expect, $message = '')
719
    {
720 33
        if ($expect != $value) {
721 17
            static::reportInvalidArgument(\sprintf(
722 17
                $message ?: 'Expected a value equal to %2$s. Got: %s',
723 17
                static::valueToString($value),
724 17
                static::valueToString($expect)
725
            ));
726
        }
727 16
    }
728
729
    /**
730
     * @param mixed  $value
731
     * @param mixed  $expect
732
     * @param string $message
733
     */
734 28
    public static function notEq($value, $expect, $message = '')
735
    {
736 28
        if ($expect == $value) {
737 16
            static::reportInvalidArgument(\sprintf(
738 16
                $message ?: 'Expected a different value than %s.',
739 16
                static::valueToString($expect)
740
            ));
741
        }
742 12
    }
743
744
    /**
745
     * @psalm-template ExpectedType
746
     * @psalm-param ExpectedType $expect
747
     * @psalm-assert =ExpectedType $value
748
     *
749
     * @param mixed  $value
750
     * @param mixed  $expect
751
     * @param string $message
752
     */
753 16
    public static function same($value, $expect, $message = '')
754
    {
755 16
        if ($expect !== $value) {
756 12
            static::reportInvalidArgument(\sprintf(
757 12
                $message ?: 'Expected a value identical to %2$s. Got: %s',
758 12
                static::valueToString($value),
759 12
                static::valueToString($expect)
760
            ));
761
        }
762 4
    }
763
764
    /**
765
     * @param mixed  $value
766
     * @param mixed  $expect
767
     * @param string $message
768
     */
769 16
    public static function notSame($value, $expect, $message = '')
770
    {
771 16
        if ($expect === $value) {
772 4
            static::reportInvalidArgument(\sprintf(
773 4
                $message ?: 'Expected a value not identical to %s.',
774 4
                static::valueToString($expect)
775
            ));
776
        }
777 12
    }
778
779
    /**
780
     * @param mixed  $value
781
     * @param mixed  $limit
782
     * @param string $message
783
     */
784 8
    public static function greaterThan($value, $limit, $message = '')
785
    {
786 8
        if ($value <= $limit) {
787 4
            static::reportInvalidArgument(\sprintf(
788 4
                $message ?: 'Expected a value greater than %2$s. Got: %s',
789 4
                static::valueToString($value),
790 4
                static::valueToString($limit)
791
            ));
792
        }
793 4
    }
794
795
    /**
796
     * @param mixed  $value
797
     * @param mixed  $limit
798
     * @param string $message
799
     */
800 12
    public static function greaterThanEq($value, $limit, $message = '')
801
    {
802 12
        if ($value < $limit) {
803 4
            static::reportInvalidArgument(\sprintf(
804 4
                $message ?: 'Expected a value greater than or equal to %2$s. Got: %s',
805 4
                static::valueToString($value),
806 4
                static::valueToString($limit)
807
            ));
808
        }
809 8
    }
810
811
    /**
812
     * @param mixed  $value
813
     * @param mixed  $limit
814
     * @param string $message
815
     */
816 8
    public static function lessThan($value, $limit, $message = '')
817
    {
818 8
        if ($value >= $limit) {
819 4
            static::reportInvalidArgument(\sprintf(
820 4
                $message ?: 'Expected a value less than %2$s. Got: %s',
821 4
                static::valueToString($value),
822 4
                static::valueToString($limit)
823
            ));
824
        }
825 4
    }
826
827
    /**
828
     * @param mixed  $value
829
     * @param mixed  $limit
830
     * @param string $message
831
     */
832 12
    public static function lessThanEq($value, $limit, $message = '')
833
    {
834 12
        if ($value > $limit) {
835 4
            static::reportInvalidArgument(\sprintf(
836 4
                $message ?: 'Expected a value less than or equal to %2$s. Got: %s',
837 4
                static::valueToString($value),
838 4
                static::valueToString($limit)
839
            ));
840
        }
841 8
    }
842
843
    /**
844
     * Inclusive range, so Assert::(3, 3, 5) passes.
845
     *
846
     * @param mixed $value
847
     * @param mixed min
848
     * @param mixed max
849
     * @param string $message
850
     */
851 16 View Code Duplication
    public static function range($value, $min, $max, $message = '')
852
    {
853 16
        if ($value < $min || $value > $max) {
854 8
            static::reportInvalidArgument(\sprintf(
855 8
                $message ?: 'Expected a value between %2$s and %3$s. Got: %s',
856 8
                static::valueToString($value),
857 8
                static::valueToString($min),
858 8
                static::valueToString($max)
859
            ));
860
        }
861 8
    }
862
863
    /**
864
     * Does strict comparison, so Assert::oneOf(3, ['3']) does not pass the assertion.
865
     *
866
     * @psalm-template ExpectedType
867
     * @psalm-param array<ExpectedType> $values
868
     * @psalm-assert ExpectedType $value
869
     *
870
     * @param mixed  $value
871
     * @param array  $values
872
     * @param string $message
873
     */
874 8
    public static function oneOf($value, array $values, $message = '')
875
    {
876 8
        if (!\in_array($value, $values, true)) {
877 4
            static::reportInvalidArgument(\sprintf(
878 4
                $message ?: 'Expected one of: %2$s. Got: %s',
879 4
                static::valueToString($value),
880 4
                \implode(', ', \array_map(array('static', 'valueToString'), $values))
881
            ));
882
        }
883 4
    }
884
885
    /**
886
     * @param mixed  $value
887
     * @param string $subString
888
     * @param string $message
889
     */
890 80 View Code Duplication
    public static function contains($value, $subString, $message = '')
891
    {
892 80
        if (false === \strpos($value, $subString)) {
893 32
            static::reportInvalidArgument(\sprintf(
894 32
                $message ?: 'Expected a value to contain %2$s. Got: %s',
895 32
                static::valueToString($value),
896 32
                static::valueToString($subString)
897
            ));
898
        }
899 48
    }
900
901
    /**
902
     * @param mixed  $value
903
     * @param string $subString
904
     * @param string $message
905
     */
906 80 View Code Duplication
    public static function notContains($value, $subString, $message = '')
907
    {
908 80
        if (false !== \strpos($value, $subString)) {
909 48
            static::reportInvalidArgument(\sprintf(
910 48
                $message ?: '%2$s was not expected to be contained in a value. Got: %s',
911 48
                static::valueToString($value),
912 48
                static::valueToString($subString)
913
            ));
914
        }
915 32
    }
916
917
    /**
918
     * @param mixed  $value
919
     * @param string $message
920
     */
921 40
    public static function notWhitespaceOnly($value, $message = '')
922
    {
923 40
        if (\preg_match('/^\s*$/', $value)) {
924 24
            static::reportInvalidArgument(\sprintf(
925 24
                $message ?: 'Expected a non-whitespace string. Got: %s',
926 24
                static::valueToString($value)
927
            ));
928
        }
929 16
    }
930
931
    /**
932
     * @param mixed  $value
933
     * @param string $prefix
934
     * @param string $message
935
     */
936 48 View Code Duplication
    public static function startsWith($value, $prefix, $message = '')
937
    {
938 48
        if (0 !== \strpos($value, $prefix)) {
939 32
            static::reportInvalidArgument(\sprintf(
940 32
                $message ?: 'Expected a value to start with %2$s. Got: %s',
941 32
                static::valueToString($value),
942 32
                static::valueToString($prefix)
943
            ));
944
        }
945 16
    }
946
947
    /**
948
     * @param mixed  $value
949
     * @param string $message
950
     */
951 24
    public static function startsWithLetter($value, $message = '')
952
    {
953 24
        $valid = isset($value[0]);
954
955 24
        if ($valid) {
956 20
            $locale = \setlocale(LC_CTYPE, 0);
957 20
            \setlocale(LC_CTYPE, 'C');
958 20
            $valid = \ctype_alpha($value[0]);
959 20
            \setlocale(LC_CTYPE, $locale);
960
        }
961
962 24
        if (!$valid) {
963 12
            static::reportInvalidArgument(\sprintf(
964 12
                $message ?: 'Expected a value to start with a letter. Got: %s',
965 12
                static::valueToString($value)
966
            ));
967
        }
968 12
    }
969
970
    /**
971
     * @param mixed  $value
972
     * @param string $suffix
973
     * @param string $message
974
     */
975 48 View Code Duplication
    public static function endsWith($value, $suffix, $message = '')
976
    {
977 48
        if ($suffix !== \substr($value, -\strlen($suffix))) {
978 32
            static::reportInvalidArgument(\sprintf(
979 32
                $message ?: 'Expected a value to end with %2$s. Got: %s',
980 32
                static::valueToString($value),
981 32
                static::valueToString($suffix)
982
            ));
983
        }
984 16
    }
985
986
    /**
987
     * @param mixed  $value
988
     * @param mixed  $pattern
989
     * @param string $message
990
     */
991 12
    public static function regex($value, $pattern, $message = '')
992
    {
993 12
        if (!\preg_match($pattern, $value)) {
994 8
            static::reportInvalidArgument(\sprintf(
995 8
                $message ?: 'The value %s does not match the expected pattern.',
996 8
                static::valueToString($value)
997
            ));
998
        }
999 4
    }
1000
1001
    /**
1002
     * @param mixed  $value
1003
     * @param mixed  $pattern
1004
     * @param string $message
1005
     */
1006 12
    public static function notRegex($value, $pattern, $message = '')
1007
    {
1008 12
        if (\preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) {
1009 4
            static::reportInvalidArgument(\sprintf(
1010 4
                $message ?: 'The value %s matches the pattern %s (at offset %d).',
1011 4
                static::valueToString($value),
1012 4
                static::valueToString($pattern),
1013 4
                $matches[0][1]
1014
            ));
1015
        }
1016 8
    }
1017
1018
    /**
1019
     * @psalm-assert !numeric $value
1020
     *
1021
     * @param mixed  $value
1022
     * @param string $message
1023
     */
1024 28 View Code Duplication
    public static function unicodeLetters($value, $message = '')
1025
    {
1026 28
        static::string($value);
1027
1028 28
        if (!\preg_match('/^\p{L}+$/u', $value)) {
1029 16
            static::reportInvalidArgument(\sprintf(
1030 16
                $message ?: 'Expected a value to contain only Unicode letters. Got: %s',
1031 16
                static::valueToString($value)
1032
            ));
1033
        }
1034 12
    }
1035
1036
    /**
1037
     * @param mixed  $value
1038
     * @param string $message
1039
     */
1040 12 View Code Duplication
    public static function alpha($value, $message = '')
1041
    {
1042 12
        $locale = \setlocale(LC_CTYPE, 0);
1043 12
        \setlocale(LC_CTYPE, 'C');
1044 12
        $valid = !\ctype_alpha($value);
1045 12
        \setlocale(LC_CTYPE, $locale);
1046
1047 12
        if ($valid) {
1048 8
            static::reportInvalidArgument(\sprintf(
1049 8
                $message ?: 'Expected a value to contain only letters. Got: %s',
1050 8
                static::valueToString($value)
1051
            ));
1052
        }
1053 4
    }
1054
1055
    /**
1056
     * @param mixed  $value
1057
     * @param string $message
1058
     */
1059 12 View Code Duplication
    public static function digits($value, $message = '')
1060
    {
1061 12
        $locale = \setlocale(LC_CTYPE, 0);
1062 12
        \setlocale(LC_CTYPE, 'C');
1063 12
        $valid = !\ctype_digit($value);
1064 12
        \setlocale(LC_CTYPE, $locale);
1065
1066 12
        if ($valid) {
1067 8
            static::reportInvalidArgument(\sprintf(
1068 8
                $message ?: 'Expected a value to contain digits only. Got: %s',
1069 8
                static::valueToString($value)
1070
            ));
1071
        }
1072 4
    }
1073
1074
    /**
1075
     * @param mixed  $value
1076
     * @param string $message
1077
     */
1078 12 View Code Duplication
    public static function alnum($value, $message = '')
1079
    {
1080 12
        $locale = \setlocale(LC_CTYPE, 0);
1081 12
        \setlocale(LC_CTYPE, 'C');
1082 12
        $valid = !\ctype_alnum($value);
1083 12
        \setlocale(LC_CTYPE, $locale);
1084
1085 12
        if ($valid) {
1086 8
            static::reportInvalidArgument(\sprintf(
1087 8
                $message ?: 'Expected a value to contain letters and digits only. Got: %s',
1088 8
                static::valueToString($value)
1089
            ));
1090
        }
1091 4
    }
1092
1093
    /**
1094
     * @param mixed  $value
1095
     * @param string $message
1096
     */
1097 16 View Code Duplication
    public static function lower($value, $message = '')
1098
    {
1099 16
        $locale = \setlocale(LC_CTYPE, 0);
1100 16
        \setlocale(LC_CTYPE, 'C');
1101 16
        $valid = !\ctype_lower($value);
1102 16
        \setlocale(LC_CTYPE, $locale);
1103
1104 16
        if ($valid) {
1105 12
            static::reportInvalidArgument(\sprintf(
1106 12
                $message ?: 'Expected a value to contain lowercase characters only. Got: %s',
1107 12
                static::valueToString($value)
1108
            ));
1109
        }
1110 4
    }
1111
1112
    /**
1113
     * @param mixed  $value
1114
     * @param string $message
1115
     */
1116 16 View Code Duplication
    public static function upper($value, $message = '')
1117
    {
1118 16
        $locale = \setlocale(LC_CTYPE, 0);
1119 16
        \setlocale(LC_CTYPE, 'C');
1120 16
        $valid = !\ctype_upper($value);
1121 16
        \setlocale(LC_CTYPE, $locale);
1122
1123 16
        if ($valid) {
1124 12
            static::reportInvalidArgument(\sprintf(
1125 12
                $message ?: 'Expected a value to contain uppercase characters only. Got: %s',
1126 12
                static::valueToString($value)
1127
            ));
1128
        }
1129 4
    }
1130
1131
    /**
1132
     * @param mixed  $value
1133
     * @param mixed  $length
1134
     * @param string $message
1135
     */
1136 36
    public static function length($value, $length, $message = '')
1137
    {
1138 36
        if ($length !== static::strlen($value)) {
1139 24
            static::reportInvalidArgument(\sprintf(
1140 24
                $message ?: 'Expected a value to contain %2$s characters. Got: %s',
1141 24
                static::valueToString($value),
1142 24
                $length
1143
            ));
1144
        }
1145 12
    }
1146
1147
    /**
1148
     * Inclusive min.
1149
     *
1150
     * @param mixed  $value
1151
     * @param mixed  $min
1152
     * @param string $message
1153
     */
1154 36
    public static function minLength($value, $min, $message = '')
1155
    {
1156 36
        if (static::strlen($value) < $min) {
1157 12
            static::reportInvalidArgument(\sprintf(
1158 12
                $message ?: 'Expected a value to contain at least %2$s characters. Got: %s',
1159 12
                static::valueToString($value),
1160 12
                $min
1161
            ));
1162
        }
1163 24
    }
1164
1165
    /**
1166
     * Inclusive max.
1167
     *
1168
     * @param mixed  $value
1169
     * @param mixed  $max
1170
     * @param string $message
1171
     */
1172 36
    public static function maxLength($value, $max, $message = '')
1173
    {
1174 36
        if (static::strlen($value) > $max) {
1175 12
            static::reportInvalidArgument(\sprintf(
1176 12
                $message ?: 'Expected a value to contain at most %2$s characters. Got: %s',
1177 12
                static::valueToString($value),
1178 12
                $max
1179
            ));
1180
        }
1181 24
    }
1182
1183
    /**
1184
     * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion.
1185
     *
1186
     * @param mixed  $value
1187
     * @param mixed  $min
1188
     * @param mixed  $max
1189
     * @param string $message
1190
     */
1191 60 View Code Duplication
    public static function lengthBetween($value, $min, $max, $message = '')
1192
    {
1193 60
        $length = static::strlen($value);
1194
1195 60
        if ($length < $min || $length > $max) {
1196 24
            static::reportInvalidArgument(\sprintf(
1197 24
                $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s',
1198 24
                static::valueToString($value),
1199 24
                $min,
1200 24
                $max
1201
            ));
1202
        }
1203 36
    }
1204
1205
    /**
1206
     * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file.
1207
     *
1208
     * @param mixed  $value
1209
     * @param string $message
1210
     */
1211 36 View Code Duplication
    public static function fileExists($value, $message = '')
1212
    {
1213 36
        static::string($value);
1214
1215 36
        if (!\file_exists($value)) {
1216 12
            static::reportInvalidArgument(\sprintf(
1217 12
                $message ?: 'The file %s does not exist.',
1218 12
                static::valueToString($value)
1219
            ));
1220
        }
1221 24
    }
1222
1223
    /**
1224
     * @param mixed  $value
1225
     * @param string $message
1226
     */
1227 12 View Code Duplication
    public static function file($value, $message = '')
1228
    {
1229 12
        static::fileExists($value, $message);
1230
1231 8
        if (!\is_file($value)) {
1232 4
            static::reportInvalidArgument(\sprintf(
1233 4
                $message ?: 'The path %s is not a file.',
1234 4
                static::valueToString($value)
1235
            ));
1236
        }
1237 4
    }
1238
1239
    /**
1240
     * @param mixed  $value
1241
     * @param string $message
1242
     */
1243 12 View Code Duplication
    public static function directory($value, $message = '')
1244
    {
1245 12
        static::fileExists($value, $message);
1246
1247 8
        if (!\is_dir($value)) {
1248 4
            static::reportInvalidArgument(\sprintf(
1249 4
                $message ?: 'The path %s is no directory.',
1250 4
                static::valueToString($value)
1251
            ));
1252
        }
1253 4
    }
1254
1255
    /**
1256
     * @param mixed  $value
1257
     * @param string $message
1258
     */
1259
    public static function readable($value, $message = '')
1260
    {
1261
        if (!\is_readable($value)) {
1262
            static::reportInvalidArgument(\sprintf(
1263
                $message ?: 'The path %s is not readable.',
1264
                static::valueToString($value)
1265
            ));
1266
        }
1267
    }
1268
1269
    /**
1270
     * @param mixed  $value
1271
     * @param string $message
1272
     */
1273
    public static function writable($value, $message = '')
1274
    {
1275
        if (!\is_writable($value)) {
1276
            static::reportInvalidArgument(\sprintf(
1277
                $message ?: 'The path %s is not writable.',
1278
                static::valueToString($value)
1279
            ));
1280
        }
1281
    }
1282
1283
    /**
1284
     * @psalm-assert class-string $value
1285
     *
1286
     * @param mixed  $value
1287
     * @param string $message
1288
     */
1289 8
    public static function classExists($value, $message = '')
1290
    {
1291 8
        if (!\class_exists($value)) {
1292 4
            static::reportInvalidArgument(\sprintf(
1293 4
                $message ?: 'Expected an existing class name. Got: %s',
1294 4
                static::valueToString($value)
1295
            ));
1296
        }
1297 4
    }
1298
1299
    /**
1300
     * @param mixed         $value
1301
     * @param string|object $class
1302
     * @param string        $message
1303
     */
1304 8
    public static function subclassOf($value, $class, $message = '')
1305
    {
1306 8
        if (!\is_subclass_of($value, $class)) {
1307 4
            static::reportInvalidArgument(\sprintf(
1308 4
                $message ?: 'Expected a sub-class of %2$s. Got: %s',
1309 4
                static::valueToString($value),
1310 4
                static::valueToString($class)
1311
            ));
1312
        }
1313 4
    }
1314
1315
    /**
1316
     * @psalm-assert class-string $value
1317
     *
1318
     * @param mixed  $value
1319
     * @param string $message
1320
     */
1321 8
    public static function interfaceExists($value, $message = '')
1322
    {
1323 8
        if (!\interface_exists($value)) {
1324 4
            static::reportInvalidArgument(\sprintf(
1325 4
                $message ?: 'Expected an existing interface name. got %s',
1326 4
                static::valueToString($value)
1327
            ));
1328
        }
1329 4
    }
1330
1331
    /**
1332
     * @param mixed  $value
1333
     * @param mixed  $interface
1334
     * @param string $message
1335
     */
1336 8 View Code Duplication
    public static function implementsInterface($value, $interface, $message = '')
1337
    {
1338 8
        if (!\in_array($interface, \class_implements($value))) {
1339 4
            static::reportInvalidArgument(\sprintf(
1340 4
                $message ?: 'Expected an implementation of %2$s. Got: %s',
1341 4
                static::valueToString($value),
1342 4
                static::valueToString($interface)
1343
            ));
1344
        }
1345 4
    }
1346
1347
    /**
1348
     * @param string|object $classOrObject
1349
     * @param mixed         $property
1350
     * @param string        $message
1351
     */
1352 12 View Code Duplication
    public static function propertyExists($classOrObject, $property, $message = '')
1353
    {
1354 12
        if (!\property_exists($classOrObject, $property)) {
1355 4
            static::reportInvalidArgument(\sprintf(
1356 4
                $message ?: 'Expected the property %s to exist.',
1357 4
                static::valueToString($property)
1358
            ));
1359
        }
1360 8
    }
1361
1362
    /**
1363
     * @param string|object $classOrObject
1364
     * @param mixed         $property
1365
     * @param string        $message
1366
     */
1367 12 View Code Duplication
    public static function propertyNotExists($classOrObject, $property, $message = '')
1368
    {
1369 12
        if (\property_exists($classOrObject, $property)) {
1370 8
            static::reportInvalidArgument(\sprintf(
1371 8
                $message ?: 'Expected the property %s to not exist.',
1372 8
                static::valueToString($property)
1373
            ));
1374
        }
1375 4
    }
1376
1377
    /**
1378
     * @param string|object $classOrObject
1379
     * @param mixed         $method
1380
     * @param string        $message
1381
     */
1382 27 View Code Duplication
    public static function methodExists($classOrObject, $method, $message = '')
1383
    {
1384 27
        if (!\method_exists($classOrObject, $method)) {
1385 19
            static::reportInvalidArgument(\sprintf(
1386 19
                $message ?: 'Expected the method %s to exist.',
1387 19
                static::valueToString($method)
1388
            ));
1389
        }
1390 8
    }
1391
1392
    /**
1393
     * @param string|object $classOrObject
1394
     * @param mixed         $method
1395
     * @param string        $message
1396
     */
1397 27 View Code Duplication
    public static function methodNotExists($classOrObject, $method, $message = '')
1398
    {
1399 27
        if (\method_exists($classOrObject, $method)) {
1400 8
            static::reportInvalidArgument(\sprintf(
1401 8
                $message ?: 'Expected the method %s to not exist.',
1402 8
                static::valueToString($method)
1403
            ));
1404
        }
1405 19
    }
1406
1407
    /**
1408
     * @param array      $array
1409
     * @param string|int $key
1410
     * @param string     $message
1411
     */
1412 12 View Code Duplication
    public static function keyExists($array, $key, $message = '')
1413
    {
1414 12
        if (!(isset($array[$key]) || \array_key_exists($key, $array))) {
1415 4
            static::reportInvalidArgument(\sprintf(
1416 4
                $message ?: 'Expected the key %s to exist.',
1417 4
                static::valueToString($key)
1418
            ));
1419
        }
1420 8
    }
1421
1422
    /**
1423
     * @param array      $array
1424
     * @param string|int $key
1425
     * @param string     $message
1426
     */
1427 12 View Code Duplication
    public static function keyNotExists($array, $key, $message = '')
1428
    {
1429 12
        if (isset($array[$key]) || \array_key_exists($key, $array)) {
1430 8
            static::reportInvalidArgument(\sprintf(
1431 8
                $message ?: 'Expected the key %s to not exist.',
1432 8
                static::valueToString($key)
1433
            ));
1434
        }
1435 4
    }
1436
1437
    /**
1438
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1439
     *
1440
     * @param mixed  $array
1441
     * @param mixed  $number
1442
     * @param string $message
1443
     */
1444 8
    public static function count($array, $number, $message = '')
1445
    {
1446 8
        static::eq(
1447 8
            \count($array),
1448
            $number,
1449 8
            $message ?: \sprintf('Expected an array to contain %d elements. Got: %d.', $number, \count($array))
1450
        );
1451 4
    }
1452
1453
    /**
1454
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1455
     *
1456
     * @param mixed  $array
1457
     * @param mixed  $min
1458
     * @param string $message
1459
     */
1460 12 View Code Duplication
    public static function minCount($array, $min, $message = '')
1461
    {
1462 12
        if (\count($array) < $min) {
1463 4
            static::reportInvalidArgument(\sprintf(
1464 4
                $message ?: 'Expected an array to contain at least %2$d elements. Got: %d',
1465 4
                \count($array),
1466 4
                $min
1467
            ));
1468
        }
1469 8
    }
1470
1471
    /**
1472
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1473
     *
1474
     * @param mixed  $array
1475
     * @param mixed  $max
1476
     * @param string $message
1477
     */
1478 12 View Code Duplication
    public static function maxCount($array, $max, $message = '')
1479
    {
1480 12
        if (\count($array) > $max) {
1481 4
            static::reportInvalidArgument(\sprintf(
1482 4
                $message ?: 'Expected an array to contain at most %2$d elements. Got: %d',
1483 4
                \count($array),
1484 4
                $max
1485
            ));
1486
        }
1487 8
    }
1488
1489
    /**
1490
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1491
     *
1492
     * @param mixed  $array
1493
     * @param mixed  $min
1494
     * @param mixed  $max
1495
     * @param string $message
1496
     */
1497 20
    public static function countBetween($array, $min, $max, $message = '')
1498
    {
1499 20
        $count = \count($array);
1500
1501 20
        if ($count < $min || $count > $max) {
1502 8
            static::reportInvalidArgument(\sprintf(
1503 8
                $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d',
1504 8
                $count,
1505 8
                $min,
1506 8
                $max
1507
            ));
1508
        }
1509 12
    }
1510
1511
    /**
1512
     * @param mixed  $array
1513
     * @param string $message
1514
     */
1515 24
    public static function isList($array, $message = '')
1516
    {
1517 24
        if (!\is_array($array) || !$array || \array_keys($array) !== \range(0, \count($array) - 1)) {
1518 20
            static::reportInvalidArgument(
1519 20
                $message ?: 'Expected list - non-associative array.'
1520
            );
1521
        }
1522 4
    }
1523
1524
    /**
1525
     * @param mixed  $array
1526
     * @param string $message
1527
     */
1528 16
    public static function isMap($array, $message = '')
1529
    {
1530
        if (
1531 16
            !\is_array($array) ||
1532 16
            !$array ||
1533
            \array_keys($array) !== \array_filter(\array_keys($array), function ($key) {
1534 12
                return \is_string($key);
1535 16
            })
1536
        ) {
1537 12
            static::reportInvalidArgument(
1538 12
                $message ?: 'Expected map - associative array with string keys.'
1539
            );
1540
        }
1541 4
    }
1542
1543
    /**
1544
     * @param mixed  $value
1545
     * @param string $message
1546
     */
1547 56
    public static function uuid($value, $message = '')
1548
    {
1549 56
        $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
1550
1551
        // The nil UUID is special form of UUID that is specified to have all
1552
        // 128 bits set to zero.
1553 56
        if ('00000000-0000-0000-0000-000000000000' === $value) {
1554 4
            return;
1555
        }
1556
1557 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)) {
1558 20
            static::reportInvalidArgument(\sprintf(
1559 20
                $message ?: 'Value %s is not a valid UUID.',
1560 20
                static::valueToString($value)
1561
            ));
1562
        }
1563 32
    }
1564
1565
    /**
1566
     * @param Closure       $expression
1567
     * @param string|object $class
1568
     * @param string        $message
1569
     */
1570 24
    public static function throws(Closure $expression, $class = 'Exception', $message = '')
1571
    {
1572 24
        static::string($class);
1573
1574 24
        $actual = 'none';
1575
1576
        try {
1577 24
            $expression();
1578 24
        } catch (Exception $e) {
1579 20
            $actual = \get_class($e);
1580 20
            if ($e instanceof $class) {
1581 20
                return;
1582
            }
1583 4
        } catch (Throwable $e) {
1584 4
            $actual = \get_class($e);
1585 4
            if ($e instanceof $class) {
1586 4
                return;
1587
            }
1588
        }
1589
1590 8
        static::reportInvalidArgument($message ?: \sprintf(
1591 8
            'Expected to throw "%s", got "%s"',
1592 8
            $class,
1593 8
            $actual
1594
        ));
1595
    }
1596
1597 1383
    public static function __callStatic($name, $arguments)
1598
    {
1599 1383
        if ('nullOr' === \substr($name, 0, 6)) {
1600 514
            if (null !== $arguments[0]) {
1601 421
                $method = \lcfirst(\substr($name, 6));
1602 421
                \call_user_func_array(array('static', $method), $arguments);
1603
            }
1604
1605 296
            return;
1606
        }
1607
1608 869
        if ('all' === \substr($name, 0, 3)) {
1609 868
            static::isIterable($arguments[0]);
1610
1611 868
            $method = \lcfirst(\substr($name, 3));
1612 868
            $args = $arguments;
1613
1614 868
            foreach ($arguments[0] as $entry) {
1615 868
                $args[0] = $entry;
1616
1617 868
                \call_user_func_array(array('static', $method), $args);
1618
            }
1619
1620 412
            return;
1621
        }
1622
1623 1
        throw new BadMethodCallException('No such method: '.$name);
1624
    }
1625
1626
    /**
1627
     * @param mixed $value
1628
     *
1629
     * @return string
1630
     */
1631 694
    protected static function valueToString($value)
1632
    {
1633 694
        if (null === $value) {
1634 20
            return 'null';
1635
        }
1636
1637 676
        if (true === $value) {
1638 15
            return 'true';
1639
        }
1640
1641 666
        if (false === $value) {
1642 25
            return 'false';
1643
        }
1644
1645 641
        if (\is_array($value)) {
1646 13
            return 'array';
1647
        }
1648
1649 628
        if (\is_object($value)) {
1650 2
            if (\method_exists($value, '__toString')) {
1651 1
                return \get_class($value).': '.self::valueToString($value->__toString());
1652
            }
1653
1654 1
            return \get_class($value);
1655
        }
1656
1657 627
        if (\is_resource($value)) {
1658 1
            return 'resource';
1659
        }
1660
1661 627
        if (\is_string($value)) {
1662 525
            return '"'.$value.'"';
1663
        }
1664
1665 110
        return (string) $value;
1666
    }
1667
1668
    /**
1669
     * @param mixed $value
1670
     *
1671
     * @return string
1672
     */
1673 169
    protected static function typeToString($value)
1674
    {
1675 169
        return \is_object($value) ? \get_class($value) : \gettype($value);
1676
    }
1677
1678 168
    protected static function strlen($value)
1679
    {
1680 168
        if (!\function_exists('mb_detect_encoding')) {
1681
            return \strlen($value);
1682
        }
1683
1684 168
        if (false === $encoding = \mb_detect_encoding($value)) {
1685
            return \strlen($value);
1686
        }
1687
1688 168
        return \mb_strlen($value, $encoding);
1689
    }
1690
1691
    /**
1692
     * @param string $message
1693
     */
1694 918
    protected static function reportInvalidArgument($message)
1695
    {
1696 918
        throw new InvalidArgumentException($message);
1697
    }
1698
1699
    private function __construct()
1700
    {
1701
    }
1702
}
1703