Failed Conditions
Pull Request — master (#106)
by Simon
02:53
created

Assert::natural()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.9666
c 0
b 0
f 0
cc 4
nc 2
nop 2
crap 4
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 ResourceBundle;
21
use SimpleXMLElement;
22
use Throwable;
23
use Traversable;
24
25
/**
26
 * Efficient assertions to validate the input/output of your methods.
27
 *
28
 * @method static void nullOrString($value, $message = '')
29
 * @method static void nullOrStringNotEmpty($value, $message = '')
30
 * @method static void nullOrInteger($value, $message = '')
31
 * @method static void nullOrIntegerish($value, $message = '')
32
 * @method static void nullOrFloat($value, $message = '')
33
 * @method static void nullOrNumeric($value, $message = '')
34
 * @method static void nullOrNatural($value, $message = '')
35
 * @method static void nullOrBoolean($value, $message = '')
36
 * @method static void nullOrScalar($value, $message = '')
37
 * @method static void nullOrObject($value, $message = '')
38
 * @method static void nullOrResource($value, $type = null, $message = '')
39
 * @method static void nullOrIsCallable($value, $message = '')
40
 * @method static void nullOrIsArray($value, $message = '')
41
 * @method static void nullOrIsTraversable($value, $message = '')
42
 * @method static void nullOrIsArrayAccessible($value, $message = '')
43
 * @method static void nullOrIsCountable($value, $message = '')
44
 * @method static void nullOrIsIterable($value, $message = '')
45
 * @method static void nullOrIsInstanceOf($value, $class, $message = '')
46
 * @method static void nullOrNotInstanceOf($value, $class, $message = '')
47
 * @method static void nullOrIsInstanceOfAny($value, $classes, $message = '')
48
 * @method static void nullOrIsAOf($value, $classes, $message = '')
49
 * @method static void nullOrIsAOfAny($value, $classes, $message = '')
50
 * @method static void nullOrNotAOf($value, $classes, $message = '')
51
 * @method static void nullOrIsEmpty($value, $message = '')
52
 * @method static void nullOrNotEmpty($value, $message = '')
53
 * @method static void nullOrTrue($value, $message = '')
54
 * @method static void nullOrFalse($value, $message = '')
55
 * @method static void nullOrNotFalse($value, $message = '')
56
 * @method static void nullOrIp($value, $message = '')
57
 * @method static void nullOrIpv4($value, $message = '')
58
 * @method static void nullOrIpv6($value, $message = '')
59
 * @method static void nullOrEmail($value, $message = '')
60
 * @method static void nullOrUniqueValues($values, $message = '')
61
 * @method static void nullOrEq($value, $expect, $message = '')
62
 * @method static void nullOrNotEq($value, $expect, $message = '')
63
 * @method static void nullOrSame($value, $expect, $message = '')
64
 * @method static void nullOrNotSame($value, $expect, $message = '')
65
 * @method static void nullOrGreaterThan($value, $limit, $message = '')
66
 * @method static void nullOrGreaterThanEq($value, $limit, $message = '')
67
 * @method static void nullOrLessThan($value, $limit, $message = '')
68
 * @method static void nullOrLessThanEq($value, $limit, $message = '')
69
 * @method static void nullOrRange($value, $min, $max, $message = '')
70
 * @method static void nullOrOneOf($value, $values, $message = '')
71
 * @method static void nullOrContains($value, $subString, $message = '')
72
 * @method static void nullOrNotContains($value, $subString, $message = '')
73
 * @method static void nullOrNotWhitespaceOnly($value, $message = '')
74
 * @method static void nullOrStartsWith($value, $prefix, $message = '')
75
 * @method static void nullOrStartsWithLetter($value, $message = '')
76
 * @method static void nullOrEndsWith($value, $suffix, $message = '')
77
 * @method static void nullOrRegex($value, $pattern, $message = '')
78
 * @method static void nullOrNotRegex($value, $pattern, $message = '')
79
 * @method static void nullOrUnicodeLetters($value, $message = '')
80
 * @method static void nullOrAlpha($value, $message = '')
81
 * @method static void nullOrDigits($value, $message = '')
82
 * @method static void nullOrAlnum($value, $message = '')
83
 * @method static void nullOrLower($value, $message = '')
84
 * @method static void nullOrUpper($value, $message = '')
85
 * @method static void nullOrLength($value, $length, $message = '')
86
 * @method static void nullOrMinLength($value, $min, $message = '')
87
 * @method static void nullOrMaxLength($value, $max, $message = '')
88
 * @method static void nullOrLengthBetween($value, $min, $max, $message = '')
89
 * @method static void nullOrFileExists($value, $message = '')
90
 * @method static void nullOrFile($value, $message = '')
91
 * @method static void nullOrDirectory($value, $message = '')
92
 * @method static void nullOrReadable($value, $message = '')
93
 * @method static void nullOrWritable($value, $message = '')
94
 * @method static void nullOrClassExists($value, $message = '')
95
 * @method static void nullOrSubclassOf($value, $class, $message = '')
96
 * @method static void nullOrInterfaceExists($value, $message = '')
97
 * @method static void nullOrImplementsInterface($value, $interface, $message = '')
98
 * @method static void nullOrPropertyExists($value, $property, $message = '')
99
 * @method static void nullOrPropertyNotExists($value, $property, $message = '')
100
 * @method static void nullOrMethodExists($value, $method, $message = '')
101
 * @method static void nullOrMethodNotExists($value, $method, $message = '')
102
 * @method static void nullOrKeyExists($value, $key, $message = '')
103
 * @method static void nullOrKeyNotExists($value, $key, $message = '')
104
 * @method static void nullOrValidArrayKey($value, $message = '')
105
 * @method static void nullOrCount($value, $key, $message = '')
106
 * @method static void nullOrMinCount($value, $min, $message = '')
107
 * @method static void nullOrMaxCount($value, $max, $message = '')
108
 * @method static void nullOrIsList($value, $message = '')
109
 * @method static void nullOrIsNonEmptyList($value, $message = '')
110
 * @method static void nullOrIsMap($value, $message = '')
111
 * @method static void nullOrIsNonEmptyMap($value, $message = '')
112
 * @method static void nullOrCountBetween($value, $min, $max, $message = '')
113
 * @method static void nullOrUuid($values, $message = '')
114
 * @method static void nullOrThrows($expression, $class = 'Exception', $message = '')
115
 * @method static void allString($values, $message = '')
116
 * @method static void allStringNotEmpty($values, $message = '')
117
 * @method static void allInteger($values, $message = '')
118
 * @method static void allIntegerish($values, $message = '')
119
 * @method static void allFloat($values, $message = '')
120
 * @method static void allNumeric($values, $message = '')
121
 * @method static void allNatural($values, $message = '')
122
 * @method static void allBoolean($values, $message = '')
123
 * @method static void allScalar($values, $message = '')
124
 * @method static void allObject($values, $message = '')
125
 * @method static void allResource($values, $type = null, $message = '')
126
 * @method static void allIsCallable($values, $message = '')
127
 * @method static void allIsArray($values, $message = '')
128
 * @method static void allIsTraversable($values, $message = '')
129
 * @method static void allIsArrayAccessible($values, $message = '')
130
 * @method static void allIsCountable($values, $message = '')
131
 * @method static void allIsIterable($values, $message = '')
132
 * @method static void allIsInstanceOf($values, $class, $message = '')
133
 * @method static void allNotInstanceOf($values, $class, $message = '')
134
 * @method static void allIsInstanceOfAny($values, $classes, $message = '')
135
 * @method static void allIsAOf($values, $class, $message = '')
136
 * @method static void allIsAOfAny($values, $class, $message = '')
137
 * @method static void allNotAOf($values, $class, $message = '')
138
 * @method static void allNull($values, $message = '')
139
 * @method static void allNotNull($values, $message = '')
140
 * @method static void allIsEmpty($values, $message = '')
141
 * @method static void allNotEmpty($values, $message = '')
142
 * @method static void allTrue($values, $message = '')
143
 * @method static void allFalse($values, $message = '')
144
 * @method static void allNotFalse($values, $message = '')
145
 * @method static void allIp($values, $message = '')
146
 * @method static void allIpv4($values, $message = '')
147
 * @method static void allIpv6($values, $message = '')
148
 * @method static void allEmail($values, $message = '')
149
 * @method static void allUniqueValues($values, $message = '')
150
 * @method static void allEq($values, $expect, $message = '')
151
 * @method static void allNotEq($values, $expect, $message = '')
152
 * @method static void allSame($values, $expect, $message = '')
153
 * @method static void allNotSame($values, $expect, $message = '')
154
 * @method static void allGreaterThan($values, $limit, $message = '')
155
 * @method static void allGreaterThanEq($values, $limit, $message = '')
156
 * @method static void allLessThan($values, $limit, $message = '')
157
 * @method static void allLessThanEq($values, $limit, $message = '')
158
 * @method static void allRange($values, $min, $max, $message = '')
159
 * @method static void allOneOf($values, $values, $message = '')
160
 * @method static void allContains($values, $subString, $message = '')
161
 * @method static void allNotContains($values, $subString, $message = '')
162
 * @method static void allNotWhitespaceOnly($values, $message = '')
163
 * @method static void allStartsWith($values, $prefix, $message = '')
164
 * @method static void allStartsWithLetter($values, $message = '')
165
 * @method static void allEndsWith($values, $suffix, $message = '')
166
 * @method static void allRegex($values, $pattern, $message = '')
167
 * @method static void allNotRegex($values, $pattern, $message = '')
168
 * @method static void allUnicodeLetters($values, $message = '')
169
 * @method static void allAlpha($values, $message = '')
170
 * @method static void allDigits($values, $message = '')
171
 * @method static void allAlnum($values, $message = '')
172
 * @method static void allLower($values, $message = '')
173
 * @method static void allUpper($values, $message = '')
174
 * @method static void allLength($values, $length, $message = '')
175
 * @method static void allMinLength($values, $min, $message = '')
176
 * @method static void allMaxLength($values, $max, $message = '')
177
 * @method static void allLengthBetween($values, $min, $max, $message = '')
178
 * @method static void allFileExists($values, $message = '')
179
 * @method static void allFile($values, $message = '')
180
 * @method static void allDirectory($values, $message = '')
181
 * @method static void allReadable($values, $message = '')
182
 * @method static void allWritable($values, $message = '')
183
 * @method static void allClassExists($values, $message = '')
184
 * @method static void allSubclassOf($values, $class, $message = '')
185
 * @method static void allInterfaceExists($values, $message = '')
186
 * @method static void allImplementsInterface($values, $interface, $message = '')
187
 * @method static void allPropertyExists($values, $property, $message = '')
188
 * @method static void allPropertyNotExists($values, $property, $message = '')
189
 * @method static void allMethodExists($values, $method, $message = '')
190
 * @method static void allMethodNotExists($values, $method, $message = '')
191
 * @method static void allKeyExists($values, $key, $message = '')
192
 * @method static void allKeyNotExists($values, $key, $message = '')
193
 * @method static void allValidArrayKey($values, $message = '')
194
 * @method static void allCount($values, $key, $message = '')
195
 * @method static void allMinCount($values, $min, $message = '')
196
 * @method static void allMaxCount($values, $max, $message = '')
197
 * @method static void allCountBetween($values, $min, $max, $message = '')
198
 * @method static void allIsList($values, $message = '')
199
 * @method static void allIsNonEmptyList($values, $message = '')
200
 * @method static void allIsMap($values, $message = '')
201
 * @method static void allIsNonEmptyMap($values, $message = '')
202
 * @method static void allUuid($values, $message = '')
203
 * @method static void allThrows($expressions, $class = 'Exception', $message = '')
204
 *
205
 * @since  1.0
206
 *
207
 * @author Bernhard Schussek <[email protected]>
208
 */
209
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...
210
{
211
    /**
212
     * @psalm-assert string $value
213
     *
214
     * @param mixed  $value
215
     * @param string $message
216
     *
217
     * @throws InvalidArgumentException
218
     */
219 241
    public static function string($value, $message = '')
220
    {
221 241
        if (!\is_string($value)) {
222 45
            static::reportInvalidArgument(\sprintf(
223 45
                $message ?: 'Expected a string. Got: %s',
224 45
                static::typeToString($value)
225
            ));
226
        }
227 196
    }
228
229
    /**
230
     * @param mixed  $value
231
     * @param string $message
232
     *
233
     * @throws InvalidArgumentException
234
     */
235 16
    public static function stringNotEmpty($value, $message = '')
236
    {
237 16
        static::string($value, $message);
238 12
        static::notEq($value, '', $message);
239 8
    }
240
241
    /**
242
     * @psalm-assert int $value
243
     *
244
     * @param mixed  $value
245
     * @param string $message
246
     *
247
     * @throws InvalidArgumentException
248
     */
249 17
    public static function integer($value, $message = '')
250
    {
251 17
        if (!\is_int($value)) {
252 13
            static::reportInvalidArgument(\sprintf(
253 13
                $message ?: 'Expected an integer. Got: %s',
254 13
                static::typeToString($value)
255
            ));
256
        }
257 4
    }
258
259
    /**
260
     * @psalm-assert numeric $value
261
     *
262
     * @param mixed  $value
263
     * @param string $message
264
     *
265
     * @throws InvalidArgumentException
266
     */
267 16
    public static function integerish($value, $message = '')
268
    {
269 16
        if (!\is_numeric($value) || $value != (int) $value) {
270 4
            static::reportInvalidArgument(\sprintf(
271 4
                $message ?: 'Expected an integerish value. Got: %s',
272 4
                static::typeToString($value)
273
            ));
274
        }
275 12
    }
276
277
    /**
278
     * @psalm-assert float $value
279
     *
280
     * @param mixed  $value
281
     * @param string $message
282
     *
283
     * @throws InvalidArgumentException
284
     */
285 16
    public static function float($value, $message = '')
286
    {
287 16
        if (!\is_float($value)) {
288 8
            static::reportInvalidArgument(\sprintf(
289 8
                $message ?: 'Expected a float. Got: %s',
290 8
                static::typeToString($value)
291
            ));
292
        }
293 8
    }
294
295
    /**
296
     * @psalm-assert numeric $value
297
     *
298
     * @param mixed  $value
299
     * @param string $message
300
     *
301
     * @throws InvalidArgumentException
302
     */
303 20
    public static function numeric($value, $message = '')
304
    {
305 20
        if (!\is_numeric($value)) {
306 4
            static::reportInvalidArgument(\sprintf(
307 4
                $message ?: 'Expected a numeric. Got: %s',
308 4
                static::typeToString($value)
309
            ));
310
        }
311 16
    }
312
313
    /**
314
     * @psalm-assert int $value
315
     *
316
     * @param mixed  $value
317
     * @param string $message
318
     *
319
     * @throws InvalidArgumentException
320
     */
321 24
    public static function natural($value, $message = '')
322
    {
323 24
        if (!\is_int($value) || $value < 0) {
324 16
            static::reportInvalidArgument(\sprintf(
325 16
                $message ?: 'Expected a non-negative integer. Got %s',
326 16
                static::valueToString($value)
327
            ));
328
        }
329 8
    }
330
331
    /**
332
     * @psalm-assert bool $value
333
     *
334
     * @param mixed  $value
335
     * @param string $message
336
     *
337
     * @throws InvalidArgumentException
338
     */
339 16
    public static function boolean($value, $message = '')
340
    {
341 16
        if (!\is_bool($value)) {
342 8
            static::reportInvalidArgument(\sprintf(
343 8
                $message ?: 'Expected a boolean. Got: %s',
344 8
                static::typeToString($value)
345
            ));
346
        }
347 8
    }
348
349
    /**
350
     * @psalm-assert scalar $value
351
     *
352
     * @param mixed  $value
353
     * @param string $message
354
     *
355
     * @throws InvalidArgumentException
356
     */
357 23
    public static function scalar($value, $message = '')
358
    {
359 23
        if (!\is_scalar($value)) {
360 11
            static::reportInvalidArgument(\sprintf(
361 11
                $message ?: 'Expected a scalar. Got: %s',
362 11
                static::typeToString($value)
363
            ));
364
        }
365 12
    }
366
367
    /**
368
     * @psalm-assert object $value
369
     *
370
     * @param mixed  $value
371
     * @param string $message
372
     *
373
     * @throws InvalidArgumentException
374
     */
375 23
    public static function object($value, $message = '')
376
    {
377 23
        if (!\is_object($value)) {
378 15
            static::reportInvalidArgument(\sprintf(
379 15
                $message ?: 'Expected an object. Got: %s',
380 15
                static::typeToString($value)
381
            ));
382
        }
383 8
    }
384
385
    /**
386
     * @psalm-assert resource $value
387
     *
388
     * @param mixed       $value
389
     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
390
     * @param string      $message
391
     *
392
     * @throws InvalidArgumentException
393
     */
394 16
    public static function resource($value, $type = null, $message = '')
395
    {
396 16
        if (!\is_resource($value)) {
397 4
            static::reportInvalidArgument(\sprintf(
398 4
                $message ?: 'Expected a resource. Got: %s',
399 4
                static::typeToString($value)
400
            ));
401
        }
402
403 12
        if ($type && $type !== \get_resource_type($value)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $type of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
404 4
            static::reportInvalidArgument(\sprintf(
405 4
                $message ?: 'Expected a resource of type %2$s. Got: %s',
406 4
                static::typeToString($value),
407 4
                $type
408
            ));
409
        }
410 8
    }
411
412
    /**
413
     * @psalm-assert callable $value
414
     *
415
     * @param mixed  $value
416
     * @param string $message
417
     *
418
     * @throws InvalidArgumentException
419
     */
420 20
    public static function isCallable($value, $message = '')
421
    {
422 20
        if (!\is_callable($value)) {
423 8
            static::reportInvalidArgument(\sprintf(
424 8
                $message ?: 'Expected a callable. Got: %s',
425 8
                static::typeToString($value)
426
            ));
427
        }
428 12
    }
429
430
    /**
431
     * @psalm-assert array $value
432
     *
433
     * @param mixed  $value
434
     * @param string $message
435
     *
436
     * @throws InvalidArgumentException
437
     */
438 20
    public static function isArray($value, $message = '')
439
    {
440 20
        if (!\is_array($value)) {
441 12
            static::reportInvalidArgument(\sprintf(
442 12
                $message ?: 'Expected an array. Got: %s',
443 12
                static::typeToString($value)
444
            ));
445
        }
446 8
    }
447
448
    /**
449
     * @psalm-assert iterable $value
450
     *
451
     * @deprecated use "isIterable" or "isInstanceOf" instead
452
     *
453
     * @param mixed  $value
454
     * @param string $message
455
     *
456
     * @throws InvalidArgumentException
457
     */
458 20
    public static function isTraversable($value, $message = '')
459
    {
460 20
        @\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...
461 20
            \sprintf(
462 20
                'The "%s" assertion is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "isIterable" or "isInstanceOf" instead.',
463 20
                __METHOD__
464
            ),
465 20
            \E_USER_DEPRECATED
466
        );
467
468 20
        if (!\is_array($value) && !($value instanceof Traversable)) {
469 8
            static::reportInvalidArgument(\sprintf(
470 8
                $message ?: 'Expected a traversable. Got: %s',
471 8
                static::typeToString($value)
472
            ));
473
        }
474 12
    }
475
476
    /**
477
     * @param mixed  $value
478
     * @param string $message
479
     *
480
     * @throws InvalidArgumentException
481
     */
482 20 View Code Duplication
    public static function isArrayAccessible($value, $message = '')
483
    {
484 20
        if (!\is_array($value) && !($value instanceof ArrayAccess)) {
485 8
            static::reportInvalidArgument(\sprintf(
486 8
                $message ?: 'Expected an array accessible. Got: %s',
487 8
                static::typeToString($value)
488
            ));
489
        }
490 12
    }
491
492
    /**
493
     * @psalm-assert countable $value
494
     *
495
     * @param mixed  $value
496
     * @param string $message
497
     *
498
     * @throws InvalidArgumentException
499
     */
500 28
    public static function isCountable($value, $message = '')
501
    {
502
        if (
503 28
            !\is_array($value)
504 28
            && !($value instanceof Countable)
505 28
            && !($value instanceof ResourceBundle)
0 ignored issues
show
Bug introduced by
The class ResourceBundle 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...
506 28
            && !($value instanceof SimpleXMLElement)
507
        ) {
508 12
            static::reportInvalidArgument(\sprintf(
509 12
                $message ?: 'Expected a countable. Got: %s',
510 12
                static::typeToString($value)
511
            ));
512
        }
513 16
    }
514
515
    /**
516
     * @psalm-assert iterable $value
517
     *
518
     * @param mixed  $value
519
     * @param string $message
520
     *
521
     * @throws InvalidArgumentException
522
     */
523 992 View Code Duplication
    public static function isIterable($value, $message = '')
524
    {
525 992
        if (!\is_array($value) && !($value instanceof Traversable)) {
526 8
            static::reportInvalidArgument(\sprintf(
527 8
                $message ?: 'Expected an iterable. Got: %s',
528 8
                static::typeToString($value)
529
            ));
530
        }
531 988
    }
532
533
    /**
534
     * @psalm-template ExpectedType of object
535
     * @psalm-param class-string<ExpectedType> $class
536
     * @psalm-assert ExpectedType $value
537
     *
538
     * @param mixed         $value
539
     * @param string|object $class
540
     * @param string        $message
541
     *
542
     * @throws InvalidArgumentException
543
     */
544 19
    public static function isInstanceOf($value, $class, $message = '')
545
    {
546 19
        if (!($value instanceof $class)) {
547 15
            static::reportInvalidArgument(\sprintf(
548 15
                $message ?: 'Expected an instance of %2$s. Got: %s',
549 15
                static::typeToString($value),
550 15
                $class
551
            ));
552
        }
553 4
    }
554
555
    /**
556
     * @psalm-template ExpectedType of object
557
     * @psalm-param class-string<ExpectedType> $class
558
     * @psalm-assert !ExpectedType $value
559
     *
560
     * @param mixed         $value
561
     * @param string|object $class
562
     * @param string        $message
563
     *
564
     * @throws InvalidArgumentException
565
     */
566 16
    public static function notInstanceOf($value, $class, $message = '')
567
    {
568 16
        if ($value instanceof $class) {
569 4
            static::reportInvalidArgument(\sprintf(
570 4
                $message ?: 'Expected an instance other than %2$s. Got: %s',
571 4
                static::typeToString($value),
572 4
                $class
573
            ));
574
        }
575 12
    }
576
577
    /**
578
     * @param mixed                $value
579
     * @param array<object|string> $classes
580
     * @param string               $message
581
     *
582
     * @throws InvalidArgumentException
583
     */
584 20
    public static function isInstanceOfAny($value, array $classes, $message = '')
585
    {
586 20
        foreach ($classes as $class) {
587 20
            if ($value instanceof $class) {
588 8
                return;
589
            }
590
        }
591
592 12
        static::reportInvalidArgument(\sprintf(
593 12
            $message ?: 'Expected an instance of any of %2$s. Got: %s',
594 12
            static::typeToString($value),
595 12
            \implode(', ', \array_map(array('static', 'valueToString'), $classes))
596
        ));
597
    }
598
599 20 View Code Duplication
    public static function isAOf($value, $class, $message = '')
600
    {
601 20
        static::string($class, 'Expected class as a string. Got: %s');
602
603 16
        if (!is_a($value, $class, is_string($value))) {
604 12
            static::reportInvalidArgument(sprintf(
605 12
                $message ?: 'Expected an instance of this class or to this class among his parents %2$s. Got: %s',
606 12
                static::typeToString($value),
607
                $class
608
            ));
609
        }
610 4
    }
611
612 20 View Code Duplication
    public static function notAOf($value, $class, $message = '')
613
    {
614 20
        static::string($class, 'Expected class as a string. Got: %s');
615
616 16
        if (is_a($value, $class, is_string($value))) {
617 4
            static::reportInvalidArgument(sprintf(
618 4
                $message ?: 'Expected an instance of this class or to this class among his parents other than %2$s. Got: %s',
619 4
                static::typeToString($value),
620
                $class
621
            ));
622
        }
623 12
    }
624
625 24
    public static function isAOfAny($value, array $classes, $message = '')
626
    {
627 24
        foreach ($classes as $class) {
628 24
            static::string($class, 'Expected class as a string. Got: %s');
629
630 20
            if (is_a($value, $class, is_string($value))) {
631 8
                return;
632
            }
633
        }
634
635 12
        static::reportInvalidArgument(sprintf(
636 12
            $message ?: 'Expected an any of instance of this class or to this class among his parents other than %2$s. Got: %s',
637 12
            static::typeToString($value),
638 12
            \implode(', ', \array_map(array('static', 'valueToString'), $classes))
639
        ));
640
    }
641
642
    /**
643
     * @psalm-assert empty $value
644
     *
645
     * @param mixed  $value
646
     * @param string $message
647
     *
648
     * @throws InvalidArgumentException
649
     */
650 23
    public static function isEmpty($value, $message = '')
651
    {
652 23
        if (!empty($value)) {
653 8
            static::reportInvalidArgument(\sprintf(
654 8
                $message ?: 'Expected an empty value. Got: %s',
655 8
                static::valueToString($value)
656
            ));
657
        }
658 15
    }
659
660
    /**
661
     * @psalm-assert !empty $value
662
     *
663
     * @param mixed  $value
664
     * @param string $message
665
     *
666
     * @throws InvalidArgumentException
667
     */
668 55
    public static function notEmpty($value, $message = '')
669
    {
670 55
        if (empty($value)) {
671 23
            static::reportInvalidArgument(\sprintf(
672 23
                $message ?: 'Expected a non-empty value. Got: %s',
673 23
                static::valueToString($value)
674
            ));
675
        }
676 32
    }
677
678
    /**
679
     * @psalm-assert null $value
680
     *
681
     * @param mixed  $value
682
     * @param string $message
683
     *
684
     * @throws InvalidArgumentException
685
     */
686 11
    public static function null($value, $message = '')
687
    {
688 11
        if (null !== $value) {
689 8
            static::reportInvalidArgument(\sprintf(
690 8
                $message ?: 'Expected null. Got: %s',
691 8
                static::valueToString($value)
692
            ));
693
        }
694 3
    }
695
696
    /**
697
     * @psalm-assert !null $value
698
     *
699
     * @param mixed  $value
700
     * @param string $message
701
     *
702
     * @throws InvalidArgumentException
703
     */
704 11
    public static function notNull($value, $message = '')
705
    {
706 11
        if (null === $value) {
707 3
            static::reportInvalidArgument(
708 3
                $message ?: 'Expected a value other than null.'
709
            );
710
        }
711 8
    }
712
713
    /**
714
     * @psalm-assert true $value
715
     *
716
     * @param mixed  $value
717
     * @param string $message
718
     *
719
     * @throws InvalidArgumentException
720
     */
721 15
    public static function true($value, $message = '')
722
    {
723 15
        if (true !== $value) {
724 11
            static::reportInvalidArgument(\sprintf(
725 11
                $message ?: 'Expected a value to be true. Got: %s',
726 11
                static::valueToString($value)
727
            ));
728
        }
729 4
    }
730
731
    /**
732
     * @psalm-assert false $value
733
     *
734
     * @param mixed  $value
735
     * @param string $message
736
     *
737
     * @throws InvalidArgumentException
738
     */
739 19
    public static function false($value, $message = '')
740
    {
741 19
        if (false !== $value) {
742 15
            static::reportInvalidArgument(\sprintf(
743 15
                $message ?: 'Expected a value to be false. Got: %s',
744 15
                static::valueToString($value)
745
            ));
746
        }
747 4
    }
748
749
    /**
750
     * @psalm-assert !false $value
751
     *
752
     * @param mixed  $value
753
     * @param string $message
754
     *
755
     * @throws InvalidArgumentException
756
     */
757 19
    public static function notFalse($value, $message = '')
758
    {
759 19
        if (false === $value) {
760 4
            static::reportInvalidArgument(
761 4
                $message ?: 'Expected a value other than false.'
762
            );
763
        }
764 15
    }
765
766
    /**
767
     * @param mixed  $value
768
     * @param string $message
769
     *
770
     * @throws InvalidArgumentException
771
     */
772 51 View Code Duplication
    public static function ip($value, $message = '')
773
    {
774 51
        if (false === \filter_var($value, \FILTER_VALIDATE_IP)) {
775 19
            static::reportInvalidArgument(\sprintf(
776 19
                $message ?: 'Expected a value to be an IP. Got: %s',
777 19
                static::valueToString($value)
778
            ));
779
        }
780 32
    }
781
782
    /**
783
     * @param mixed  $value
784
     * @param string $message
785
     *
786
     * @throws InvalidArgumentException
787
     */
788 51 View Code Duplication
    public static function ipv4($value, $message = '')
789
    {
790 51
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
791 35
            static::reportInvalidArgument(\sprintf(
792 35
                $message ?: 'Expected a value to be an IPv4. Got: %s',
793 35
                static::valueToString($value)
794
            ));
795
        }
796 16
    }
