Failed Conditions
Pull Request — master (#118)
by Gert de
16:40
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 $value
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
     * @psalm-assert iterable $value
410 12
     *
411 12
     * @deprecated use "isIterable" or "isInstanceOf" instead
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
     * @psalm-assert !numeric $value
1024
     *
1025
     * @param mixed  $value
1026 4
     * @param string $message
1027
     */
1028 8 View Code Duplication
    public static function unicodeLetters($value, $message = '')
1029
    {
1030 8
        static::string($value);
1031 8
1032
        if (!\preg_match('/^\p{L}+$/u', $value)) {
1033 8
            static::reportInvalidArgument(\sprintf(
1034
                $message ?: 'Expected a value to contain only Unicode letters. Got: %s',
1035 4
                static::valueToString($value)
1036
            ));
1037 12
        }
1038
    }
1039 12
1040 4
    /**
1041 4
     * @param mixed  $value
1042 4
     * @param string $message
1043 4
     */
1044 View Code Duplication
    public static function alpha($value, $message = '')
1045
    {
1046 8
        $locale = \setlocale(LC_CTYPE, 0);
1047
        \setlocale(LC_CTYPE, 'C');
1048 12
        $valid = !\ctype_alpha($value);
1049
        \setlocale(LC_CTYPE, $locale);
1050 12
1051 4
        if ($valid) {
1052 4
            static::reportInvalidArgument(\sprintf(
1053 4
                $message ?: 'Expected a value to contain only letters. Got: %s',
1054 4
                static::valueToString($value)
1055
            ));
1056
        }
1057 8
    }
1058
1059 20
    /**
1060
     * @param mixed  $value
1061 20
     * @param string $message
1062
     */
1063 20 View Code Duplication
    public static function digits($value, $message = '')
1064 8
    {
1065 8
        $locale = \setlocale(LC_CTYPE, 0);
1066 8
        \setlocale(LC_CTYPE, 'C');
1067 8
        $valid = !\ctype_digit($value);
1068 8
        \setlocale(LC_CTYPE, $locale);
1069
1070
        if ($valid) {
1071 12
            static::reportInvalidArgument(\sprintf(
1072
                $message ?: 'Expected a value to contain digits only. Got: %s',
1073 24
                static::valueToString($value)
1074
            ));
1075 24
        }
1076 20
    }
1077 20
1078
    /**
1079
     * @param mixed  $value
1080 4
     * @param string $message
1081
     */
1082 16 View Code Duplication
    public static function alnum($value, $message = '')
1083
    {
1084
        $locale = \setlocale(LC_CTYPE, 0);
1085 16
        \setlocale(LC_CTYPE, 'C');
1086 16
        $valid = !\ctype_alnum($value);
1087
        \setlocale(LC_CTYPE, $locale);
1088 12
1089 16
        if ($valid) {
1090
            static::reportInvalidArgument(\sprintf(
1091 12
                $message ?: 'Expected a value to contain letters and digits only. Got: %s',
1092 12
                static::valueToString($value)
1093
            ));
1094
        }
1095 4
    }
1096
1097 56
    /**
1098
     * @param mixed  $value
1099 56
     * @param string $message
1100
     */
1101 View Code Duplication
    public static function lower($value, $message = '')
1102
    {
1103 56
        $locale = \setlocale(LC_CTYPE, 0);
1104 4
        \setlocale(LC_CTYPE, 'C');
1105
        $valid = !\ctype_lower($value);
1106
        \setlocale(LC_CTYPE, $locale);
1107 52
1108 20
        if ($valid) {
1109 20
            static::reportInvalidArgument(\sprintf(
1110 20
                $message ?: 'Expected a value to contain lowercase characters only. Got: %s',
1111
                static::valueToString($value)
1112
            ));
1113 32
        }
1114
    }
1115 24
1116
    /**
1117 24
     * @param mixed  $value
1118
     * @param string $message
1119 24
     */
1120 View Code Duplication
    public static function upper($value, $message = '')
1121
    {
1122 24
        $locale = \setlocale(LC_CTYPE, 0);
1123 24
        \setlocale(LC_CTYPE, 'C');
1124 20
        $valid = !\ctype_upper($value);
1125 20
        \setlocale(LC_CTYPE, $locale);
1126 20
1127
        if ($valid) {
1128 4
            static::reportInvalidArgument(\sprintf(
1129 4
                $message ?: 'Expected a value to contain uppercase characters only. Got: %s',
1130 4
                static::valueToString($value)
1131 4
            ));
1132
        }
1133
    }
1134
1135 8
    /**
1136 8
     * @param mixed  $value
1137 8
     * @param mixed  $length
1138 8
     * @param string $message
1139
     */
1140
    public static function length($value, $length, $message = '')
1141
    {
1142 1383
        if ($length !== static::strlen($value)) {
1143
            static::reportInvalidArgument(\sprintf(
1144 1383
                $message ?: 'Expected a value to contain %2$s characters. Got: %s',
1145 514
                static::valueToString($value),
1146 421
                $length
1147 421
            ));
1148
        }
1149
    }
1150 296
1151
    /**
1152
     * Inclusive min.
1153 869
     *
1154 868
     * @param mixed  $value
1155
     * @param mixed  $min
1156 868
     * @param string $message
1157 868
     */
1158
    public static function minLength($value, $min, $message = '')
1159 868
    {
1160 868
        if (static::strlen($value) < $min) {
1161
            static::reportInvalidArgument(\sprintf(
1162 868
                $message ?: 'Expected a value to contain at least %2$s characters. Got: %s',
1163
                static::valueToString($value),
1164
                $min
1165 412
            ));
1166
        }
1167
    }
1168 1
1169
    /**
1170
     * Inclusive max.
1171 694
     *
1172
     * @param mixed  $value
1173 694
     * @param mixed  $max
1174 20
     * @param string $message
1175
     */
1176
    public static function maxLength($value, $max, $message = '')
1177 676
    {
1178 15
        if (static::strlen($value) > $max) {
1179
            static::reportInvalidArgument(\sprintf(
1180
                $message ?: 'Expected a value to contain at most %2$s characters. Got: %s',
1181 666
                static::valueToString($value),
1182 25
                $max
1183
            ));
1184
        }
1185 641
    }
1186 13
1187
    /**
1188
     * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion.
1189 628
     *
1190 2
     * @param mixed  $value
1191 1
     * @param mixed  $min
1192
     * @param mixed  $max
1193
     * @param string $message
1194 1
     */
1195 View Code Duplication
    public static function lengthBetween($value, $min, $max, $message = '')
1196
    {
1197 627
        $length = static::strlen($value);
1198 1
1199
        if ($length < $min || $length > $max) {
1200
            static::reportInvalidArgument(\sprintf(
1201 627
                $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s',
1202 525
                static::valueToString($value),
1203
                $min,
1204
                $max
1205 110
            ));
1206
        }
1207
    }
1208 169
1209
    /**
1210 169
     * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file.
1211
     *
1212
     * @param mixed  $value
1213 168
     * @param string $message
1214
     */
1215 168 View Code Duplication
    public static function fileExists($value, $message = '')
1216
    {
1217
        static::string($value);
1218
1219 168
        if (!\file_exists($value)) {
1220
            static::reportInvalidArgument(\sprintf(
1221
                $message ?: 'The file %s does not exist.',
1222
                static::valueToString($value)
1223 168
            ));
1224
        }
1225
    }
1226 918
1227
    /**
1228 918
     * @param mixed  $value
1229
     * @param string $message
1230
     */
1231 View Code Duplication
    public static function file($value, $message = '')
1232
    {
1233
        static::fileExists($value, $message);
1234
1235
        if (!\is_file($value)) {
1236
            static::reportInvalidArgument(\sprintf(
1237
                $message ?: 'The path %s is not a file.',
1238
                static::valueToString($value)
1239
            ));
1240
        }
1241
    }
1242
1243
    /**
1244
     * @param mixed  $value
1245
     * @param string $message
1246
     */
1247 View Code Duplication
    public static function directory($value, $message = '')
1248
    {
1249
        static::fileExists($value, $message);
1250
1251
        if (!\is_dir($value)) {
1252
            static::reportInvalidArgument(\sprintf(
1253
                $message ?: 'The path %s is no directory.',
1254
                static::valueToString($value)
1255
            ));
1256
        }
1257
    }
1258
1259
    /**
1260
     * @param mixed  $value
1261
     * @param string $message
1262
     */
1263
    public static function readable($value, $message = '')
1264
    {
1265
        if (!\is_readable($value)) {
1266
            static::reportInvalidArgument(\sprintf(
1267
                $message ?: 'The path %s is not readable.',
1268
                static::valueToString($value)
1269
            ));
1270
        }
1271
    }
1272
1273
    /**
1274
     * @param mixed  $value
1275
     * @param string $message
1276
     */
1277
    public static function writable($value, $message = '')
1278
    {
1279
        if (!\is_writable($value)) {
1280
            static::reportInvalidArgument(\sprintf(
1281
                $message ?: 'The path %s is not writable.',
1282
                static::valueToString($value)
1283
            ));
1284
        }
1285
    }
1286
1287
    /**
1288
     * @psalm-assert class-string $value
1289
     *
1290
     * @param mixed  $value
1291
     * @param string $message
1292
     */
1293
    public static function classExists($value, $message = '')
1294
    {
1295
        if (!\class_exists($value)) {
1296
            static::reportInvalidArgument(\sprintf(
1297
                $message ?: 'Expected an existing class name. Got: %s',
1298
                static::valueToString($value)
1299
            ));
1300
        }
1301
    }
1302
1303
    /**
1304
     * @param mixed         $value
1305
     * @param string|object $class
1306
     * @param string        $message
1307
     */
1308
    public static function subclassOf($value, $class, $message = '')
1309
    {
1310
        if (!\is_subclass_of($value, $class)) {
1311
            static::reportInvalidArgument(\sprintf(
1312
                $message ?: 'Expected a sub-class of %2$s. Got: %s',
1313
                static::valueToString($value),
1314
                static::valueToString($class)
1315
            ));
1316
        }
1317
    }
1318
1319
    /**
1320
     * @psalm-assert class-string $value
1321
     *
1322
     * @param mixed  $value
1323
     * @param string $message
1324
     */
1325
    public static function interfaceExists($value, $message = '')
1326
    {
1327
        if (!\interface_exists($value)) {
1328
            static::reportInvalidArgument(\sprintf(
1329
                $message ?: 'Expected an existing interface name. got %s',
1330
                static::valueToString($value)
1331
            ));
1332
        }
1333
    }
1334
1335
    /**
1336
     * @param mixed  $value
1337
     * @param mixed  $interface
1338
     * @param string $message
1339
     */
1340 View Code Duplication
    public static function implementsInterface($value, $interface, $message = '')
1341
    {
1342
        if (!\in_array($interface, \class_implements($value))) {
1343
            static::reportInvalidArgument(\sprintf(
1344
                $message ?: 'Expected an implementation of %2$s. Got: %s',
1345
                static::valueToString($value),
1346
                static::valueToString($interface)
1347
            ));
1348
        }
1349
    }
1350
1351
    /**
1352
     * @param string|object $classOrObject
1353
     * @param mixed         $property
1354
     * @param string        $message
1355
     */
1356 View Code Duplication
    public static function propertyExists($classOrObject, $property, $message = '')
1357
    {
1358
        if (!\property_exists($classOrObject, $property)) {
1359
            static::reportInvalidArgument(\sprintf(
1360
                $message ?: 'Expected the property %s to exist.',
1361
                static::valueToString($property)
1362
            ));
1363
        }
1364
    }
1365
1366
    /**
1367
     * @param string|object $classOrObject
1368
     * @param mixed         $property
1369
     * @param string        $message
1370
     */
1371 View Code Duplication
    public static function propertyNotExists($classOrObject, $property, $message = '')
1372
    {
1373
        if (\property_exists($classOrObject, $property)) {
1374
            static::reportInvalidArgument(\sprintf(
1375
                $message ?: 'Expected the property %s to not exist.',
1376
                static::valueToString($property)
1377
            ));
1378
        }
1379
    }
1380
1381
    /**
1382
     * @param string|object $classOrObject
1383
     * @param mixed         $method
1384
     * @param string        $message
1385
     */
1386 View Code Duplication
    public static function methodExists($classOrObject, $method, $message = '')
1387
    {
1388
        if (!\method_exists($classOrObject, $method)) {
1389
            static::reportInvalidArgument(\sprintf(
1390
                $message ?: 'Expected the method %s to exist.',
1391
                static::valueToString($method)
1392
            ));
1393
        }
1394
    }
1395
1396
    /**
1397
     * @param string|object $classOrObject
1398
     * @param mixed         $method
1399
     * @param string        $message
1400
     */
1401 View Code Duplication
    public static function methodNotExists($classOrObject, $method, $message = '')
1402
    {
1403
        if (\method_exists($classOrObject, $method)) {
1404
            static::reportInvalidArgument(\sprintf(
1405
                $message ?: 'Expected the method %s to not exist.',
1406
                static::valueToString($method)
1407
            ));
1408
        }
1409
    }
1410
1411
    /**
1412
     * @param array      $array
1413
     * @param string|int $key
1414
     * @param string     $message
1415
     */
1416 View Code Duplication
    public static function keyExists($array, $key, $message = '')
1417
    {
1418
        if (!(isset($array[$key]) || \array_key_exists($key, $array))) {
1419
            static::reportInvalidArgument(\sprintf(
1420
                $message ?: 'Expected the key %s to exist.',
1421
                static::valueToString($key)
1422
            ));
1423
        }
1424
    }
1425
1426
    /**
1427
     * @param array      $array
1428
     * @param string|int $key
1429
     * @param string     $message
1430
     */
1431 View Code Duplication
    public static function keyNotExists($array, $key, $message = '')
1432
    {
1433
        if (isset($array[$key]) || \array_key_exists($key, $array)) {
1434
            static::reportInvalidArgument(\sprintf(
1435
                $message ?: 'Expected the key %s to not exist.',
1436
                static::valueToString($key)
1437
            ));
1438
        }
1439
    }
1440
1441
    /**
1442
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1443
     *
1444
     * @param mixed  $array
1445
     * @param mixed  $number
1446
     * @param string $message
1447
     */
1448
    public static function count($array, $number, $message = '')
1449
    {
1450
        static::eq(
1451
            \count($array),
1452
            $number,
1453
            $message ?: \sprintf('Expected an array to contain %d elements. Got: %d.', $number, \count($array))
1454
        );
1455
    }
1456
1457
    /**
1458
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1459
     *
1460
     * @param mixed  $array
1461
     * @param mixed  $min
1462
     * @param string $message
1463
     */
1464 View Code Duplication
    public static function minCount($array, $min, $message = '')
1465
    {
1466
        if (\count($array) < $min) {
1467
            static::reportInvalidArgument(\sprintf(
1468
                $message ?: 'Expected an array to contain at least %2$d elements. Got: %d',
1469
                \count($array),
1470
                $min
1471
            ));
1472
        }
1473
    }
1474
1475
    /**
1476
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1477
     *
1478
     * @param mixed  $array
1479
     * @param mixed  $max
1480
     * @param string $message
1481
     */
1482 View Code Duplication
    public static function maxCount($array, $max, $message = '')
1483
    {
1484
        if (\count($array) > $max) {
1485
            static::reportInvalidArgument(\sprintf(
1486
                $message ?: 'Expected an array to contain at most %2$d elements. Got: %d',
1487
                \count($array),
1488
                $max
1489
            ));
1490
        }
1491
    }
1492
1493
    /**
1494
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1495
     *
1496
     * @param mixed  $array
1497
     * @param mixed  $min
1498
     * @param mixed  $max
1499
     * @param string $message
1500
     */
1501
    public static function countBetween($array, $min, $max, $message = '')
1502
    {
1503
        $count = \count($array);
1504
1505
        if ($count < $min || $count > $max) {
1506
            static::reportInvalidArgument(\sprintf(
1507
                $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d',
1508
                $count,
1509
                $min,
1510
                $max
1511
            ));
1512
        }
1513
    }
1514
1515
    /**
1516
     * @param mixed  $array
1517
     * @param string $message
1518
     */
1519
    public static function isList($array, $message = '')
1520
    {
1521
        if (!\is_array($array) || !$array || \array_keys($array) !== \range(0, \count($array) - 1)) {
1522
            static::reportInvalidArgument(
1523
                $message ?: 'Expected list - non-associative array.'
1524
            );
1525
        }
1526
    }
1527
1528
    /**
1529
     * @param mixed  $array
1530
     * @param string $message
1531
     */
1532
    public static function isMap($array, $message = '')
1533
    {
1534
        if (
1535
            !\is_array($array) ||
1536
            !$array ||
1537
            \array_keys($array) !== \array_filter(\array_keys($array), function ($key) {
1538
                return \is_string($key);
1539
            })
1540
        ) {
1541
            static::reportInvalidArgument(
1542
                $message ?: 'Expected map - associative array with string keys.'
1543
            );
1544
        }
1545
    }
1546
1547
    /**
1548
     * @param mixed  $value
1549
     * @param string $message
1550
     */
1551
    public static function uuid($value, $message = '')
1552
    {
1553
        $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
1554
1555
        // The nil UUID is special form of UUID that is specified to have all
1556
        // 128 bits set to zero.
1557
        if ('00000000-0000-0000-0000-000000000000' === $value) {
1558
            return;
1559
        }
1560
1561
        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)) {
1562
            static::reportInvalidArgument(\sprintf(
1563
                $message ?: 'Value %s is not a valid UUID.',
1564
                static::valueToString($value)
1565
            ));
1566
        }
