Failed Conditions
Pull Request — master (#118)
by Gert de
15:57
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 122
    /**
196
     * @psalm-assert string $value
197 122
     *
198 14
     * @param mixed  $value
199 14
     * @param string $message
200 14
     */
201
    public static function string($value, $message = '')
202
    {
203 108
        if (!\is_string($value)) {
204
            static::reportInvalidArgument(\sprintf(
205 16
                $message ?: 'Expected a string. Got: %s',
206
                static::typeToString($value)
207 16
            ));
208 12
        }
209 8
    }
210
211 17
    /**
212
     * @psalm-assert string $value
213 17
     *
214 13
     * @param mixed  $value
215 13
     * @param string $message
216 13
     */
217
    public static function stringNotEmpty($value, $message = '')
218
    {
219 4
        static::string($value, $message);
220
        static::notEq($value, '', $message);
221 16
    }
222
223 16
    /**
224 4
     * @psalm-assert int $value
225 4
     *
226 4
     * @param mixed  $value
227
     * @param string $message
228
     */
229 12
    public static function integer($value, $message = '')
230
    {
231 16
        if (!\is_int($value)) {
232
            static::reportInvalidArgument(\sprintf(
233 16
                $message ?: 'Expected an integer. Got: %s',
234 8
                static::typeToString($value)
235 8
            ));
236 8
        }
237
    }
238
239 8
    /**
240
     * @psalm-assert numeric
241 20
     *
242
     * @param mixed  $value
243 20
     * @param string $message
244 4
     */
245 4
    public static function integerish($value, $message = '')
246 4
    {
247
        if (!\is_numeric($value) || $value != (int) $value) {
248
            static::reportInvalidArgument(\sprintf(
249 16
                $message ?: 'Expected an integerish value. Got: %s',
250
                static::typeToString($value)
251 24
            ));
252
        }
253 24
    }
254 16
255 16
    /**
256 16
     * @psalm-assert float $value
257
     *
258
     * @param mixed  $value
259 8
     * @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 23
    /**
272
     * @psalm-assert numeric $value
273 23
     *
274 11
     * @param mixed  $value
275 11
     * @param string $message
276 11
     */
277
    public static function numeric($value, $message = '')
278
    {
279 12
        if (!\is_numeric($value)) {
280
            static::reportInvalidArgument(\sprintf(
281 23
                $message ?: 'Expected a numeric. Got: %s',
282
                static::typeToString($value)
283 23
            ));
284 15
        }
285 15
    }
286 15
287
    /**
288
     * @psalm-assert int $value
289 8
     *
290
     * @param mixed  $value
291 16
     * @param string $message
292
     */
293 16
    public static function natural($value, $message = '')
294 4
    {
295 4
        if (!\is_int($value) || $value < 0) {
296 4
            static::reportInvalidArgument(\sprintf(
297
                $message ?: 'Expected a non-negative integer. Got %s',
298
                static::valueToString($value)
299
            ));
300 12
        }
301 4
    }
302 4
303 4
    /**
304 4
     * @psalm-assert bool $value
305
     *
306
     * @param mixed  $value
307 8
     * @param string $message
308
     */
309 20
    public static function boolean($value, $message = '')
310
    {
311 20
        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 12
    }
318
319 20
    /**
320
     * @psalm-assert scalar $value
321 20
     *
322 12
     * @param mixed  $value
323 12
     * @param string $message
324 12
     */
325
    public static function scalar($value, $message = '')
326
    {
327 8
        if (!\is_scalar($value)) {
328
            static::reportInvalidArgument(\sprintf(
329
                $message ?: 'Expected a scalar. Got: %s',
330
                static::typeToString($value)
331
            ));
332 20
        }
333
    }
334 20
335 20
    /**
336 20
     * @psalm-assert object $value
337 20
     *
338
     * @param mixed$value
339 20
     * @param string $message
340
     */
341
    public static function object($value, $message = '')
342 20
    {
343 8
        if (!\is_object($value)) {
344 8
            static::reportInvalidArgument(\sprintf(
345 8
                $message ?: 'Expected an object. Got: %s',
346
                static::typeToString($value)
347
            ));
348 12
        }
349
    }
350 20
351
    /**
352 20
     * @psalm-assert resource $value
353 8
     *
354 8
     * @param mixed       $value
355 8
     * @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 12
    public static function resource($value, $type = null, $message = '')
359
    {
360 24
        if (!\is_resource($value)) {
361
            static::reportInvalidArgument(\sprintf(
362 24
                $message ?: 'Expected a resource. Got: %s',
363 12
                static::typeToString($value)
364 12
            ));
365 12
        }
366
367
        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 12
            static::reportInvalidArgument(\sprintf(
369
                $message ?: 'Expected a resource of type %2$s. Got: %s',
370 878
                static::typeToString($value),
371
                $type
372 878
            ));
373 8
        }
374 8
    }
375 8
376
    /**
377
     * @psalm-assert callable $value
378 874
     *
379
     * @param mixed  $value
380 16
     * @param string $message
381
     */
382 16
    public static function isCallable($value, $message = '')
383 12
    {
384 12
        if (!\is_callable($value)) {
385 12
            static::reportInvalidArgument(\sprintf(
386 12
                $message ?: 'Expected a callable. Got: %s',
387
                static::typeToString($value)
388
            ));
389 4
        }
390
    }
391 16
392
    /**
393 16
     * @psalm-assert array $value
394 4
     *
395 4
     * @param mixed  $value
396 4
     * @param string $message
397 4
     */
398
    public static function isArray($value, $message = '')
399
    {
400 12
        if (!\is_array($value)) {
401
            static::reportInvalidArgument(\sprintf(
402 20
                $message ?: 'Expected an array. Got: %s',
403
                static::typeToString($value)
404 20
            ));
405 20
        }
406 8
    }
407
408
    /**
409
     * @deprecated use "isIterable" or "isInstanceOf" instead
410 12
     *
411 12
     * @psalm-assert iterable $value
412 12
     *
413 12
     * @param mixed  $value
414
     * @param string $message
415
     */
416
    public static function isTraversable($value, $message = '')
417 23
    {
418
        @\trigger_error(
419 23
            \sprintf(
420 8
                '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 8
                __METHOD__
422 8
            ),
423
            \E_USER_DEPRECATED
424
        );
425 15
426
        if (!\is_array($value) && !($value instanceof Traversable)) {
427 23
            static::reportInvalidArgument(\sprintf(
428
                $message ?: 'Expected a traversable. Got: %s',
429 23
                static::typeToString($value)
430 15
            ));
431 15
        }
432 15
    }
433
434
    /**
435 8
     * @param mixed  $value
436
     * @param string $message
437 11
     */
438 View Code Duplication
    public static function isArrayAccessible($value, $message = '')
439 11
    {
440 8
        if (!\is_array($value) && !($value instanceof ArrayAccess)) {
441 8
            static::reportInvalidArgument(\sprintf(
442 8
                $message ?: 'Expected an array accessible. Got: %s',
443
                static::typeToString($value)
444
            ));
445 3
        }
446
    }
447 11
448
    /**
449 11
     * @psalm-assert countable $value
450 3
     *
451 3
     * @param mixed  $value
452
     * @param string $message
453
     */
454 8 View Code Duplication
    public static function isCountable($value, $message = '')
455
    {
456 15
        if (!\is_array($value) && !($value instanceof Countable)) {
457
            static::reportInvalidArgument(\sprintf(
458 15
                $message ?: 'Expected a countable. Got: %s',
459 11
                static::typeToString($value)
460 11
            ));
461 11
        }
462
    }
463
464 4
    /**
465
     * @psalm-assert iterable $value
466 19
     *
467
     * @param mixed  $value
468 19
     * @param string $message
469 15
     */
470 15 View Code Duplication
    public static function isIterable($value, $message = '')
471 15
    {
472
        if (!\is_array($value) && !($value instanceof Traversable)) {
473
            static::reportInvalidArgument(\sprintf(
474 4
                $message ?: 'Expected an iterable. Got: %s',
475
                static::typeToString($value)
476 47
            ));
477
        }
478 47
    }
479 19
480 19
    /**
481 19
     * @psalm-template ExpectedType of object
482
     * @psalm-param class-string<ExpectedType> $class
483
     * @psalm-assert ExpectedType $value
484 28
     *
485
     * @param mixed         $value
486 47
     * @param string|object $class
487
     * @param string        $message
488 47
     */
489 35
    public static function isInstanceOf($value, $class, $message = '')
490 35
    {
491 35
        if (!($value instanceof $class)) {
492
            static::reportInvalidArgument(\sprintf(
493
                $message ?: 'Expected an instance of %2$s. Got: %s',
494 12
                static::typeToString($value),
495
                $class
496 47
            ));
497
        }
498 47
    }
499 31
500 31
    /**
501 31
     * @psalm-template ExpectedType of object
502
     * @psalm-param class-string<ExpectedType> $class
503
     * @psalm-assert !ExpectedType $value
504 16
     *
505
     * @param mixed         $value
506 16
     * @param string|object $class
507
     * @param string        $message
508 16
     */
509 12
    public static function notInstanceOf($value, $class, $message = '')
510 12
    {
511 12
        if ($value instanceof $class) {
512
            static::reportInvalidArgument(\sprintf(
513
                $message ?: 'Expected an instance other than %2$s. Got: %s',
514 4
                static::typeToString($value),
515
                $class
516 12
            ));
517
        }
518 12
    }
519 12
520
    /**
521 12
     * @psalm-template ExpectedType
522 8
     * @psalm-param array<class-string<ExpectedType>|ExpectedType> $classes
523
     * @psalm-assert ExpectedType $value
524 8
     *
525 8
     * @param mixed                $value
526 8
     * @param array<object|string> $classes
527 8
     * @param string               $message
528
     */
529
    public static function isInstanceOfAny($value, array $classes, $message = '')
530 4
    {
531
        foreach ($classes as $class) {
532 33
            if ($value instanceof $class) {
533
                return;
534 33
            }
535 17
        }
536 17
537 17
        static::reportInvalidArgument(\sprintf(
538 17
            $message ?: 'Expected an instance of any of %2$s. Got: %s',
539
            static::typeToString($value),
540
            \implode(', ', \array_map(array('static', 'valueToString'), $classes))
541 16
        ));
542
    }
543 28
544
    /**
545 28
     * @psalm-assert empty $value
546 16
     *
547 16
     * @param mixed  $value
548 16
     * @param string $message
549
     */
550
    public static function isEmpty($value, $message = '')
551 12
    {
552
        if (!empty($value)) {
553 16
            static::reportInvalidArgument(\sprintf(
554
                $message ?: 'Expected an empty value. Got: %s',
555 16
                static::valueToString($value)
556 12
            ));
557 12
        }
558 12
    }
559 12
560
    /**
561
     * @psalm-assert !empty $value
562 4
     *
563
     * @param mixed  $value
564 16
     * @param string $message
565
     */
566 16
    public static function notEmpty($value, $message = '')
567 4
    {
568 4
        if (empty($value)) {
569 4
            static::reportInvalidArgument(\sprintf(
570
                $message ?: 'Expected a non-empty value. Got: %s',
571
                static::valueToString($value)
572 12
            ));
573
        }
574 8
    }
575
576 8
    /**
577 4
     * @psalm-assert null $value
578 4
     *
579 4
     * @param mixed  $value
580 4
     * @param string $message
581
     */
582
    public static function null($value, $message = '')
583 4
    {
584
        if (null !== $value) {
585 12
            static::reportInvalidArgument(\sprintf(
586
                $message ?: 'Expected null. Got: %s',
587 12
                static::valueToString($value)
588 4
            ));
589 4
        }
590 4
    }
591 4
592
    /**
593
     * @psalm-assert !null $value
594 8
     *
595
     * @param mixed  $value
596 8
     * @param string $message
597
     */
598 8
    public static function notNull($value, $message = '')
599 4
    {
600 4
        if (null === $value) {
601 4
            static::reportInvalidArgument(
602 4
                $message ?: 'Expected a value other than null.'
603
            );
604
        }
605 4
    }
606
607 12
    /**
608
     * @psalm-assert true $value
609 12
     *
610 4
     * @param mixed  $value
611 4
     * @param string $message
612 4
     */
613 4
    public static function true($value, $message = '')
614
    {
615
        if (true !== $value) {
616 8
            static::reportInvalidArgument(\sprintf(
617
                $message ?: 'Expected a value to be true. Got: %s',
618 16
                static::valueToString($value)
619
            ));
620 16
        }
621 8
    }
622 8
623 8
    /**
624 8
     * @psalm-assert false $value
625 8
     *
626
     * @param mixed$value
627
     * @param string $message
628 8
     */
629
    public static function false($value, $message = '')
630 8
    {
631
        if (false !== $value) {
632 8
            static::reportInvalidArgument(\sprintf(
633 4
                $message ?: 'Expected a value to be false. Got: %s',
634 4
                static::valueToString($value)
635 4
            ));
636 4
        }
637
    }
638
639 4
    /**
640
     * @param mixed  $value
641 80
     * @param string $message
642
     */
643 80 View Code Duplication
    public static function ip($value, $message = '')
644 32
    {
645 32
        if (false === \filter_var($value, \FILTER_VALIDATE_IP)) {
646 32
            static::reportInvalidArgument(\sprintf(
647 32
                $message ?: 'Expected a value to be an IP. Got: %s',
648
                static::valueToString($value)
649
            ));
650 48
        }
651
    }
652 80
653
    /**
654 80
     * @param mixed  $value
655 48
     * @param string $message
656 48
     */
657 48 View Code Duplication
    public static function ipv4($value, $message = '')
658 48
    {
659
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
660
            static::reportInvalidArgument(\sprintf(
661 32
                $message ?: 'Expected a value to be an IPv4. Got: %s',
662
                static::valueToString($value)
663 40
            ));
664
        }
665 40
    }