797
798
    /**
799
     * @param mixed  $value
800
     * @param string $message
801
     *
802
     * @throws InvalidArgumentException
803
     */
804 51 View Code Duplication
    public static function ipv6($value, $message = '')
805
    {
806 51
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
807 31
            static::reportInvalidArgument(\sprintf(
808 31
                $message ?: 'Expected a value to be an IPv6. Got %s',
809 31
                static::valueToString($value)
810
            ));
811
        }
812 20
    }
813
814
    /**
815
     * @param mixed  $value
816
     * @param string $message
817
     *
818
     * @throws InvalidArgumentException
819
     */
820 20 View Code Duplication
    public static function email($value, $message = '')
821
    {
822 20
        if (false === \filter_var($value, FILTER_VALIDATE_EMAIL)) {
823 12
            static::reportInvalidArgument(\sprintf(
824 12
                $message ?: 'Expected a value to be a valid e-mail address. Got %s',
825 12
                static::valueToString($value)
826
            ));
827
        }
828 8
    }
829
830
    /**
831
     * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion.
832
     *
833
     * @param array  $values
834
     * @param string $message
835
     *
836
     * @throws InvalidArgumentException
837
     */
838 12
    public static function uniqueValues(array $values, $message = '')
839
    {
840 12
        $allValues = \count($values);
841 12
        $uniqueValues = \count(\array_unique($values));
842
843 12
        if ($allValues !== $uniqueValues) {
844 8
            $difference = $allValues - $uniqueValues;
845
846 8
            static::reportInvalidArgument(\sprintf(
847 8
                $message ?: 'Expected an array of unique values, but %s of them %s duplicated',
848 8
                $difference,
849 8
                (1 === $difference ? 'is' : 'are')
850
            ));
851
        }
852 4
    }