1567
    }
1568
1569
    /**
1570
     * @param Closure       $expression
1571
     * @param string|object $class
1572
     * @param string        $message
1573
     */
1574
    public static function throws(Closure $expression, $class = 'Exception', $message = '')
1575
    {
1576
        static::string($class);
1577
1578
        $actual = 'none';
1579
1580
        try {
1581
            $expression();
1582
        } catch (Exception $e) {
1583
            $actual = \get_class($e);
1584
            if ($e instanceof $class) {
1585
                return;
1586
            }
1587
        } catch (Throwable $e) {
1588
            $actual = \get_class($e);
1589
            if ($e instanceof $class) {
1590
                return;
1591
            }
1592
        }
1593
1594
        static::reportInvalidArgument($message ?: \sprintf(
1595
            'Expected to throw "%s", got "%s"',
1596
            $class,
1597
            $actual
1598
        ));
1599
    }
1600
1601
    public static function __callStatic($name, $arguments)
1602
    {
1603
        if ('nullOr' === \substr($name, 0, 6)) {
1604
            if (null !== $arguments[0]) {
1605
                $method = \lcfirst(\substr($name, 6));
1606
                \call_user_func_array(array('static', $method), $arguments);
1607
            }
1608
1609
            return;
1610
        }
1611
1612
        if ('all' === \substr($name, 0, 3)) {
1613
            static::isIterable($arguments[0]);
1614
1615
            $method = \lcfirst(\substr($name, 3));
1616
            $args = $arguments;
1617
1618
            foreach ($arguments[0] as $entry) {
1619
                $args[0] = $entry;
1620
1621
                \call_user_func_array(array('static', $method), $args);
1622
            }
1623
1624
            return;
1625
        }
1626
1627
        throw new BadMethodCallException('No such method: '.$name);
1628
    }