666 24
667 24
    /**
668 24
     * @param mixed  $value
669
     * @param string $message
670
     */
671 16 View Code Duplication
    public static function ipv6($value, $message = '')
672
    {
673 48
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
674
            static::reportInvalidArgument(\sprintf(
675 48
                $message ?: 'Expected a value to be an IPv6. Got %s',
676 32
                static::valueToString($value)
677 32
            ));
678 32
        }
679 32
    }
680
681
    /**
682 16
     * @param mixed  $value
683
     * @param string $message
684 24
     */
685 View Code Duplication
    public static function email($value, $message = '')
686 24
    {
687
        if (false === \filter_var($value, FILTER_VALIDATE_EMAIL)) {
688 24
            static::reportInvalidArgument(\sprintf(
689 20
                $message ?: 'Expected a value to be a valid e-mail address. Got %s',
690 20
                static::valueToString($value)
691 20
            ));
692 20
        }
693
    }
694
695 24
    /**
696 12
     * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion.
697 12
     *
698 12
     * @param array  $values
699
     * @param string $message
700
     */
701 12
    public static function uniqueValues(array $values, $message = '')
702
    {
703 48
        $allValues = \count($values);
704
        $uniqueValues = \count(\array_unique($values));
705 48
706 32
        if ($allValues !== $uniqueValues) {
707 32
            $difference = $allValues - $uniqueValues;
708 32
709 32
            static::reportInvalidArgument(\sprintf(
710
                $message ?: 'Expected an array of unique values, but %s of them %s duplicated',
711
                $difference,
712 16
                (1 === $difference ? 'is' : 'are')
713
            ));
714 12
        }
715
    }