853
854
    /**
855
     * @param mixed  $value
856
     * @param mixed  $expect
857
     * @param string $message
858
     *
859
     * @throws InvalidArgumentException
860
     */
861 33
    public static function eq($value, $expect, $message = '')
862
    {
863 33
        if ($expect != $value) {
864 17
            static::reportInvalidArgument(\sprintf(
865 17
                $message ?: 'Expected a value equal to %2$s. Got: %s',
866 17
                static::valueToString($value),
867 17
                static::valueToString($expect)
868
            ));
869
        }
870 16
    }
871
872
    /**
873
     * @param mixed  $value
874
     * @param mixed  $expect
875
     * @param string $message
876
     *
877
     * @throws InvalidArgumentException
878
     */
879 28
    public static function notEq($value, $expect, $message = '')
880
    {
881 28
        if ($expect == $value) {
882 16
            static::reportInvalidArgument(\sprintf(
883 16
                $message ?: 'Expected a different value than %s.',
884 16
                static::valueToString($expect)
885
            ));
886
        }
887 12
    }
888
889
    /**
890
     * @param mixed  $value
891
     * @param mixed  $expect
892
     * @param string $message
893
     *
894
     * @throws InvalidArgumentException
895
     */
896 16
    public static function same($value, $expect, $message = '')