1629
1630
    /**
1631
     * @param mixed $value
1632
     *
1633
     * @return string
1634
     */
1635
    protected static function valueToString($value)
1636
    {
1637
        if (null === $value) {
1638
            return 'null';
1639
        }
1640
1641
        if (true === $value) {
1642
            return 'true';
1643
        }
1644
1645
        if (false === $value) {
1646
            return 'false';
1647
        }
1648
1649
        if (\is_array($value)) {
1650
            return 'array';
1651
        }
1652
1653
        if (\is_object($value)) {
1654
            if (\method_exists($value, '__toString')) {
1655
                return \get_class($value).': '.self::valueToString($value->__toString());
1656
            }
1657
1658
            return \get_class($value);
1659
        }
1660
1661
        if (\is_resource($value)) {
1662
            return 'resource';
1663
        }
1664
1665
        if (\is_string($value)) {
1666
            return '"'.$value.'"';
1667
        }
1668
1669
        return (string) $value;
1670
    }
1671
1672
    /**
1673
     * @param mixed $value
1674
     *
1675
     * @return string
1676
     */
1677
    protected static function typeToString($value)
1678
    {
1679
        return \is_object($value) ? \get_class($value) : \gettype($value);
1680
    }
1681
1682
    protected static function strlen($value)
1683
    {
1684
        if (!\function_exists('mb_detect_encoding')) {
1685
            return \strlen($value);
1686
        }
1687
1688
        if (false === $encoding = \mb_detect_encoding($value)) {
1689
            return \strlen($value);
1690
        }
1691
1692
        return \mb_strlen($value, $encoding);
1693
    }
1694
1695
    /**
1696
     * @param string $message
1697
     */
1698
    protected static function reportInvalidArgument($message)
1699
    {
1700
        throw new InvalidArgumentException($message);
1701
    }
1702
1703
    private function __construct()
1704
    {
1705
    }
1706
}
1707