716 12
717 8
    /**
718 8
     * @param mixed  $value
719 8
     * @param mixed  $expect
720
     * @param string $message
721
     */
722 4
    public static function eq($value, $expect, $message = '')
723
    {
724 12
        if ($expect != $value) {
725
            static::reportInvalidArgument(\sprintf(
726 12
                $message ?: 'Expected a value equal to %2$s. Got: %s',
727 4
                static::valueToString($value),
728 4
                static::valueToString($expect)
729 4
            ));
730 4
        }
731 4
    }
732
733
    /**
734 8
     * @param mixed  $value
735
     * @param mixed  $expect
736 28
     * @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 12
    /**
749
     * @psalm-template ExpectedType
750 12
     * @psalm-param ExpectedType $expect
751 12
     * @psalm-assert =ExpectedType $value
752 12
     *
753 12
     * @param mixed  $value
754
     * @param mixed  $expect
755 12
     * @param string $message
756 8
     */
757 8
    public static function same($value, $expect, $message = '')
758 8
    {
759
        if ($expect !== $value) {
760
            static::reportInvalidArgument(\sprintf(
761 4
                $message ?: 'Expected a value identical to %2$s. Got: %s',
762
                static::valueToString($value),
763 12
                static::valueToString($expect)
764
            ));
765 12
        }
766 12
    }