897
    {
898 16
        if ($expect !== $value) {
899 12
            static::reportInvalidArgument(\sprintf(
900 12
                $message ?: 'Expected a value identical to %2$s. Got: %s',
901 12
                static::valueToString($value),
902 12
                static::valueToString($expect)
903
            ));
904
        }
905 4
    }
906
907
    /**
908
     * @param mixed  $value
909
     * @param mixed  $expect
910
     * @param string $message
911
     *
912
     * @throws InvalidArgumentException
913
     */
914 16
    public static function notSame($value, $expect, $message = '')
915
    {
916 16
        if ($expect === $value) {
917 4
            static::reportInvalidArgument(\sprintf(
918 4
                $message ?: 'Expected a value not identical to %s.',
919 4
                static::valueToString($expect)
920
            ));
921
        }
922 12
    }
923
924
    /**
925
     * @param mixed  $value
926
     * @param mixed  $limit
927
     * @param string $message
928
     *
929
     * @throws InvalidArgumentException
930
     */
931 8
    public static function greaterThan($value, $limit, $message = '')
932
    {
933 8
        if ($value <= $limit) {
934 4
            static::reportInvalidArgument(\sprintf(
935 4
                $message ?: 'Expected a value greater than %2$s. Got: %s',
936 4
                static::valueToString($value),
937 4
                static::valueToString($limit)
938
            ));
939
        }
940 4
    }
