Failed Conditions
Pull Request — master (#118)
by Gert de
15:57
created

Assert::oneOf()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 5
cts 5
cp 1
rs 9.9332
c 0
b 0
f 0
cc 3
nc 2
nop 3
crap 3
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
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
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(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
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)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $array of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
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 ||
0 ignored issues
show
Bug Best Practice introduced by
The expression $array of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
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) {
0 ignored issues
show
Bug introduced by
The class Throwable does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
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