767 12
768 12
    /**
769
     * @param mixed  $value
770 12
     * @param mixed  $expect
771 8
     * @param string $message
772 8
     */
773 8
    public static function notSame($value, $expect, $message = '')
774
    {
775
        if ($expect === $value) {
776 4
            static::reportInvalidArgument(\sprintf(
777
                $message ?: 'Expected a value not identical to %s.',
778 12
                static::valueToString($expect)
779
            ));
780 12
        }
781 12
    }
782 12
783 12
    /**
784
     * @param mixed  $value
785 12
     * @param mixed  $limit
786 8
     * @param string $message
787 8
     */
788 8
    public static function greaterThan($value, $limit, $message = '')
789
    {
790
        if ($value <= $limit) {
791 4
            static::reportInvalidArgument(\sprintf(
792
                $message ?: 'Expected a value greater than %2$s. Got: %s',
793 16
                static::valueToString($value),
794
                static::valueToString($limit)
795 16
            ));
796 16
        }
797 16
    }
798 16
799
    /**
800 16
     * @param mixed  $value
801 12
     * @param mixed  $limit
802 12
     * @param string $message
803 12
     */
804
    public static function greaterThanEq($value, $limit, $message = '')
805
    {
806 4
        if ($value < $limit) {
807
            static::reportInvalidArgument(\sprintf(
808 16
                $message ?: 'Expected a value greater than or equal to %2$s. Got: %s',
809
                static::valueToString($value),
810 16
                static::valueToString($limit)
811 16
            ));
812 16
        }
813 16
    }
814
815 16
    /**
816 12
     * @param mixed  $value
817 12
     * @param mixed  $limit
818 12
     * @param string $message
819
     */
820
    public static function lessThan($value, $limit, $message = '')
821 4
    {
822
        if ($value >= $limit) {
823 36
            static::reportInvalidArgument(\sprintf(
824
                $message ?: 'Expected a value less than %2$s. Got: %s',
825 36
                static::valueToString($value),
826 24
                static::valueToString($limit)
827 24
            ));
828 24
        }
829 24
    }
830
831
    /**
832 12
     * @param mixed  $value
833
     * @param mixed  $limit
834 36
     * @param string $message
835
     */
836 36
    public static function lessThanEq($value, $limit, $message = '')
837 12
    {
838 12
        if ($value > $limit) {
839 12
            static::reportInvalidArgument(\sprintf(
840 12
                $message ?: 'Expected a value less than or equal to %2$s. Got: %s',
841
                static::valueToString($value),
842
                static::valueToString($limit)
843 24
            ));
844
        }
845 36
    }
846
847 36
    /**
848 12
     * Inclusive range, so Assert::(3, 3, 5) passes.
849 12
     *
850 12
     * @param mixed $value
851 12
     * @param mixed min
852
     * @param mixed max
853
     * @param string $message
854 24
     */
855 View Code Duplication
    public static function range($value, $min, $max, $message = '')
856 60
    {
857
        if ($value < $min || $value > $max) {
858 60
            static::reportInvalidArgument(\sprintf(
859
                $message ?: 'Expected a value between %2$s and %3$s. Got: %s',
860 60
                static::valueToString($value),
861 24
                static::valueToString($min),
862 24
                static::valueToString($max)
863 24
            ));
864 24
        }
865 24
    }
866
867
    /**
868 36
     * Does strict comparison, so Assert::oneOf(3, ['3']) does not pass the assertion.
869
     *
870 36
     * @psalm-template ExpectedType
871
     * @psalm-param array<ExpectedType> $values
872 36
     * @psalm-assert ExpectedType $value
873
     *
874 36
     * @param mixed  $value
875 12
     * @param array  $values
876 12
     * @param string $message
877 12
     */
878
    public static function oneOf($value, array $values, $message = '')
879
    {
880 24
        if (!\in_array($value, $values, true)) {
881
            static::reportInvalidArgument(\sprintf(
882 12
                $message ?: 'Expected one of: %2$s. Got: %s',
883
                static::valueToString($value),
884 12
                \implode(', ', \array_map(array('static', 'valueToString'), $values))
885
            ));
886 8
        }
887 4
    }
888 4
889 4
    /**
890
     * @param mixed  $value
891
     * @param string $subString
892 4
     * @param string $message
893
     */
894 12 View Code Duplication
    public static function contains($value, $subString, $message = '')
895
    {
896 12
        if (false === \strpos($value, $subString)) {
897
            static::reportInvalidArgument(\sprintf(
898 8
                $message ?: 'Expected a value to contain %2$s. Got: %s',
899 4
                static::valueToString($value),
900 4
                static::valueToString($subString)
901 4
            ));
902
        }
903
    }
904 4
905
    /**
906
     * @param mixed  $value
907
     * @param string $subString
908
     * @param string $message
909
     */
910 View Code Duplication
    public static function notContains($value, $subString, $message = '')
911
    {
912
        if (false !== \strpos($value, $subString)) {
913
            static::reportInvalidArgument(\sprintf(
914
                $message ?: '%2$s was not expected to be contained in a value. Got: %s',
915
                static::valueToString($value),
916
                static::valueToString($subString)
917
            ));
918
        }
919
    }
920
921
    /**
922
     * @param mixed  $value
923
     * @param string $message
924
     */
925
    public static function notWhitespaceOnly($value, $message = '')
926 8
    {
927
        if (\preg_match('/^\s*$/', $value)) {
928 8
            static::reportInvalidArgument(\sprintf(
929 4
                $message ?: 'Expected a non-whitespace string. Got: %s',
930 4
                static::valueToString($value)
931 4
            ));
932
        }
933
    }