941
942
    /**
943
     * @param mixed  $value
944
     * @param mixed  $limit
945
     * @param string $message
946
     *
947
     * @throws InvalidArgumentException
948
     */
949 12
    public static function greaterThanEq($value, $limit, $message = '')
950
    {
951 12
        if ($value < $limit) {
952 4
            static::reportInvalidArgument(\sprintf(
953 4
                $message ?: 'Expected a value greater than or equal to %2$s. Got: %s',
954 4
                static::valueToString($value),
955 4
                static::valueToString($limit)
956
            ));
957
        }
958 8
    }
959
960
    /**
961
     * @param mixed  $value
962
     * @param mixed  $limit
963
     * @param string $message
964
     *
965
     * @throws InvalidArgumentException
966
     */
967 8
    public static function lessThan($value, $limit, $message = '')
968
    {
969 8
        if ($value >= $limit) {
970 4
            static::reportInvalidArgument(\sprintf(
971 4
                $message ?: 'Expected a value less than %2$s. Got: %s',
972 4
                static::valueToString($value),
973 4
                static::valueToString($limit)
974
            ));
975
        }
976 4
    }
977
978
    /**
979
     * @param mixed  $value
980
     * @param mixed  $limit
981
     * @param string $message
982
     *
983
     * @throws InvalidArgumentException
984
     */
985 12
    public static function lessThanEq($value, $limit, $message = '')
986
    {
987 12
        if ($value > $limit) {
988 4
            static::reportInvalidArgument(\sprintf(
989 4
                $message ?: 'Expected a value less than or equal to %2$s. Got: %s',
990 4
                static::valueToString($value),
991 4
                static::valueToString($limit)
992
            ));
993
        }
994 8
    }
995
996
    /**
997
     * Inclusive range, so Assert::(3, 3, 5) passes.
998
     *
999
     * @param mixed  $value
1000
     * @param mixed  $min
1001
     * @param mixed  $max
1002
     * @param string $message
1003
     *
1004
     * @throws InvalidArgumentException
1005
     */
1006 16 View Code Duplication
    public static function range($value, $min, $max, $message = '')
1007
    {
1008 16
        if ($value < $min || $value > $max) {
1009 8
            static::reportInvalidArgument(\sprintf(
1010 8
                $message ?: 'Expected a value between %2$s and %3$s. Got: %s',
1011 8
                static::valueToString($value),
1012 8
                static::valueToString($min),
1013 8
                static::valueToString($max)
1014
            ));
1015
        }
1016 8
    }
1017
1018
    /**
1019
     * Does strict comparison, so Assert::oneOf(3, ['3']) does not pass the assertion.
1020
     *
1021
     * @param mixed  $value
1022
     * @param array  $values
1023
     * @param string $message
1024
     *
1025
     * @throws InvalidArgumentException
1026
     */
1027 8
    public static function oneOf($value, array $values, $message = '')
1028
    {
1029 8
        if (!\in_array($value, $values, true)) {
1030 4
            static::reportInvalidArgument(\sprintf(
1031 4
                $message ?: 'Expected one of: %2$s. Got: %s',
1032 4
                static::valueToString($value),
1033 4
                \implode(', ', \array_map(array('static', 'valueToString'), $values))
1034
            ));
1035
        }
1036 4
    }
1037
1038
    /**
1039
     * @param mixed  $value
1040
     * @param string $subString
1041
     * @param string $message
1042
     *
1043
     * @throws InvalidArgumentException
1044
     */
1045 80 View Code Duplication
    public static function contains($value, $subString, $message = '')
1046
    {
1047 80
        if (false === \strpos($value, $subString)) {
1048 32
            static::reportInvalidArgument(\sprintf(
1049 32
                $message ?: 'Expected a value to contain %2$s. Got: %s',
1050 32
                static::valueToString($value),
1051 32
                static::valueToString($subString)
1052
            ));
1053
        }
1054 48
    }
1055
1056
    /**
1057
     * @param mixed  $value
1058
     * @param string $subString
1059
     * @param string $message
1060
     *
1061
     * @throws InvalidArgumentException
1062
     */
1063 80 View Code Duplication
    public static function notContains($value, $subString, $message = '')
1064
    {
1065 80
        if (false !== \strpos($value, $subString)) {
1066 48
            static::reportInvalidArgument(\sprintf(
1067 48
                $message ?: '%2$s was not expected to be contained in a value. Got: %s',
1068 48
                static::valueToString($value),
1069 48
                static::valueToString($subString)
1070
            ));
1071
        }
1072 32
    }
1073
1074
    /**
1075
     * @param mixed  $value
1076
     * @param string $message
1077
     *
1078
     * @throws InvalidArgumentException
1079
     */
1080 40
    public static function notWhitespaceOnly($value, $message = '')
1081
    {
1082 40
        if (\preg_match('/^\s*$/', $value)) {
1083 24
            static::reportInvalidArgument(\sprintf(
1084 24
                $message ?: 'Expected a non-whitespace string. Got: %s',
1085 24
                static::valueToString($value)
1086
            ));
1087
        }
1088 16
    }
1089
1090
    /**
1091
     * @param mixed  $value
1092
     * @param string $prefix
1093
     * @param string $message
1094
     *
1095
     * @throws InvalidArgumentException
1096
     */
1097 48 View Code Duplication
    public static function startsWith($value, $prefix, $message = '')
1098
    {
1099 48
        if (0 !== \strpos($value, $prefix)) {
1100 32
            static::reportInvalidArgument(\sprintf(
1101 32
                $message ?: 'Expected a value to start with %2$s. Got: %s',
1102 32
                static::valueToString($value),
1103 32
                static::valueToString($prefix)
1104
            ));
1105
        }
1106 16
    }
1107
1108
    /**
1109
     * @param mixed  $value
1110
     * @param string $message
1111
     *
1112
     * @throws InvalidArgumentException
1113
     */
1114 35
    public static function startsWithLetter($value, $message = '')
1115
    {
1116 35
        static::string($value);
1117
1118 24
        $valid = isset($value[0]);
1119
1120 24
        if ($valid) {
1121 20
            $locale = \setlocale(LC_CTYPE, 0);
1122 20
            \setlocale(LC_CTYPE, 'C');
1123 20
            $valid = \ctype_alpha($value[0]);
1124 20
            \setlocale(LC_CTYPE, $locale);
1125
        }
1126
1127 24
        if (!$valid) {
1128 12
            static::reportInvalidArgument(\sprintf(
1129 12
                $message ?: 'Expected a value to start with a letter. Got: %s',
1130 12
                static::valueToString($value)
1131
            ));
1132
        }
1133 12
    }
1134
1135
    /**
1136
     * @param mixed  $value
1137
     * @param string $suffix
1138
     * @param string $message
1139
     *
1140
     * @throws InvalidArgumentException
1141
     */
1142 48 View Code Duplication
    public static function endsWith($value, $suffix, $message = '')
1143
    {
1144 48
        if ($suffix !== \substr($value, -\strlen($suffix))) {
1145 32
            static::reportInvalidArgument(\sprintf(
1146 32
                $message ?: 'Expected a value to end with %2$s. Got: %s',
1147 32
                static::valueToString($value),
1148 32
                static::valueToString($suffix)
1149
            ));
1150
        }
1151 16
    }
1152
1153
    /**
1154
     * @param mixed  $value
1155
     * @param mixed  $pattern
1156
     * @param string $message
1157
     *
1158
     * @throws InvalidArgumentException
1159
     */
1160 12
    public static function regex($value, $pattern, $message = '')
1161
    {
1162 12
        if (!\preg_match($pattern, $value)) {
1163 8
            static::reportInvalidArgument(\sprintf(
1164 8
                $message ?: 'The value %s does not match the expected pattern.',
1165 8
                static::valueToString($value)
1166
            ));
1167
        }
1168 4
    }
1169
1170
    /**
1171
     * @param mixed  $value
1172
     * @param mixed  $pattern
1173
     * @param string $message
1174
     *
1175
     * @throws InvalidArgumentException
1176
     */
1177 12
    public static function notRegex($value, $pattern, $message = '')
1178
    {
1179 12
        if (\preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) {
1180 4
            static::reportInvalidArgument(\sprintf(
1181 4
                $message ?: 'The value %s matches the pattern %s (at offset %d).',
1182 4
                static::valueToString($value),
1183 4
                static::valueToString($pattern),
1184 4
                $matches[0][1]
1185
            ));
1186
        }
1187 8
    }
1188
1189
    /**
1190
     * @param mixed  $value
1191
     * @param string $message
1192
     *
1193
     * @throws InvalidArgumentException
1194
     */
1195 28 View Code Duplication
    public static function unicodeLetters($value, $message = '')
1196
    {
1197 28
        static::string($value);
1198
1199 28
        if (!\preg_match('/^\p{L}+$/u', $value)) {
1200 16
            static::reportInvalidArgument(\sprintf(
1201 16
                $message ?: 'Expected a value to contain only Unicode letters. Got: %s',
1202 16
                static::valueToString($value)
1203
            ));
1204
        }
1205 12
    }
1206
1207
    /**
1208
     * @param mixed  $value
1209
     * @param string $message
1210
     *
1211
     * @throws InvalidArgumentException
1212
     */
1213 20 View Code Duplication
    public static function alpha($value, $message = '')
1214
    {
1215 20
        static::string($value);
1216
1217 12
        $locale = \setlocale(LC_CTYPE, 0);
1218 12
        \setlocale(LC_CTYPE, 'C');
1219 12
        $valid = !\ctype_alpha($value);
1220 12
        \setlocale(LC_CTYPE, $locale);
1221
1222 12
        if ($valid) {
1223 8
            static::reportInvalidArgument(\sprintf(
1224 8
                $message ?: 'Expected a value to contain only letters. Got: %s',
1225 8
                static::valueToString($value)
1226
            ));
1227
        }
1228 4
    }
1229
1230
    /**
1231
     * @param mixed  $value
1232
     * @param string $message
1233
     *
1234
     * @throws InvalidArgumentException
1235
     */
1236 12 View Code Duplication
    public static function digits($value, $message = '')
1237
    {
1238 12
        $locale = \setlocale(LC_CTYPE, 0);
1239 12
        \setlocale(LC_CTYPE, 'C');
1240 12
        $valid = !\ctype_digit($value);
1241 12
        \setlocale(LC_CTYPE, $locale);
1242
1243 12
        if ($valid) {
1244 8
            static::reportInvalidArgument(\sprintf(
1245 8
                $message ?: 'Expected a value to contain digits only. Got: %s',
1246 8
                static::valueToString($value)
1247
            ));
1248
        }
1249 4
    }
1250
1251
    /**
1252
     * @param mixed  $value
1253
     * @param string $message
1254
     *
1255
     * @throws InvalidArgumentException
1256
     */
1257 12 View Code Duplication
    public static function alnum($value, $message = '')
1258
    {
1259 12
        $locale = \setlocale(LC_CTYPE, 0);
1260 12
        \setlocale(LC_CTYPE, 'C');
1261 12
        $valid = !\ctype_alnum($value);
1262 12
        \setlocale(LC_CTYPE, $locale);
1263
1264 12
        if ($valid) {
1265 8
            static::reportInvalidArgument(\sprintf(
1266 8
                $message ?: 'Expected a value to contain letters and digits only. Got: %s',
1267 8
                static::valueToString($value)
1268
            ));
1269
        }
1270 4
    }
1271
1272
    /**
1273
     * @param mixed  $value
1274
     * @param string $message
1275
     *
1276
     * @throws InvalidArgumentException
1277
     */
1278 16 View Code Duplication
    public static function lower($value, $message = '')
1279
    {
1280 16
        $locale = \setlocale(LC_CTYPE, 0);
1281 16
        \setlocale(LC_CTYPE, 'C');
1282 16
        $valid = !\ctype_lower($value);
1283 16
        \setlocale(LC_CTYPE, $locale);
1284
1285 16
        if ($valid) {
1286 12
            static::reportInvalidArgument(\sprintf(
1287 12
                $message ?: 'Expected a value to contain lowercase characters only. Got: %s',
1288 12
                static::valueToString($value)
1289
            ));
1290
        }
1291 4
    }
1292
1293
    /**
1294
     * @param mixed  $value
1295
     * @param string $message
1296
     *
1297
     * @throws InvalidArgumentException
1298
     */
1299 16 View Code Duplication
    public static function upper($value, $message = '')
1300
    {
1301 16
        $locale = \setlocale(LC_CTYPE, 0);
1302 16
        \setlocale(LC_CTYPE, 'C');
1303 16
        $valid = !\ctype_upper($value);
1304 16
        \setlocale(LC_CTYPE, $locale);
1305
1306 16
        if ($valid) {
1307 12
            static::reportInvalidArgument(\sprintf(
1308 12
                $message ?: 'Expected a value to contain uppercase characters only. Got: %s',
1309 12
                static::valueToString($value)
1310
            ));
1311
        }
1312 4
    }
1313
1314
    /**
1315
     * @param mixed  $value
1316
     * @param mixed  $length
1317
     * @param string $message
1318
     *
1319
     * @throws InvalidArgumentException
1320
     */
1321 36
    public static function length($value, $length, $message = '')
1322
    {
1323 36
        if ($length !== static::strlen($value)) {
1324 24
            static::reportInvalidArgument(\sprintf(
1325 24
                $message ?: 'Expected a value to contain %2$s characters. Got: %s',
1326 24
                static::valueToString($value),
1327 24
                $length
1328
            ));
1329
        }
1330 12
    }
1331
1332
    /**
1333
     * Inclusive min.
1334
     *
1335
     * @param mixed  $value
1336
     * @param mixed  $min
1337
     * @param string $message
1338
     *
1339
     * @throws InvalidArgumentException
1340
     */
1341 36
    public static function minLength($value, $min, $message = '')
1342
    {
1343 36
        if (static::strlen($value) < $min) {
1344 12
            static::reportInvalidArgument(\sprintf(
1345 12
                $message ?: 'Expected a value to contain at least %2$s characters. Got: %s',
1346 12
                static::valueToString($value),
1347 12
                $min
1348
            ));
1349
        }
1350 24
    }
1351
1352
    /**
1353
     * Inclusive max.
1354
     *
1355
     * @param mixed  $value
1356
     * @param mixed  $max
1357
     * @param string $message
1358
     *
1359
     * @throws InvalidArgumentException
1360
     */
1361 36
    public static function maxLength($value, $max, $message = '')
1362
    {
1363 36
        if (static::strlen($value) > $max) {
1364 12
            static::reportInvalidArgument(\sprintf(
1365 12
                $message ?: 'Expected a value to contain at most %2$s characters. Got: %s',
1366 12
                static::valueToString($value),
1367 12
                $max
1368
            ));
1369
        }
1370 24
    }
1371
1372
    /**
1373
     * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion.
1374
     *
1375
     * @param mixed  $value
1376
     * @param mixed  $min
1377
     * @param mixed  $max
1378
     * @param string $message
1379
     *
1380
     * @throws InvalidArgumentException
1381
     */
1382 60 View Code Duplication
    public static function lengthBetween($value, $min, $max, $message = '')
1383
    {
1384 60
        $length = static::strlen($value);
1385
1386 60
        if ($length < $min || $length > $max) {
1387 24
            static::reportInvalidArgument(\sprintf(
1388 24
                $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s',
1389 24
                static::valueToString($value),
1390 24
                $min,
1391 24
                $max
1392
            ));
1393
        }
1394 36
    }
1395
1396
    /**
1397
     * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file.
1398
     *
1399
     * @param mixed  $value
1400
     * @param string $message
1401
     *
1402
     * @throws InvalidArgumentException
1403
     */
1404 36 View Code Duplication
    public static function fileExists($value, $message = '')
1405
    {
1406 36
        static::string($value);
1407
1408 36
        if (!\file_exists($value)) {
1409 12
            static::reportInvalidArgument(\sprintf(
1410 12
                $message ?: 'The file %s does not exist.',
1411 12
                static::valueToString($value)
1412
            ));
1413
        }
1414 24
    }
1415
1416
    /**
1417
     * @param mixed  $value
1418
     * @param string $message
1419
     *
1420
     * @throws InvalidArgumentException
1421
     */
1422 12 View Code Duplication
    public static function file($value, $message = '')
1423
    {
1424 12
        static::fileExists($value, $message);
1425
1426 8
        if (!\is_file($value)) {
1427 4
            static::reportInvalidArgument(\sprintf(
1428 4
                $message ?: 'The path %s is not a file.',
1429 4
                static::valueToString($value)
1430
            ));
1431
        }
1432 4
    }
1433
1434
    /**
1435
     * @param mixed  $value
1436
     * @param string $message
1437
     *
1438
     * @throws InvalidArgumentException
1439
     */
1440 12 View Code Duplication
    public static function directory($value, $message = '')