934 4
935
    /**
936 8
     * @param mixed  $value
937
     * @param string $prefix
938 8
     * @param string $message
939 4
     */
940 4 View Code Duplication
    public static function startsWith($value, $prefix, $message = '')
941 4
    {
942 4
        if (0 !== \strpos($value, $prefix)) {
943
            static::reportInvalidArgument(\sprintf(
944
                $message ?: 'Expected a value to start with %2$s. Got: %s',
945 4
                static::valueToString($value),
946
                static::valueToString($prefix)
947 8
            ));
948
        }
949 8
    }
950 4
951 4
    /**
952 4
     * @param mixed  $value
953
     * @param string $message
954
     */
955 4
    public static function startsWithLetter($value, $message = '')
956
    {
957 8
        $valid = isset($value[0]);
958
959 8
        if ($valid) {
960 4
            $locale = \setlocale(LC_CTYPE, 0);
961 4
            \setlocale(LC_CTYPE, 'C');
962 4
            $valid = \ctype_alpha($value[0]);
963 4
            \setlocale(LC_CTYPE, $locale);
964
        }
965
966 4
        if (!$valid) {
967
            static::reportInvalidArgument(\sprintf(
968 12
                $message ?: 'Expected a value to start with a letter. Got: %s',
969
                static::valueToString($value)
970 12
            ));
971 4
        }
972 4
    }
973 4
974
    /**
975
     * @param mixed  $value
976 8
     * @param string $suffix
977
     * @param string $message
978 12
     */
979 View Code Duplication
    public static function endsWith($value, $suffix, $message = '')
980 12
    {
981 8
        if ($suffix !== \substr($value, -\strlen($suffix))) {
982 8
            static::reportInvalidArgument(\sprintf(
983 8
                $message ?: 'Expected a value to end with %2$s. Got: %s',
984
                static::valueToString($value),
985
                static::valueToString($suffix)
986 4
            ));
987
        }
988 27
    }
989
990 27
    /**
991 19
     * @param mixed  $value
992 19
     * @param mixed  $pattern
993 19
     * @param string $message
994
     */
995
    public static function regex($value, $pattern, $message = '')
996 8
    {
997
        if (!\preg_match($pattern, $value)) {
998 27
            static::reportInvalidArgument(\sprintf(
999
                $message ?: 'The value %s does not match the expected pattern.',
1000 27
                static::valueToString($value)
1001 8
            ));
1002 8
        }
1003 8
    }
1004
1005
    /**
1006 19
     * @param mixed  $value
1007
     * @param mixed  $pattern
1008 12
     * @param string $message
1009
     */
1010 12
    public static function notRegex($value, $pattern, $message = '')
1011 4
    {
1012 4
        if (\preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) {
1013 4
            static::reportInvalidArgument(\sprintf(
1014
                $message ?: 'The value %s matches the pattern %s (at offset %d).',
1015
                static::valueToString($value),
1016 8
                static::valueToString($pattern),
1017
                $matches[0][1]
1018 12
            ));
1019
        }
1020 12
    }
1021 8
1022 8
    /**
1023 8
     * @param mixed  $value
1024
     * @param string $message
1025
     */
1026 4 View Code Duplication
    public static function unicodeLetters($value, $message = '')
1027
    {
1028 8
        static::string($value);
1029
1030 8
        if (!\preg_match('/^\p{L}+$/u', $value)) {
1031 8
            static::reportInvalidArgument(\sprintf(
1032
                $message ?: 'Expected a value to contain only Unicode letters. Got: %s',
1033 8
                static::valueToString($value)
1034
            ));
1035 4
        }
1036
    }
1037 12
1038
    /**
1039 12
     * @param mixed  $value
1040 4
     * @param string $message
1041 4
     */
1042 4 View Code Duplication
    public static function alpha($value, $message = '')
1043 4
    {
1044
        $locale = \setlocale(LC_CTYPE, 0);
1045
        \setlocale(LC_CTYPE, 'C');
1046 8
        $valid = !\ctype_alpha($value);
1047
        \setlocale(LC_CTYPE, $locale);
1048 12
1049
        if ($valid) {
1050 12
            static::reportInvalidArgument(\sprintf(
1051 4
                $message ?: 'Expected a value to contain only letters. Got: %s',
1052 4
                static::valueToString($value)
1053 4
            ));
1054 4
        }
1055
    }
1056
1057 8
    /**
1058
     * @param mixed  $value
1059 20
     * @param string $message
1060
     */
1061 20 View Code Duplication
    public static function digits($value, $message = '')
1062
    {
1063 20
        $locale = \setlocale(LC_CTYPE, 0);
1064 8
        \setlocale(LC_CTYPE, 'C');
1065 8
        $valid = !\ctype_digit($value);
1066 8
        \setlocale(LC_CTYPE, $locale);
1067 8
1068 8
        if ($valid) {
1069
            static::reportInvalidArgument(\sprintf(
1070
                $message ?: 'Expected a value to contain digits only. Got: %s',
1071 12
                static::valueToString($value)
1072
            ));
1073 24
        }
1074
    }
1075 24
1076 20
    /**
1077 20
     * @param mixed  $value
1078
     * @param string $message
1079
     */
1080 4 View Code Duplication
    public static function alnum($value, $message = '')
1081
    {
1082 16
        $locale = \setlocale(LC_CTYPE, 0);
1083
        \setlocale(LC_CTYPE, 'C');
1084
        $valid = !\ctype_alnum($value);
1085 16
        \setlocale(LC_CTYPE, $locale);
1086 16
1087
        if ($valid) {
1088 12
            static::reportInvalidArgument(\sprintf(
1089 16
                $message ?: 'Expected a value to contain letters and digits only. Got: %s',
1090
                static::valueToString($value)
1091 12
            ));
1092 12
        }
1093
    }
1094
1095 4
    /**
1096
     * @param mixed  $value
1097 56
     * @param string $message
1098
     */
1099 56 View Code Duplication
    public static function lower($value, $message = '')
1100
    {
1101
        $locale = \setlocale(LC_CTYPE, 0);
1102
        \setlocale(LC_CTYPE, 'C');
1103 56
        $valid = !\ctype_lower($value);
1104 4
        \setlocale(LC_CTYPE, $locale);
1105
1106
        if ($valid) {
1107 52
            static::reportInvalidArgument(\sprintf(
1108 20
                $message ?: 'Expected a value to contain lowercase characters only. Got: %s',
1109 20
                static::valueToString($value)
1110 20
            ));
1111
        }
1112
    }
1113 32
1114
    /**
1115 24
     * @param mixed  $value
1116
     * @param string $message
1117 24
     */
1118 View Code Duplication
    public static function upper($value, $message = '')
1119 24
    {
1120
        $locale = \setlocale(LC_CTYPE, 0);
1121
        \setlocale(LC_CTYPE, 'C');
1122 24
        $valid = !\ctype_upper($value);
1123 24
        \setlocale(LC_CTYPE, $locale);
1124 20
1125 20
        if ($valid) {
1126 20
            static::reportInvalidArgument(\sprintf(
1127
                $message ?: 'Expected a value to contain uppercase characters only. Got: %s',
1128 4
                static::valueToString($value)
1129 4
            ));
1130 4
        }
1131 4
    }
1132
1133
    /**
1134
     * @param mixed  $value
1135 8
     * @param mixed  $length
1136 8
     * @param string $message
1137 8
     */
1138 8
    public static function length($value, $length, $message = '')
1139
    {
1140
        if ($length !== static::strlen($value)) {
1141
            static::reportInvalidArgument(\sprintf(
1142 1383
                $message ?: 'Expected a value to contain %2$s characters. Got: %s',
1143
                static::valueToString($value),
1144 1383
                $length
1145 514
            ));
1146 421
        }
1147 421
    }
1148
1149
    /**
1150 296
     * Inclusive min.
1151
     *
1152
     * @param mixed  $value
1153 869
     * @param mixed  $min
1154 868
     * @param string $message
1155
     */
1156 868
    public static function minLength($value, $min, $message = '')
1157 868
    {
1158
        if (static::strlen($value) < $min) {
1159 868
            static::reportInvalidArgument(\sprintf(
1160 868
                $message ?: 'Expected a value to contain at least %2$s characters. Got: %s',
1161
                static::valueToString($value),
1162 868
                $min
1163
            ));
1164
        }
1165 412
    }
1166
1167
    /**
1168 1
     * Inclusive max.
1169
     *
1170
     * @param mixed  $value
1171 694
     * @param mixed  $max
1172
     * @param string $message
1173 694
     */
1174 20
    public static function maxLength($value, $max, $message = '')
1175
    {
1176
        if (static::strlen($value) > $max) {
1177 676
            static::reportInvalidArgument(\sprintf(
1178 15
                $message ?: 'Expected a value to contain at most %2$s characters. Got: %s',
1179
                static::valueToString($value),
1180
                $max
1181 666
            ));
1182 25
        }
1183
    }
1184
1185 641
    /**
1186 13
     * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion.
1187
     *
1188
     * @param mixed  $value
1189 628
     * @param mixed  $min
1190 2
     * @param mixed  $max
1191 1
     * @param string $message
1192
     */
1193 View Code Duplication
    public static function lengthBetween($value, $min, $max, $message = '')
1194 1
    {
1195
        $length = static::strlen($value);
1196
1197 627
        if ($length < $min || $length > $max) {
1198 1
            static::reportInvalidArgument(\sprintf(
1199
                $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s',
1200
                static::valueToString($value),
1201 627
                $min,
1202 525
                $max
1203
            ));
1204
        }
1205 110
    }
1206
1207
    /**
1208 169
     * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file.
1209
     *
1210 169
     * @param mixed  $value
1211
     * @param string $message
1212
     */
1213 168 View Code Duplication
    public static function fileExists($value, $message = '')
1214
    {
1215 168
        static::string($value);
1216
1217
        if (!\file_exists($value)) {
1218
            static::reportInvalidArgument(\sprintf(
1219 168
                $message ?: 'The file %s does not exist.',
1220
                static::valueToString($value)
1221
            ));
1222
        }
1223 168
    }
1224
1225
    /**
1226 918
     * @param mixed  $value
1227
     * @param string $message
1228 918
     */
1229 View Code Duplication
    public static function file($value, $message = '')
1230
    {
1231
        static::fileExists($value, $message);
1232
1233
        if (!\is_file($value)) {
1234
            static::reportInvalidArgument(\sprintf(
1235
                $message ?: 'The path %s is not a file.',
1236
                static::valueToString($value)
1237
            ));
1238
        }
1239
    }
1240
1241
    /**
1242
     * @param mixed  $value
1243
     * @param string $message
1244
     */
1245 View Code Duplication
    public static function directory($value, $message = '')
1246
    {
1247
        static::fileExists($value, $message);
1248
1249
        if (!\is_dir($value)) {
1250
            static::reportInvalidArgument(\sprintf(
1251
                $message ?: 'The path %s is no directory.',
1252
                static::valueToString($value)
1253
            ));
1254
        }
1255
    }
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
    public static function classExists($value, $message = '')