1441
    {
1442 12
        static::fileExists($value, $message);
1443
1444 8
        if (!\is_dir($value)) {
1445 4
            static::reportInvalidArgument(\sprintf(
1446 4
                $message ?: 'The path %s is no directory.',
1447 4
                static::valueToString($value)
1448
            ));
1449
        }
1450 4
    }
1451
1452
    /**
1453
     * @param mixed  $value
1454
     * @param string $message
1455
     *
1456
     * @throws InvalidArgumentException
1457
     */
1458
    public static function readable($value, $message = '')
1459
    {
1460
        if (!\is_readable($value)) {
1461
            static::reportInvalidArgument(\sprintf(
1462
                $message ?: 'The path %s is not readable.',
1463
                static::valueToString($value)
1464
            ));
1465
        }
1466
    }
1467
1468
    /**
1469
     * @param mixed  $value
1470
     * @param string $message
1471
     *
1472
     * @throws InvalidArgumentException
1473
     */
1474
    public static function writable($value, $message = '')
1475
    {
1476
        if (!\is_writable($value)) {
1477
            static::reportInvalidArgument(\sprintf(
1478
                $message ?: 'The path %s is not writable.',
1479
                static::valueToString($value)
1480
            ));
1481
        }
1482
    }
1483
1484
    /**
1485
     * @psalm-assert class-string $value
1486
     *
1487
     * @param mixed  $value
1488
     * @param string $message
1489
     *
1490
     * @throws InvalidArgumentException
1491
     */
1492 8
    public static function classExists($value, $message = '')
1493
    {
1494 8
        if (!\class_exists($value)) {
1495 4
            static::reportInvalidArgument(\sprintf(
1496 4
                $message ?: 'Expected an existing class name. Got: %s',
1497 4
                static::valueToString($value)
1498
            ));
1499
        }
1500 4
    }
1501
1502
    /**
1503
     * @param mixed         $value
1504
     * @param string|object $class
1505
     * @param string        $message
1506
     *
1507
     * @throws InvalidArgumentException
1508
     */
1509 8
    public static function subclassOf($value, $class, $message = '')
1510
    {
1511 8
        if (!\is_subclass_of($value, $class)) {
1512 4
            static::reportInvalidArgument(\sprintf(
1513 4
                $message ?: 'Expected a sub-class of %2$s. Got: %s',
1514 4
                static::valueToString($value),
1515 4
                static::valueToString($class)
1516
            ));
1517
        }
1518 4
    }
1519
1520
    /**
1521
     * @psalm-assert class-string $value
1522
     *
1523
     * @param mixed  $value
1524
     * @param string $message
1525
     *
1526
     * @throws InvalidArgumentException
1527
     */
1528 8
    public static function interfaceExists($value, $message = '')
1529
    {
1530 8
        if (!\interface_exists($value)) {
1531 4
            static::reportInvalidArgument(\sprintf(
1532 4
                $message ?: 'Expected an existing interface name. got %s',
1533 4
                static::valueToString($value)
1534
            ));
1535
        }
1536 4
    }
1537
1538
    /**
1539
     * @param mixed  $value
1540
     * @param mixed  $interface
1541
     * @param string $message
1542
     *
1543
     * @throws InvalidArgumentException
1544
     */
1545 8 View Code Duplication
    public static function implementsInterface($value, $interface, $message = '')
1546
    {
1547 8
        if (!\in_array($interface, \class_implements($value))) {
1548 4
            static::reportInvalidArgument(\sprintf(
1549 4
                $message ?: 'Expected an implementation of %2$s. Got: %s',
1550 4
                static::valueToString($value),
1551 4
                static::valueToString($interface)
1552
            ));
1553
        }
1554 4
    }
1555
1556
    /**
1557
     * @param string|object $classOrObject
1558
     * @param mixed         $property
1559
     * @param string        $message
1560
     *
1561
     * @throws InvalidArgumentException
1562
     */
1563 12 View Code Duplication
    public static function propertyExists($classOrObject, $property, $message = '')
1564
    {
1565 12
        if (!\property_exists($classOrObject, $property)) {
1566 4
            static::reportInvalidArgument(\sprintf(
1567 4
                $message ?: 'Expected the property %s to exist.',
1568 4
                static::valueToString($property)
1569
            ));
1570
        }
1571 8
    }
1572
1573
    /**
1574
     * @param string|object $classOrObject
1575
     * @param mixed         $property
1576
     * @param string        $message
1577
     *
1578
     * @throws InvalidArgumentException
1579
     */
1580 12 View Code Duplication
    public static function propertyNotExists($classOrObject, $property, $message = '')
1581
    {
1582 12
        if (\property_exists($classOrObject, $property)) {
1583 8
            static::reportInvalidArgument(\sprintf(
1584 8
                $message ?: 'Expected the property %s to not exist.',
1585 8
                static::valueToString($property)
1586
            ));
1587
        }
1588 4
    }
1589
1590
    /**
1591
     * @param string|object $classOrObject
1592
     * @param mixed         $method
1593
     * @param string        $message
1594
     *
1595
     * @throws InvalidArgumentException
1596
     */
1597 27 View Code Duplication
    public static function methodExists($classOrObject, $method, $message = '')
1598
    {
1599 27
        if (!\method_exists($classOrObject, $method)) {
1600 19
            static::reportInvalidArgument(\sprintf(
1601 19
                $message ?: 'Expected the method %s to exist.',
1602 19
                static::valueToString($method)
1603
            ));
1604
        }
1605 8
    }
1606
1607
    /**
1608
     * @param string|object $classOrObject
1609
     * @param mixed         $method
1610
     * @param string        $message
1611
     *
1612
     * @throws InvalidArgumentException
1613
     */
1614 27 View Code Duplication
    public static function methodNotExists($classOrObject, $method, $message = '')
1615
    {
1616 27
        if (\method_exists($classOrObject, $method)) {
1617 8
            static::reportInvalidArgument(\sprintf(
1618 8
                $message ?: 'Expected the method %s to not exist.',
1619 8
                static::valueToString($method)
1620
            ));
1621
        }
1622 19
    }
1623
1624
    /**
1625
     * @param array      $array
1626
     * @param string|int $key
1627
     * @param string     $message
1628
     *
1629
     * @throws InvalidArgumentException
1630
     */
1631 12 View Code Duplication
    public static function keyExists($array, $key, $message = '')
1632
    {
1633 12
        if (!(isset($array[$key]) || \array_key_exists($key, $array))) {
1634 4
            static::reportInvalidArgument(\sprintf(
1635 4
                $message ?: 'Expected the key %s to exist.',
1636 4
                static::valueToString($key)
1637
            ));
1638
        }
1639 8
    }
1640
1641
    /**
1642
     * @param array      $array
1643
     * @param string|int $key
1644
     * @param string     $message
1645
     *
1646
     * @throws InvalidArgumentException
1647
     */
1648 12 View Code Duplication
    public static function keyNotExists($array, $key, $message = '')
1649
    {
1650 12
        if (isset($array[$key]) || \array_key_exists($key, $array)) {
1651 8
            static::reportInvalidArgument(\sprintf(
1652 8
                $message ?: 'Expected the key %s to not exist.',
1653 8
                static::valueToString($key)
1654
            ));
1655
        }
1656 4
    }
1657
1658
    /**
1659
     * Checks if a value is a valid array key (int or string).
1660
     *
1661
     * @psalm-assert array-key $value
1662
     *
1663
     * @param mixed  $value
1664
     * @param string $message
1665
     *
1666
     * @throws InvalidArgumentException
1667
     */
1668 28
    public static function validArrayKey($value, $message = '')
1669
    {
1670 28
        if (!(\is_int($value) || \is_string($value))) {
1671 20
            static::reportInvalidArgument(\sprintf(
1672 20
                $message ?: 'Expected string or integer. Got: %s',
1673 20
                static::typeToString($value)
1674
            ));
1675
        }
1676 8
    }
1677
1678
    /**
1679
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1680
     *
1681
     * @param mixed  $array
1682
     * @param mixed  $number
1683
     * @param string $message
1684
     *
1685
     * @throws InvalidArgumentException
1686
     */
1687 8
    public static function count($array, $number, $message = '')
1688
    {
1689 8
        static::eq(
1690 8
            \count($array),
1691
            $number,
1692 8
            $message ?: \sprintf('Expected an array to contain %d elements. Got: %d.', $number, \count($array))
1693
        );
1694 4
    }
1695
1696
    /**
1697
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1698
     *
1699
     * @param mixed  $array
1700
     * @param mixed  $min
1701
     * @param string $message
1702
     *
1703
     * @throws InvalidArgumentException
1704
     */