1292
    {
1293
        if (!\class_exists($value)) {
1294
            static::reportInvalidArgument(\sprintf(
1295
                $message ?: 'Expected an existing class name. Got: %s',
1296
                static::valueToString($value)
1297
            ));
1298
        }
1299
    }
1300
1301
    /**
1302
     * @param mixed         $value
1303
     * @param string|object $class
1304
     * @param string        $message
1305
     */
1306
    public static function subclassOf($value, $class, $message = '')
1307
    {
1308
        if (!\is_subclass_of($value, $class)) {
1309
            static::reportInvalidArgument(\sprintf(
1310
                $message ?: 'Expected a sub-class of %2$s. Got: %s',
1311
                static::valueToString($value),
1312
                static::valueToString($class)
1313
            ));
1314
        }
1315
    }
1316
1317
    /**
1318
     * @psalm-assert class-string $value
1319
     *
1320
     * @param mixed  $value
1321
     * @param string $message
1322
     */
1323
    public static function interfaceExists($value, $message = '')
1324
    {
1325
        if (!\interface_exists($value)) {
1326
            static::reportInvalidArgument(\sprintf(
1327
                $message ?: 'Expected an existing interface name. got %s',
1328
                static::valueToString($value)
1329
            ));
1330
        }
1331
    }
1332
1333
    /**
1334
     * @param mixed  $value
1335
     * @param mixed  $interface
1336
     * @param string $message
1337
     */
1338 View Code Duplication
    public static function implementsInterface($value, $interface, $message = '')
1339
    {
1340
        if (!\in_array($interface, \class_implements($value))) {
1341
            static::reportInvalidArgument(\sprintf(
1342
                $message ?: 'Expected an implementation of %2$s. Got: %s',
1343
                static::valueToString($value),
1344
                static::valueToString($interface)
1345
            ));
1346
        }
1347
    }
1348
1349
    /**
1350
     * @param string|object $classOrObject
1351
     * @param mixed         $property
1352
     * @param string        $message
1353
     */
1354 View Code Duplication
    public static function propertyExists($classOrObject, $property, $message = '')
1355
    {
1356
        if (!\property_exists($classOrObject, $property)) {
1357
            static::reportInvalidArgument(\sprintf(
1358
                $message ?: 'Expected the property %s to exist.',
1359
                static::valueToString($property)
1360
            ));
1361
        }
1362
    }
1363
1364
    /**
1365
     * @param string|object $classOrObject
1366
     * @param mixed         $property
1367
     * @param string        $message
1368
     */
1369 View Code Duplication
    public static function propertyNotExists($classOrObject, $property, $message = '')
1370
    {
1371
        if (\property_exists($classOrObject, $property)) {
1372
            static::reportInvalidArgument(\sprintf(
1373
                $message ?: 'Expected the property %s to not exist.',
1374
                static::valueToString($property)
1375
            ));
1376
        }
1377
    }
1378
1379
    /**
1380
     * @param string|object $classOrObject
1381
     * @param mixed         $method
1382
     * @param string        $message
1383
     */
1384 View Code Duplication
    public static function methodExists($classOrObject, $method, $message = '')
1385
    {
1386
        if (!\method_exists($classOrObject, $method)) {
1387
            static::reportInvalidArgument(\sprintf(
1388
                $message ?: 'Expected the method %s to exist.',
1389
                static::valueToString($method)
1390
            ));
1391
        }
1392
    }
1393
1394
    /**
1395
     * @param string|object $classOrObject
1396
     * @param mixed         $method
1397
     * @param string        $message
1398
     */
1399 View Code Duplication
    public static function methodNotExists($classOrObject, $method, $message = '')
1400
    {
1401
        if (\method_exists($classOrObject, $method)) {
1402
            static::reportInvalidArgument(\sprintf(
1403
                $message ?: 'Expected the method %s to not exist.',
1404
                static::valueToString($method)
1405
            ));
1406
        }
1407
    }
1408
1409
    /**
1410
     * @param array      $array
1411
     * @param string|int $key
1412
     * @param string     $message
1413
     */
1414 View Code Duplication
    public static function keyExists($array, $key, $message = '')
1415
    {
1416
        if (!(isset($array[$key]) || \array_key_exists($key, $array))) {
1417
            static::reportInvalidArgument(\sprintf(
1418
                $message ?: 'Expected the key %s to exist.',
1419
                static::valueToString($key)
1420
            ));
1421
        }
1422
    }
1423
1424
    /**
1425
     * @param array      $array
1426
     * @param string|int $key
1427
     * @param string     $message
1428
     */
1429 View Code Duplication
    public static function keyNotExists($array, $key, $message = '')
1430
    {
1431
        if (isset($array[$key]) || \array_key_exists($key, $array)) {
1432
            static::reportInvalidArgument(\sprintf(
1433
                $message ?: 'Expected the key %s to not exist.',
1434
                static::valueToString($key)
1435
            ));
1436
        }
1437
    }
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
    public static function count($array, $number, $message = '')
1447
    {
1448
        static::eq(
1449
            \count($array),
1450
            $number,
1451
            $message ?: \sprintf('Expected an array to contain %d elements. Got: %d.', $number, \count($array))
1452
        );
1453
    }
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 View Code Duplication
    public static function minCount($array, $min, $message = '')
1463
    {
1464
        if (\count($array) < $min) {
1465
            static::reportInvalidArgument(\sprintf(
1466
                $message ?: 'Expected an array to contain at least %2$d elements. Got: %d',
1467
                \count($array),
1468
                $min
1469
            ));
1470
        }
1471
    }
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 View Code Duplication
    public static function maxCount($array, $max, $message = '')