1705 12 View Code Duplication
    public static function minCount($array, $min, $message = '')
1706
    {
1707 12
        if (\count($array) < $min) {
1708 4
            static::reportInvalidArgument(\sprintf(
1709 4
                $message ?: 'Expected an array to contain at least %2$d elements. Got: %d',
1710 4
                \count($array),
1711 4
                $min
1712
            ));
1713
        }
1714 8
    }
1715
1716
    /**
1717
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1718
     *
1719
     * @param mixed  $array
1720
     * @param mixed  $max
1721
     * @param string $message
1722
     *
1723
     * @throws InvalidArgumentException
1724
     */
1725 12 View Code Duplication
    public static function maxCount($array, $max, $message = '')
1726
    {
1727 12
        if (\count($array) > $max) {
1728 4
            static::reportInvalidArgument(\sprintf(
1729 4
                $message ?: 'Expected an array to contain at most %2$d elements. Got: %d',
1730 4
                \count($array),
1731 4
                $max
1732
            ));
1733
        }
1734 8
    }
1735
1736
    /**
1737
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1738
     *
1739
     * @param mixed  $array
1740
     * @param mixed  $min
1741
     * @param mixed  $max
1742
     * @param string $message
1743
     *
1744
     * @throws InvalidArgumentException
1745
     */
1746 20
    public static function countBetween($array, $min, $max, $message = '')
1747
    {
1748 20
        $count = \count($array);
1749
1750 20
        if ($count < $min || $count > $max) {
1751 8
            static::reportInvalidArgument(\sprintf(
1752 8
                $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d',
1753 8
                $count,
1754 8
                $min,
1755 8
                $max
1756
            ));
1757
        }
1758 12
    }
1759
1760
    /**
1761
     * @psalm-assert list $array
1762
     *
1763
     * @param mixed  $array
1764
     * @param string $message
1765
     *
1766
     * @throws InvalidArgumentException
1767
     */
1768 80 View Code Duplication
    public static function isList($array, $message = '')
1769
    {
1770 80
        if (!\is_array($array) || $array !== \array_values($array)) {
1771 32
            static::reportInvalidArgument(
1772 32
                $message ?: 'Expected list - non-associative array.'
1773
            );
1774
        }
1775 48
    }
1776
1777
    /**
1778
     * @psalm-assert non-empty-list $array
1779
     *
1780
     * @param mixed  $array
1781
     * @param string $message
1782
     *
1783
     * @throws InvalidArgumentException
1784
     */
1785 40
    public static function isNonEmptyList($array, $message = '')
1786
    {
1787 40
        static::isList($array, $message);
1788 24
        static::notEmpty($array, $message);
1789 20
    }
1790
1791
    /**
1792
     * @param mixed  $array
1793
     * @param string $message
1794
     *
1795
     * @throws InvalidArgumentException
1796
     */
1797 32
    public static function isMap($array, $message = '')
1798
    {
1799
        if (
1800 32
            !\is_array($array) ||
1801 32
            \array_keys($array) !== \array_filter(\array_keys($array), '\is_string')
1802
        ) {
1803 16
            static::reportInvalidArgument(
1804 16
                $message ?: 'Expected map - associative array with string keys.'
1805
            );
1806
        }
1807 16
    }
1808
1809
    /**
1810
     * @param mixed  $array
1811
     * @param string $message
1812
     *
1813
     * @throws InvalidArgumentException
1814
     */
1815 16
    public static function isNonEmptyMap($array, $message = '')
1816
    {
1817 16
        static::isMap($array, $message);
1818 8
        static::notEmpty($array, $message);
1819 4
    }
1820
1821
    /**
1822
     * @param mixed  $value
1823
     * @param string $message
1824
     *
1825
     * @throws InvalidArgumentException
1826
     */
1827 56
    public static function uuid($value, $message = '')
1828
    {
1829 56
        $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
1830
1831
        // The nil UUID is special form of UUID that is specified to have all
1832
        // 128 bits set to zero.
1833 56
        if ('00000000-0000-0000-0000-000000000000' === $value) {
1834 4
            return;
1835
        }
1836
1837 52
        if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) {
1838 20
            static::reportInvalidArgument(\sprintf(
1839 20
                $message ?: 'Value %s is not a valid UUID.',
1840 20
                static::valueToString($value)
1841
            ));
1842
        }
1843 32
    }
1844
1845
    /**
1846
     * @param Closure       $expression
1847
     * @param string|object $class
1848
     * @param string        $message
1849
     *
1850
     * @throws InvalidArgumentException
1851
     */
1852 24
    public static function throws(Closure $expression, $class = 'Exception', $message = '')
1853
    {
1854 24
        static::string($class);
1855
1856 24
        $actual = 'none';
1857
1858
        try {
1859 24
            $expression();
1860 24
        } catch (Exception $e) {
1861 20
            $actual = \get_class($e);
1862 20
            if ($e instanceof $class) {
1863 20
                return;
1864
            }
1865 4
        } 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...
1866 4
            $actual = \get_class($e);
1867 4
            if ($e instanceof $class) {
1868 4
                return;
1869
            }
1870
        }
1871
1872 8
        static::reportInvalidArgument($message ?: \sprintf(
1873 8
            'Expected to throw "%s", got "%s"',
1874 8
            $class,
1875 8
            $actual
1876
        ));
1877
    }
1878
1879
    /**
1880
     * @throws BadMethodCallException
1881
     */
1882 1561
    public static function __callStatic($name, $arguments)
1883
    {
1884 1561
        if ('nullOr' === \substr($name, 0, 6)) {
1885 578
            if (null !== $arguments[0]) {
1886 475
                $method = \lcfirst(\substr($name, 6));
1887 475
                \call_user_func_array(array('static', $method), $arguments);
1888
            }
1889
1890 334
            return;
1891
        }
1892
1893 983
        if ('all' === \substr($name, 0, 3)) {
1894 982
            static::isIterable($arguments[0]);
1895
1896 982
            $method = \lcfirst(\substr($name, 3));
1897 982
            $args = $arguments;
1898
1899 982
            foreach ($arguments[0] as $entry) {
1900 982
                $args[0] = $entry;
1901
1902 982
                \call_user_func_array(array('static', $method), $args);
1903
            }
1904
1905 470
            return;
1906
        }
1907
1908 1
        throw new BadMethodCallException('No such method: '.$name);
1909
    }
1910
1911
    /**
1912
     * @param mixed $value
1913
     *
1914
     * @return string
1915
     */
1916 714
    protected static function valueToString($value)
1917
    {
1918 714
        if (null === $value) {
1919 20
            return 'null';
1920
        }
1921
1922 696
        if (true === $value) {
1923 15
            return 'true';
1924
        }
1925
1926 686
        if (false === $value) {
1927 25
            return 'false';
1928
        }
1929
1930 661
        if (\is_array($value)) {
1931 21
            return 'array';
1932
        }
1933
1934 640
        if (\is_object($value)) {
1935 2
            if (\method_exists($value, '__toString')) {
1936 1
                return \get_class($value).': '.self::valueToString($value->__toString());
1937
            }
1938
1939 1
            return \get_class($value);
1940
        }
1941
1942 639
        if (\is_resource($value)) {
1943 1
            return 'resource';
1944
        }
1945
1946 639
        if (\is_string($value)) {
1947 537
            return '"'.$value.'"';
1948
        }
1949
1950 110
        return (string) $value;
1951
    }
1952
1953
    /**
1954
     * @param mixed $value
1955
     *
1956
     * @return string
1957
     */
1958 251
    protected static function typeToString($value)
1959
    {
1960 251
        return \is_object($value) ? \get_class($value) : \gettype($value);
1961
    }
1962
1963 168
    protected static function strlen($value)
1964
    {
1965 168
        if (!\function_exists('mb_detect_encoding')) {
1966
            return \strlen($value);
1967
        }
1968
1969 168
        if (false === $encoding = \mb_detect_encoding($value)) {
1970
            return \strlen($value);
1971
        }
1972
1973 168
        return \mb_strlen($value, $encoding);
1974
    }
1975
1976
    /**
1977
     * @param string $message
1978
     *
1979
     * @throws InvalidArgumentException
1980
     */
1981 1028
    protected static function reportInvalidArgument($message)
1982
    {
1983 1028
        throw new InvalidArgumentException($message);
1984
    }
1985
1986
    private function __construct()
1987
    {
1988
    }
1989
}
1990