1481
    {
1482
        if (\count($array) > $max) {
1483
            static::reportInvalidArgument(\sprintf(
1484
                $message ?: 'Expected an array to contain at most %2$d elements. Got: %d',
1485
                \count($array),
1486
                $max
1487
            ));
1488
        }
1489
    }
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
    public static function countBetween($array, $min, $max, $message = '')
1500
    {
1501
        $count = \count($array);
1502
1503
        if ($count < $min || $count > $max) {
1504
            static::reportInvalidArgument(\sprintf(
1505
                $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d',
1506
                $count,
1507
                $min,
1508
                $max
1509
            ));
1510
        }
1511
    }
1512
1513
    /**
1514
     * @param mixed  $array
1515
     * @param string $message
1516
     */
1517
    public static function isList($array, $message = '')
1518
    {
1519
        if (!\is_array($array) || !$array || \array_keys($array) !== \range(0, \count($array) - 1)) {
1520
            static::reportInvalidArgument(
1521
                $message ?: 'Expected list - non-associative array.'
1522
            );
1523
        }
1524
    }
1525
1526
    /**
1527
     * @param mixed  $array
1528
     * @param string $message
1529
     */
1530
    public static function isMap($array, $message = '')
1531
    {
1532
        if (
1533
            !\is_array($array) ||
1534
            !$array ||
1535
            \array_keys($array) !== \array_filter(\array_keys($array), function ($key) {
1536
                return \is_string($key);
1537
            })
1538
        ) {
1539
            static::reportInvalidArgument(
1540
                $message ?: 'Expected map - associative array with string keys.'
1541
            );
1542
        }
1543
    }
1544
1545
    /**
1546
     * @param mixed  $value
1547
     * @param string $message
1548
     */
1549
    public static function uuid($value, $message = '')
1550
    {
1551
        $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
        if ('00000000-0000-0000-0000-000000000000' === $value) {
1556
            return;
1557
        }
1558
1559
        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
            static::reportInvalidArgument(\sprintf(
1561
                $message ?: 'Value %s is not a valid UUID.',
1562
                static::valueToString($value)
1563
            ));
1564
        }
1565
    }
1566
1567
    /**
1568
     * @param Closure       $expression
1569
     * @param string|object $class
1570
     * @param string        $message
1571
     */
1572
    public static function throws(Closure $expression, $class = 'Exception', $message = '')
1573
    {
1574
        static::string($class);
1575
1576
        $actual = 'none';
1577
1578
        try {
1579
            $expression();
1580
        } catch (Exception $e) {
1581
            $actual = \get_class($e);
1582
            if ($e instanceof $class) {
1583
                return;
1584
            }
1585
        } catch (Throwable $e) {
1586
            $actual = \get_class($e);
1587
            if ($e instanceof $class) {
1588
                return;
1589
            }
1590
        }
1591
1592
        static::reportInvalidArgument($message ?: \sprintf(
1593
            'Expected to throw "%s", got "%s"',
1594
            $class,
1595
            $actual
1596
        ));
1597
    }
1598
1599
    public static function __callStatic($name, $arguments)
1600
    {
1601
        if ('nullOr' === \substr($name, 0, 6)) {
1602
            if (null !== $arguments[0]) {
1603
                $method = \lcfirst(\substr($name, 6));
1604
                \call_user_func_array(array('static', $method), $arguments);
1605
            }
1606
1607
            return;
1608
        }
1609
1610
        if ('all' === \substr($name, 0, 3)) {
1611
            static::isIterable($arguments[0]);
1612
1613
            $method = \lcfirst(\substr($name, 3));
1614
            $args = $arguments;
1615
1616
            foreach ($arguments[0] as $entry) {
1617
                $args[0] = $entry;
1618
1619
                \call_user_func_array(array('static', $method), $args);
1620
            }
1621
1622
            return;
1623
        }
1624
1625
        throw new BadMethodCallException('No such method: '.$name);
1626
    }
1627
1628
    /**
1629
     * @param mixed $value
1630
     *
1631
     * @return string
1632
     */
1633
    protected static function valueToString($value)
1634
    {
1635
        if (null === $value) {
1636
            return 'null';
1637
        }
1638
1639
        if (true === $value) {
1640
            return 'true';
1641
        }
1642
1643
        if (false === $value) {
1644
            return 'false';
1645
        }
1646
1647
        if (\is_array($value)) {
1648
            return 'array';
1649
        }
1650
1651
        if (\is_object($value)) {
1652
            if (\method_exists($value, '__toString')) {
1653
                return \get_class($value).': '.self::valueToString($value->__toString());
1654
            }
1655
1656
            return \get_class($value);
1657
        }
1658
1659
        if (\is_resource($value)) {
1660
            return 'resource';
1661
        }
1662
1663
        if (\is_string($value)) {
1664
            return '"'.$value.'"';
1665
        }
1666
1667
        return (string) $value;
1668
    }
1669
1670
    /**
1671
     * @param mixed $value
1672
     *
1673
     * @return string
1674
     */
1675
    protected static function typeToString($value)
1676
    {
1677
        return \is_object($value) ? \get_class($value) : \gettype($value);
1678
    }
1679
1680
    protected static function strlen($value)
1681
    {
1682
        if (!\function_exists('mb_detect_encoding')) {
1683
            return \strlen($value);
1684
        }
1685
1686
        if (false === $encoding = \mb_detect_encoding($value)) {
1687
            return \strlen($value);
1688
        }
1689
1690
        return \mb_strlen($value, $encoding);
1691
    }
1692
1693
    /**
1694
     * @param string $message
1695
     */
1696
    protected static function reportInvalidArgument($message)
1697
    {
1698
        throw new InvalidArgumentException($message);
1699
    }
1700
1701
    private function __construct()
1702
    {
1703
    }
1704
}
1705