Failed Conditions
Pull Request — master (#199)
by Tomasz
16:26 queued 15:14
created

Assert::notEq()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

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 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 DateTime;
19
use DateTimeImmutable;
20
use Exception;
21
use InvalidArgumentException;
22
use ResourceBundle;
23
use SimpleXMLElement;
24
use Throwable;
25
use Traversable;
26
27
/**
28
 * Efficient assertions to validate the input/output of your methods.
29
 *
30
 * @method static void nullOrString($value, $message = '')
31
 * @method static void nullOrStringNotEmpty($value, $message = '')
32
 * @method static void nullOrInteger($value, $message = '')
33
 * @method static void nullOrIntegerish($value, $message = '')
34
 * @method static void nullOrFloat($value, $message = '')
35
 * @method static void nullOrNumeric($value, $message = '')
36
 * @method static void nullOrNatural($value, $message = '')
37
 * @method static void nullOrBoolean($value, $message = '')
38
 * @method static void nullOrScalar($value, $message = '')
39
 * @method static void nullOrObject($value, $message = '')
40
 * @method static void nullOrResource($value, $type = null, $message = '')
41
 * @method static void nullOrIsCallable($value, $message = '')
42
 * @method static void nullOrIsArray($value, $message = '')
43
 * @method static void nullOrIsTraversable($value, $message = '')
44
 * @method static void nullOrIsArrayAccessible($value, $message = '')
45
 * @method static void nullOrIsCountable($value, $message = '')
46
 * @method static void nullOrIsIterable($value, $message = '')
47
 * @method static void nullOrIsInstanceOf($value, $class, $message = '')
48
 * @method static void nullOrNotInstanceOf($value, $class, $message = '')
49
 * @method static void nullOrIsInstanceOfAny($value, $classes, $message = '')
50
 * @method static void nullOrIsAOf($value, $classes, $message = '')
51
 * @method static void nullOrIsAnyOf($value, $classes, $message = '')
52
 * @method static void nullOrIsNotA($value, $classes, $message = '')
53
 * @method static void nullOrIsEmpty($value, $message = '')
54
 * @method static void nullOrNotEmpty($value, $message = '')
55
 * @method static void nullOrTrue($value, $message = '')
56
 * @method static void nullOrFalse($value, $message = '')
57
 * @method static void nullOrNotFalse($value, $message = '')
58
 * @method static void nullOrIp($value, $message = '')
59
 * @method static void nullOrIpv4($value, $message = '')
60
 * @method static void nullOrIpv6($value, $message = '')
61
 * @method static void nullOrUrl($value, $message = '')
62
 * @method static void nullOrEmail($value, $message = '')
63
 * @method static void nullOrUniqueValues($values, $message = '')
64
 * @method static void nullOrEq($value, $expect, $message = '')
65
 * @method static void nullOrNotEq($value, $expect, $message = '')
66
 * @method static void nullOrSame($value, $expect, $message = '')
67
 * @method static void nullOrNotSame($value, $expect, $message = '')
68
 * @method static void nullOrGreaterThan($value, $limit, $message = '')
69
 * @method static void nullOrGreaterThanEq($value, $limit, $message = '')
70
 * @method static void nullOrLessThan($value, $limit, $message = '')
71
 * @method static void nullOrLessThanEq($value, $limit, $message = '')
72
 * @method static void nullOrRange($value, $min, $max, $message = '')
73
 * @method static void nullOrOneOf($value, $values, $message = '')
74
 * @method static void nullOrInArray($value, $values, $message = '')
75
 * @method static void nullOrContains($value, $subString, $message = '')
76
 * @method static void nullOrNotContains($value, $subString, $message = '')
77
 * @method static void nullOrNotWhitespaceOnly($value, $message = '')
78
 * @method static void nullOrStartsWith($value, $prefix, $message = '')
79
 * @method static void nullOrNotStartsWith($value, $prefix, $message = '')
80
 * @method static void nullOrStartsWithLetter($value, $message = '')
81
 * @method static void nullOrEndsWith($value, $suffix, $message = '')
82
 * @method static void nullOrNotEndsWith($value, $suffix, $message = '')
83
 * @method static void nullOrRegex($value, $pattern, $message = '')
84
 * @method static void nullOrNotRegex($value, $pattern, $message = '')
85
 * @method static void nullOrUnicodeLetters($value, $message = '')
86
 * @method static void nullOrAlpha($value, $message = '')
87
 * @method static void nullOrDigits($value, $message = '')
88
 * @method static void nullOrAlnum($value, $message = '')
89
 * @method static void nullOrLower($value, $message = '')
90
 * @method static void nullOrUpper($value, $message = '')
91
 * @method static void nullOrLength($value, $length, $message = '')
92
 * @method static void nullOrMinLength($value, $min, $message = '')
93
 * @method static void nullOrMaxLength($value, $max, $message = '')
94
 * @method static void nullOrLengthBetween($value, $min, $max, $message = '')
95
 * @method static void nullOrFileExists($value, $message = '')
96
 * @method static void nullOrFile($value, $message = '')
97
 * @method static void nullOrDirectory($value, $message = '')
98
 * @method static void nullOrReadable($value, $message = '')
99
 * @method static void nullOrWritable($value, $message = '')
100
 * @method static void nullOrClassExists($value, $message = '')
101
 * @method static void nullOrSubclassOf($value, $class, $message = '')
102
 * @method static void nullOrInterfaceExists($value, $message = '')
103
 * @method static void nullOrImplementsInterface($value, $interface, $message = '')
104
 * @method static void nullOrPropertyExists($value, $property, $message = '')
105
 * @method static void nullOrPropertyNotExists($value, $property, $message = '')
106
 * @method static void nullOrMethodExists($value, $method, $message = '')
107
 * @method static void nullOrMethodNotExists($value, $method, $message = '')
108
 * @method static void nullOrKeyExists($value, $key, $message = '')
109
 * @method static void nullOrKeyNotExists($value, $key, $message = '')
110
 * @method static void nullOrValidArrayKey($value, $message = '')
111
 * @method static void nullOrCount($value, $key, $message = '')
112
 * @method static void nullOrMinCount($value, $min, $message = '')
113
 * @method static void nullOrMaxCount($value, $max, $message = '')
114
 * @method static void nullOrIsList($value, $message = '')
115
 * @method static void nullOrIsNonEmptyList($value, $message = '')
116
 * @method static void nullOrIsMap($value, $message = '')
117
 * @method static void nullOrIsNonEmptyMap($value, $message = '')
118
 * @method static void nullOrCountBetween($value, $min, $max, $message = '')
119
 * @method static void nullOrUuid($values, $message = '')
120
 * @method static void nullOrThrows($expression, $class = 'Exception', $message = '')
121
 * @method static void allString($values, $message = '')
122
 * @method static void allStringNotEmpty($values, $message = '')
123
 * @method static void allInteger($values, $message = '')
124
 * @method static void allIntegerish($values, $message = '')
125
 * @method static void allFloat($values, $message = '')
126
 * @method static void allNumeric($values, $message = '')
127
 * @method static void allNatural($values, $message = '')
128
 * @method static void allBoolean($values, $message = '')
129
 * @method static void allScalar($values, $message = '')
130
 * @method static void allObject($values, $message = '')
131
 * @method static void allResource($values, $type = null, $message = '')
132
 * @method static void allIsCallable($values, $message = '')
133
 * @method static void allIsArray($values, $message = '')
134
 * @method static void allIsTraversable($values, $message = '')
135
 * @method static void allIsArrayAccessible($values, $message = '')
136
 * @method static void allIsCountable($values, $message = '')
137
 * @method static void allIsIterable($values, $message = '')
138
 * @method static void allIsInstanceOf($values, $class, $message = '')
139
 * @method static void allNotInstanceOf($values, $class, $message = '')
140
 * @method static void allIsInstanceOfAny($values, $classes, $message = '')
141
 * @method static void allIsAOf($values, $class, $message = '')
142
 * @method static void allIsAnyOf($values, $class, $message = '')
143
 * @method static void allIsNotA($values, $class, $message = '')
144
 * @method static void allNull($values, $message = '')
145
 * @method static void allNotNull($values, $message = '')
146
 * @method static void allIsEmpty($values, $message = '')
147
 * @method static void allNotEmpty($values, $message = '')
148
 * @method static void allTrue($values, $message = '')
149
 * @method static void allFalse($values, $message = '')
150
 * @method static void allNotFalse($values, $message = '')
151
 * @method static void allIp($values, $message = '')
152
 * @method static void allIpv4($values, $message = '')
153
 * @method static void allIpv6($values, $message = '')
154
 * @method static void allUrl($values, $message = '')
155
 * @method static void allEmail($values, $message = '')
156
 * @method static void allUniqueValues($values, $message = '')
157
 * @method static void allEq($values, $expect, $message = '')
158
 * @method static void allNotEq($values, $expect, $message = '')
159
 * @method static void allSame($values, $expect, $message = '')
160
 * @method static void allNotSame($values, $expect, $message = '')
161
 * @method static void allGreaterThan($values, $limit, $message = '')
162
 * @method static void allGreaterThanEq($values, $limit, $message = '')
163
 * @method static void allLessThan($values, $limit, $message = '')
164
 * @method static void allLessThanEq($values, $limit, $message = '')
165
 * @method static void allRange($values, $min, $max, $message = '')
166
 * @method static void allOneOf($values, $values, $message = '')
167
 * @method static void allInArray($values, $values, $message = '')
168
 * @method static void allContains($values, $subString, $message = '')
169
 * @method static void allNotContains($values, $subString, $message = '')
170
 * @method static void allNotWhitespaceOnly($values, $message = '')
171
 * @method static void allStartsWith($values, $prefix, $message = '')
172
 * @method static void allNotStartsWith($values, $prefix, $message = '')
173
 * @method static void allStartsWithLetter($values, $message = '')
174
 * @method static void allEndsWith($values, $suffix, $message = '')
175
 * @method static void allNotEndsWith($values, $suffix, $message = '')
176
 * @method static void allRegex($values, $pattern, $message = '')
177
 * @method static void allNotRegex($values, $pattern, $message = '')
178
 * @method static void allUnicodeLetters($values, $message = '')
179
 * @method static void allAlpha($values, $message = '')
180
 * @method static void allDigits($values, $message = '')
181
 * @method static void allAlnum($values, $message = '')
182
 * @method static void allLower($values, $message = '')
183
 * @method static void allUpper($values, $message = '')
184
 * @method static void allLength($values, $length, $message = '')
185
 * @method static void allMinLength($values, $min, $message = '')
186
 * @method static void allMaxLength($values, $max, $message = '')
187
 * @method static void allLengthBetween($values, $min, $max, $message = '')
188
 * @method static void allFileExists($values, $message = '')
189
 * @method static void allFile($values, $message = '')
190
 * @method static void allDirectory($values, $message = '')
191
 * @method static void allReadable($values, $message = '')
192
 * @method static void allWritable($values, $message = '')
193
 * @method static void allClassExists($values, $message = '')
194
 * @method static void allSubclassOf($values, $class, $message = '')
195
 * @method static void allInterfaceExists($values, $message = '')
196
 * @method static void allImplementsInterface($values, $interface, $message = '')
197
 * @method static void allPropertyExists($values, $property, $message = '')
198
 * @method static void allPropertyNotExists($values, $property, $message = '')
199
 * @method static void allMethodExists($values, $method, $message = '')
200
 * @method static void allMethodNotExists($values, $method, $message = '')
201
 * @method static void allKeyExists($values, $key, $message = '')
202
 * @method static void allKeyNotExists($values, $key, $message = '')
203
 * @method static void allValidArrayKey($values, $message = '')
204
 * @method static void allCount($values, $key, $message = '')
205
 * @method static void allMinCount($values, $min, $message = '')
206
 * @method static void allMaxCount($values, $max, $message = '')
207
 * @method static void allCountBetween($values, $min, $max, $message = '')
208
 * @method static void allIsList($values, $message = '')
209
 * @method static void allIsNonEmptyList($values, $message = '')
210
 * @method static void allIsMap($values, $message = '')
211
 * @method static void allIsNonEmptyMap($values, $message = '')
212
 * @method static void allUuid($values, $message = '')
213
 * @method static void allThrows($expressions, $class = 'Exception', $message = '')
214
 *
215
 * @since  1.0
216
 *
217
 * @author Bernhard Schussek <[email protected]>
218
 */
219
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...
220
{
221
    /**
222
     * @psalm-pure
223
     * @psalm-assert string $value
224
     *
225
     * @param mixed  $value
226
     * @param string $message
227
     *
228
     * @throws InvalidArgumentException
229
     */
230 241
    public static function string($value, $message = '')
231
    {
232 241
        if (!\is_string($value)) {
233 45
            static::reportInvalidArgument(\sprintf(
234 45
                $message ?: 'Expected a string. Got: %s',
235 45
                static::typeToString($value)
236
            ));
237
        }
238 196
    }
239
240
    /**
241
     * @psalm-pure
242
     * @psalm-assert string $value
243
     * @psalm-assert !empty $value
244
     *
245
     * @param mixed  $value
246
     * @param string $message
247
     *
248
     * @throws InvalidArgumentException
249
     */
250 16
    public static function stringNotEmpty($value, $message = '')
251
    {
252 16
        static::string($value, $message);
253 12
        static::notEq($value, '', $message);
254 8
    }
255
256
    /**
257
     * @psalm-pure
258
     * @psalm-assert int $value
259
     *
260
     * @param mixed  $value
261
     * @param string $message
262
     *
263
     * @throws InvalidArgumentException
264
     */
265 17
    public static function integer($value, $message = '')
266
    {
267 17
        if (!\is_int($value)) {
268 13
            static::reportInvalidArgument(\sprintf(
269 13
                $message ?: 'Expected an integer. Got: %s',
270 13
                static::typeToString($value)
271
            ));
272
        }
273 4
    }
274
275
    /**
276
     * @psalm-pure
277
     * @psalm-assert numeric $value
278
     *
279
     * @param mixed  $value
280
     * @param string $message
281
     *
282
     * @throws InvalidArgumentException
283
     */
284 16
    public static function integerish($value, $message = '')
285
    {
286 16
        if (!\is_numeric($value) || $value != (int) $value) {
287 4
            static::reportInvalidArgument(\sprintf(
288 4
                $message ?: 'Expected an integerish value. Got: %s',
289 4
                static::typeToString($value)
290
            ));
291
        }
292 12
    }
293
294
    /**
295
     * @psalm-pure
296
     * @psalm-assert float $value
297
     *
298
     * @param mixed  $value
299
     * @param string $message
300
     *
301
     * @throws InvalidArgumentException
302
     */
303 16
    public static function float($value, $message = '')
304
    {
305 16
        if (!\is_float($value)) {
306 8
            static::reportInvalidArgument(\sprintf(
307 8
                $message ?: 'Expected a float. Got: %s',
308 8
                static::typeToString($value)
309
            ));
310
        }
311 8
    }
312
313
    /**
314
     * @psalm-pure
315
     * @psalm-assert numeric $value
316
     *
317
     * @param mixed  $value
318
     * @param string $message
319
     *
320
     * @throws InvalidArgumentException
321
     */
322 20
    public static function numeric($value, $message = '')
323
    {
324 20
        if (!\is_numeric($value)) {
325 4
            static::reportInvalidArgument(\sprintf(
326 4
                $message ?: 'Expected a numeric. Got: %s',
327 4
                static::typeToString($value)
328
            ));
329
        }
330 16
    }
331
332
    /**
333
     * @psalm-pure
334
     * @psalm-assert int $value
335
     *
336
     * @param mixed  $value
337
     * @param string $message
338
     *
339
     * @throws InvalidArgumentException
340
     */
341 24
    public static function natural($value, $message = '')
342
    {
343 24
        if (!\is_int($value) || $value < 0) {
344 16
            static::reportInvalidArgument(\sprintf(
345 16
                $message ?: 'Expected a non-negative integer. Got: %s',
346 16
                static::valueToString($value)
347
            ));
348
        }
349 8
    }
350
351
    /**
352
     * @psalm-pure
353
     * @psalm-assert bool $value
354
     *
355
     * @param mixed  $value
356
     * @param string $message
357
     *
358
     * @throws InvalidArgumentException
359
     */
360 16
    public static function boolean($value, $message = '')
361
    {
362 16
        if (!\is_bool($value)) {
363 8
            static::reportInvalidArgument(\sprintf(
364 8
                $message ?: 'Expected a boolean. Got: %s',
365 8
                static::typeToString($value)
366
            ));
367
        }
368 8
    }
369
370
    /**
371
     * @psalm-pure
372
     * @psalm-assert scalar $value
373
     *
374
     * @param mixed  $value
375
     * @param string $message
376
     *
377
     * @throws InvalidArgumentException
378
     */
379 23
    public static function scalar($value, $message = '')
380
    {
381 23
        if (!\is_scalar($value)) {
382 11
            static::reportInvalidArgument(\sprintf(
383 11
                $message ?: 'Expected a scalar. Got: %s',
384 11
                static::typeToString($value)
385
            ));
386
        }
387 12
    }
388
389
    /**
390
     * @psalm-pure
391
     * @psalm-assert object $value
392
     *
393
     * @param mixed  $value
394
     * @param string $message
395
     *
396
     * @throws InvalidArgumentException
397
     */
398 23
    public static function object($value, $message = '')
399
    {
400 23
        if (!\is_object($value)) {
401 15
            static::reportInvalidArgument(\sprintf(
402 15
                $message ?: 'Expected an object. Got: %s',
403 15
                static::typeToString($value)
404
            ));
405
        }
406 8
    }
407
408
    /**
409
     * @psalm-pure
410
     * @psalm-assert resource $value
411
     *
412
     * @param mixed       $value
413
     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
414
     * @param string      $message
415
     *
416
     * @throws InvalidArgumentException
417
     */
418 16
    public static function resource($value, $type = null, $message = '')
419
    {
420 16
        if (!\is_resource($value)) {
421 4
            static::reportInvalidArgument(\sprintf(
422 4
                $message ?: 'Expected a resource. Got: %s',
423 4
                static::typeToString($value)
424
            ));
425
        }
426
427 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...
428 4
            static::reportInvalidArgument(\sprintf(
429 4
                $message ?: 'Expected a resource of type %2$s. Got: %s',
430 4
                static::typeToString($value),
431 4
                $type
432
            ));
433
        }
434 8
    }
435
436
    /**
437
     * @psalm-pure
438
     * @psalm-assert callable $value
439
     *
440
     * @param mixed  $value
441
     * @param string $message
442
     *
443
     * @throws InvalidArgumentException
444
     */
445 20
    public static function isCallable($value, $message = '')
446
    {
447 20
        if (!\is_callable($value)) {
448 8
            static::reportInvalidArgument(\sprintf(
449 8
                $message ?: 'Expected a callable. Got: %s',
450 8
                static::typeToString($value)
451
            ));
452
        }
453 12
    }
454
455
    /**
456
     * @psalm-pure
457
     * @psalm-assert array $value
458
     *
459
     * @param mixed  $value
460
     * @param string $message
461
     *
462
     * @throws InvalidArgumentException
463
     */
464 20
    public static function isArray($value, $message = '')
465
    {
466 20
        if (!\is_array($value)) {
467 12
            static::reportInvalidArgument(\sprintf(
468 12
                $message ?: 'Expected an array. Got: %s',
469 12
                static::typeToString($value)
470
            ));
471
        }
472 8
    }
473
474
    /**
475
     * @psalm-pure
476
     * @psalm-assert iterable $value
477
     *
478
     * @deprecated use "isIterable" or "isInstanceOf" instead
479
     *
480
     * @param mixed  $value
481
     * @param string $message
482
     *
483
     * @throws InvalidArgumentException
484
     */
485 20
    public static function isTraversable($value, $message = '')
486
    {
487 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...
488 20
            \sprintf(
489 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.',
490 20
                __METHOD__
491
            ),
492 20
            \E_USER_DEPRECATED
493
        );
494
495 20
        if (!\is_array($value) && !($value instanceof Traversable)) {
496 8
            static::reportInvalidArgument(\sprintf(
497 8
                $message ?: 'Expected a traversable. Got: %s',
498 8
                static::typeToString($value)
499
            ));
500
        }
501 12
    }
502
503
    /**
504
     * @psalm-pure
505
     * @psalm-assert array|ArrayAccess $value
506
     *
507
     * @param mixed  $value
508
     * @param string $message
509
     *
510
     * @throws InvalidArgumentException
511
     */
512 20 View Code Duplication
    public static function isArrayAccessible($value, $message = '')
513
    {
514 20
        if (!\is_array($value) && !($value instanceof ArrayAccess)) {
515 8
            static::reportInvalidArgument(\sprintf(
516 8
                $message ?: 'Expected an array accessible. Got: %s',
517 8
                static::typeToString($value)
518
            ));
519
        }
520 12
    }
521
522
    /**
523
     * @psalm-pure
524
     * @psalm-assert countable $value
525
     *
526
     * @param mixed  $value
527
     * @param string $message
528
     *
529
     * @throws InvalidArgumentException
530
     */
531 28
    public static function isCountable($value, $message = '')
532
    {
533
        if (
534 28
            !\is_array($value)
535 28
            && !($value instanceof Countable)
536 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...
537 28
            && !($value instanceof SimpleXMLElement)
538
        ) {
539 12
            static::reportInvalidArgument(\sprintf(
540 12
                $message ?: 'Expected a countable. Got: %s',
541 12
                static::typeToString($value)
542
            ));
543
        }
544 16
    }
545
546
    /**
547
     * @psalm-pure
548
     * @psalm-assert iterable $value
549
     *
550
     * @param mixed  $value
551
     * @param string $message
552
     *
553
     * @throws InvalidArgumentException
554
     */
555 1214 View Code Duplication
    public static function isIterable($value, $message = '')
556
    {
557 1214
        if (!\is_array($value) && !($value instanceof Traversable)) {
558 8
            static::reportInvalidArgument(\sprintf(
559 8
                $message ?: 'Expected an iterable. Got: %s',
560 8
                static::typeToString($value)
561
            ));
562
        }
563 1210
    }
564
565
    /**
566
     * @psalm-pure
567
     * @psalm-template ExpectedType of object
568
     * @psalm-param class-string<ExpectedType> $class
569
     * @psalm-assert ExpectedType $value
570
     *
571
     * @param mixed         $value
572
     * @param string|object $class
573
     * @param string        $message
574
     *
575
     * @throws InvalidArgumentException
576
     */
577 19
    public static function isInstanceOf($value, $class, $message = '')
578
    {
579 19
        if (!($value instanceof $class)) {
580 15
            static::reportInvalidArgument(\sprintf(
581 15
                $message ?: 'Expected an instance of %2$s. Got: %s',
582 15
                static::typeToString($value),
583 15
                $class
584
            ));
585
        }
586 4
    }
587
588
    /**
589
     * @psalm-pure
590
     * @psalm-template ExpectedType of object
591
     * @psalm-param class-string<ExpectedType> $class
592
     * @psalm-assert !ExpectedType $value
593
     *
594
     * @param mixed         $value
595
     * @param string|object $class
596
     * @param string        $message
597
     *
598
     * @throws InvalidArgumentException
599
     */
600 16
    public static function notInstanceOf($value, $class, $message = '')
601
    {
602 16
        if ($value instanceof $class) {
603 4
            static::reportInvalidArgument(\sprintf(
604 4
                $message ?: 'Expected an instance other than %2$s. Got: %s',
605 4
                static::typeToString($value),
606 4
                $class
607
            ));
608
        }
609 12
    }
610
611
    /**
612
     * @psalm-pure
613
     * @psalm-param array<class-string> $classes
614
     *
615
     * @param mixed                $value
616
     * @param array<object|string> $classes
617
     * @param string               $message
618
     *
619
     * @throws InvalidArgumentException
620
     */
621 20
    public static function isInstanceOfAny($value, array $classes, $message = '')
622
    {
623 20
        foreach ($classes as $class) {
624 20
            if ($value instanceof $class) {
625 8
                return;
626
            }
627
        }
628
629 12
        static::reportInvalidArgument(\sprintf(
630 12
            $message ?: 'Expected an instance of any of %2$s. Got: %s',
631 12
            static::typeToString($value),
632 12
            \implode(', ', \array_map(array('static', 'valueToString'), $classes))
633
        ));
634
    }
635
636
    /**
637
     * @psalm-pure
638
     * @psalm-template ExpectedType of object
639
     * @psalm-param class-string<ExpectedType> $class
640
     * @psalm-assert ExpectedType|class-string<ExpectedType> $value
641
     *
642
     * @param object|string $value
643
     * @param string        $class
644
     * @param string        $message
645
     *
646
     * @throws InvalidArgumentException
647
     */
648 20 View Code Duplication
    public static function isAOf($value, $class, $message = '')
649
    {
650 20
        static::string($class, 'Expected class as a string. Got: %s');
651
652 16
        if (!\is_a($value, $class, \is_string($value))) {
653 12
            static::reportInvalidArgument(sprintf(
654 12
                $message ?: 'Expected an instance of this class or to this class among his parents %2$s. Got: %s',
655 12
                static::typeToString($value),
656
                $class
657
            ));
658
        }
659 4
    }
660
661
    /**
662
     * @psalm-pure
663
     * @psalm-template UnexpectedType of object
664
     * @psalm-param class-string<UnexpectedType> $class
665
     * @psalm-assert !UnexpectedType $value
666
     * @psalm-assert !class-string<UnexpectedType> $value
667
     *
668
     * @param object|string $value
669
     * @param string        $class
670
     * @param string        $message
671
     *
672
     * @throws InvalidArgumentException
673
     */
674 20 View Code Duplication
    public static function isNotA($value, $class, $message = '')
675
    {
676 20
        static::string($class, 'Expected class as a string. Got: %s');
677
678 16
        if (\is_a($value, $class, \is_string($value))) {
679 4
            static::reportInvalidArgument(sprintf(
680 4
                $message ?: 'Expected an instance of this class or to this class among his parents other than %2$s. Got: %s',
681 4
                static::typeToString($value),
682
                $class
683
            ));
684
        }
685 12
    }
686
687
    /**
688
     * @psalm-pure
689
     * @psalm-param array<class-string> $classes
690
     *
691
     * @param object|string $value
692
     * @param string[]      $classes
693
     * @param string        $message
694
     *
695
     * @throws InvalidArgumentException
696
     */
697 24
    public static function isAnyOf($value, array $classes, $message = '')
698
    {
699 24
        foreach ($classes as $class) {
700 24
            static::string($class, 'Expected class as a string. Got: %s');
701
702 20
            if (\is_a($value, $class, \is_string($value))) {
703 8
                return;
704
            }
705
        }
706
707 12
        static::reportInvalidArgument(sprintf(
708 12
            $message ?: 'Expected an any of instance of this class or to this class among his parents other than %2$s. Got: %s',
709 12
            static::typeToString($value),
710 12
            \implode(', ', \array_map(array('static', 'valueToString'), $classes))
711
        ));
712
    }
713
714
    /**
715
     * @psalm-pure
716
     * @psalm-assert empty $value
717
     *
718
     * @param mixed  $value
719
     * @param string $message
720
     *
721
     * @throws InvalidArgumentException
722
     */
723 23
    public static function isEmpty($value, $message = '')
724
    {
725 23
        if (!empty($value)) {
726 8
            static::reportInvalidArgument(\sprintf(
727 8
                $message ?: 'Expected an empty value. Got: %s',
728 8
                static::valueToString($value)
729
            ));
730
        }
731 15
    }
732
733
    /**
734
     * @psalm-pure
735
     * @psalm-assert !empty $value
736
     *
737
     * @param mixed  $value
738
     * @param string $message
739
     *
740
     * @throws InvalidArgumentException
741
     */
742 55
    public static function notEmpty($value, $message = '')
743
    {
744 55
        if (empty($value)) {
745 23
            static::reportInvalidArgument(\sprintf(
746 23
                $message ?: 'Expected a non-empty value. Got: %s',
747 23
                static::valueToString($value)
748
            ));
749
        }
750 32
    }
751
752
    /**
753
     * @psalm-pure
754
     * @psalm-assert null $value
755
     *
756
     * @param mixed  $value
757
     * @param string $message
758
     *
759
     * @throws InvalidArgumentException
760
     */
761 11
    public static function null($value, $message = '')
762
    {
763 11
        if (null !== $value) {
764 8
            static::reportInvalidArgument(\sprintf(
765 8
                $message ?: 'Expected null. Got: %s',
766 8
                static::valueToString($value)
767
            ));
768
        }
769 3
    }
770
771
    /**
772
     * @psalm-pure
773
     * @psalm-assert !null $value
774
     *
775
     * @param mixed  $value
776
     * @param string $message
777
     *
778
     * @throws InvalidArgumentException
779
     */
780 11
    public static function notNull($value, $message = '')
781
    {
782 11
        if (null === $value) {
783 3
            static::reportInvalidArgument(
784 3
                $message ?: 'Expected a value other than null.'
785
            );
786
        }
787 8
    }
788
789
    /**
790
     * @psalm-pure
791
     * @psalm-assert true $value
792
     *
793
     * @param mixed  $value
794
     * @param string $message
795
     *
796
     * @throws InvalidArgumentException
797
     */
798 15
    public static function true($value, $message = '')
799
    {
800 15
        if (true !== $value) {
801 11
            static::reportInvalidArgument(\sprintf(
802 11
                $message ?: 'Expected a value to be true. Got: %s',
803 11
                static::valueToString($value)
804
            ));
805
        }
806 4
    }
807
808
    /**
809
     * @psalm-pure
810
     * @psalm-assert false $value
811
     *
812
     * @param mixed  $value
813
     * @param string $message
814
     *
815
     * @throws InvalidArgumentException
816
     */
817 19
    public static function false($value, $message = '')
818
    {
819 19
        if (false !== $value) {
820 15
            static::reportInvalidArgument(\sprintf(
821 15
                $message ?: 'Expected a value to be false. Got: %s',
822 15
                static::valueToString($value)
823
            ));
824
        }
825 4
    }
826
827
    /**
828
     * @psalm-pure
829
     * @psalm-assert !false $value
830
     *
831
     * @param mixed  $value
832
     * @param string $message
833
     *
834
     * @throws InvalidArgumentException
835
     */
836 19
    public static function notFalse($value, $message = '')
837
    {
838 19
        if (false === $value) {
839 4
            static::reportInvalidArgument(
840 4
                $message ?: 'Expected a value other than false.'
841
            );
842
        }
843 15
    }
844
845
    /**
846
     * @param mixed  $value
847
     * @param string $message
848
     *
849
     * @throws InvalidArgumentException
850
     */
851 51 View Code Duplication
    public static function ip($value, $message = '')
852
    {
853 51
        if (false === \filter_var($value, \FILTER_VALIDATE_IP)) {
854 19
            static::reportInvalidArgument(\sprintf(
855 19
                $message ?: 'Expected a value to be an IP. Got: %s',
856 19
                static::valueToString($value)
857
            ));
858
        }
859 32
    }
860
861
    /**
862
     * @param mixed  $value
863
     * @param string $message
864
     *
865
     * @throws InvalidArgumentException
866
     */
867 51 View Code Duplication
    public static function ipv4($value, $message = '')
868
    {
869 51
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
870 35
            static::reportInvalidArgument(\sprintf(
871 35
                $message ?: 'Expected a value to be an IPv4. Got: %s',
872 35
                static::valueToString($value)
873
            ));
874
        }
875 16
    }
876
877
    /**
878
     * @param mixed  $value
879
     * @param string $message
880
     *
881
     * @throws InvalidArgumentException
882
     */
883 51 View Code Duplication
    public static function ipv6($value, $message = '')
884
    {
885 51
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
886 31
            static::reportInvalidArgument(\sprintf(
887 31
                $message ?: 'Expected a value to be an IPv6. Got: %s',
888 31
                static::valueToString($value)
889
            ));
890
        }
891 20
    }
892
893
    /**
894
     * @psalm-pure
895
     *
896
     * @param string $value
897
     * @param string $message
898
     *
899
     * @throws InvalidArgumentException
900
     *
901
     * The URL pattern is taken from Symfony: @see https://github.com/symfony/Validator/blob/master/Constraints/UrlValidator.php
902
     */
903 340 View Code Duplication
    public static function url($value, $message = '')
904
    {
905 340
        $pattern = '~^
906
            (http|https)://                                                                     # protocol
907
            (((?:[\_\.\pL\pN-]|%%[0-9A-Fa-f]{2})+:)?((?:[\_\.\pL\pN-]|%%[0-9A-Fa-f]{2})+)@)?    # basic auth
908
            (
909
                ([\pL\pN\pS\-\_\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?)                        # a domain name
910
                    |                                                                           # or
911
                \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}                                              # an IP address
912
                    |                                                                           # or
913
                \[
914
                    (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::))))
915
                \]                                                                              # an IPv6 address
916
            )
917
            (:[0-9]+)?                                                                          # a port (optional)
918
            (?:/ (?:[\pL\pN\-._\~!$&\'()*+,;=:@]|%%[0-9A-Fa-f]{2})* )*                          # a path
919
            (?:\? (?:[\pL\pN\-._\~!$&\'\[\]()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )?                   # a query (optional)
920
            (?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )?                       # a fragment (optional)
921
        $~ixu';
922
923 340
        if (!\preg_match($pattern, $value)) {
924 88
            static::reportInvalidArgument(\sprintf(
925 88
                $message ?: 'Expected a value to be a valid URL. Got %s',
926 88
                static::valueToString($value)
927
            ));
928
        }
929 252
    }
930
931
    /**
932
     * @param mixed  $value
933
     * @param string $message
934
     *
935
     * @throws InvalidArgumentException
936
     */
937 20 View Code Duplication
    public static function email($value, $message = '')
938
    {
939 20
        if (false === \filter_var($value, FILTER_VALIDATE_EMAIL)) {
940 12
            static::reportInvalidArgument(\sprintf(
941 12
                $message ?: 'Expected a value to be a valid e-mail address. Got: %s',
942 12
                static::valueToString($value)
943
            ));
944
        }
945 8
    }
946
947
    /**
948
     * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion.
949
     *
950
     * @param array  $values
951
     * @param string $message
952
     *
953
     * @throws InvalidArgumentException
954
     */
955 12
    public static function uniqueValues(array $values, $message = '')
956
    {
957 12
        $allValues = \count($values);
958 12
        $uniqueValues = \count(\array_unique($values));
959
960 12
        if ($allValues !== $uniqueValues) {
961 8
            $difference = $allValues - $uniqueValues;
962
963 8
            static::reportInvalidArgument(\sprintf(
964 8
                $message ?: 'Expected an array of unique values, but %s of them %s duplicated',
965 8
                $difference,
966 8
                (1 === $difference ? 'is' : 'are')
967
            ));
968
        }
969 4
    }
970
971
    /**
972
     * @param mixed  $value
973
     * @param mixed  $expect
974
     * @param string $message
975
     *
976
     * @throws InvalidArgumentException
977
     */
978 33
    public static function eq($value, $expect, $message = '')
979
    {
980 33
        if ($expect != $value) {
981 17
            static::reportInvalidArgument(\sprintf(
982 17
                $message ?: 'Expected a value equal to %2$s. Got: %s',
983 17
                static::valueToString($value),
984 17
                static::valueToString($expect)
985
            ));
986
        }
987 16
    }
988
989
    /**
990
     * @param mixed  $value
991
     * @param mixed  $expect
992
     * @param string $message
993
     *
994
     * @throws InvalidArgumentException
995
     */
996 28
    public static function notEq($value, $expect, $message = '')
997
    {
998 28
        if ($expect == $value) {
999 16
            static::reportInvalidArgument(\sprintf(
1000 16
                $message ?: 'Expected a different value than %s.',
1001 16
                static::valueToString($expect)
1002
            ));
1003
        }
1004 12
    }
1005
1006
    /**
1007
     * @psalm-pure
1008
     *
1009
     * @param mixed  $value
1010
     * @param mixed  $expect
1011
     * @param string $message
1012
     *
1013
     * @throws InvalidArgumentException
1014
     */
1015 16
    public static function same($value, $expect, $message = '')
1016
    {
1017 16
        if ($expect !== $value) {
1018 12
            static::reportInvalidArgument(\sprintf(
1019 12
                $message ?: 'Expected a value identical to %2$s. Got: %s',
1020 12
                static::valueToString($value),
1021 12
                static::valueToString($expect)
1022
            ));
1023
        }
1024 4
    }
1025
1026
    /**
1027
     * @psalm-pure
1028
     *
1029
     * @param mixed  $value
1030
     * @param mixed  $expect
1031
     * @param string $message
1032
     *
1033
     * @throws InvalidArgumentException
1034
     */
1035 16
    public static function notSame($value, $expect, $message = '')
1036
    {
1037 16
        if ($expect === $value) {
1038 4
            static::reportInvalidArgument(\sprintf(
1039 4
                $message ?: 'Expected a value not identical to %s.',
1040 4
                static::valueToString($expect)
1041
            ));
1042
        }
1043 12
    }
1044
1045
    /**
1046
     * @psalm-pure
1047
     *
1048
     * @param mixed  $value
1049
     * @param mixed  $limit
1050
     * @param string $message
1051
     *
1052
     * @throws InvalidArgumentException
1053
     */
1054 8
    public static function greaterThan($value, $limit, $message = '')
1055
    {
1056 8
        if ($value <= $limit) {
1057 4
            static::reportInvalidArgument(\sprintf(
1058 4
                $message ?: 'Expected a value greater than %2$s. Got: %s',
1059 4
                static::valueToString($value),
1060 4
                static::valueToString($limit)
1061
            ));
1062
        }
1063 4
    }
1064
1065
    /**
1066
     * @psalm-pure
1067
     *
1068
     * @param mixed  $value
1069
     * @param mixed  $limit
1070
     * @param string $message
1071
     *
1072
     * @throws InvalidArgumentException
1073
     */
1074 12
    public static function greaterThanEq($value, $limit, $message = '')
1075
    {
1076 12
        if ($value < $limit) {
1077 4
            static::reportInvalidArgument(\sprintf(
1078 4
                $message ?: 'Expected a value greater than or equal to %2$s. Got: %s',
1079 4
                static::valueToString($value),
1080 4
                static::valueToString($limit)
1081
            ));
1082
        }
1083 8
    }
1084
1085
    /**
1086
     * @psalm-pure
1087
     *
1088
     * @param mixed  $value
1089
     * @param mixed  $limit
1090
     * @param string $message
1091
     *
1092
     * @throws InvalidArgumentException
1093
     */
1094 9
    public static function lessThan($value, $limit, $message = '')
1095
    {
1096 9
        if ($value >= $limit) {
1097 5
            static::reportInvalidArgument(\sprintf(
1098 5
                $message ?: 'Expected a value less than %2$s. Got: %s',
1099 5
                static::valueToString($value),
1100 5
                static::valueToString($limit)
1101
            ));
1102
        }
1103 4
    }
1104
1105
    /**
1106
     * @psalm-pure
1107
     *
1108
     * @param mixed  $value
1109
     * @param mixed  $limit
1110
     * @param string $message
1111
     *
1112
     * @throws InvalidArgumentException
1113
     */
1114 12
    public static function lessThanEq($value, $limit, $message = '')
1115
    {
1116 12
        if ($value > $limit) {
1117 4
            static::reportInvalidArgument(\sprintf(
1118 4
                $message ?: 'Expected a value less than or equal to %2$s. Got: %s',
1119 4
                static::valueToString($value),
1120 4
                static::valueToString($limit)
1121
            ));
1122
        }
1123 8
    }
1124
1125
    /**
1126
     * Inclusive range, so Assert::(3, 3, 5) passes.
1127
     *
1128
     * @psalm-pure
1129
     *
1130
     * @param mixed  $value
1131
     * @param mixed  $min
1132
     * @param mixed  $max
1133
     * @param string $message
1134
     *
1135
     * @throws InvalidArgumentException
1136
     */
1137 16 View Code Duplication
    public static function range($value, $min, $max, $message = '')
1138
    {
1139 16
        if ($value < $min || $value > $max) {
1140 8
            static::reportInvalidArgument(\sprintf(
1141 8
                $message ?: 'Expected a value between %2$s and %3$s. Got: %s',
1142 8
                static::valueToString($value),
1143 8
                static::valueToString($min),
1144 8
                static::valueToString($max)
1145
            ));
1146
        }
1147 8
    }
1148
1149
    /**
1150
     * A more human-readable alias of Assert::inArray().
1151
     *
1152
     * @psalm-pure
1153
     *
1154
     * @param mixed  $value
1155
     * @param array  $values
1156
     * @param string $message
1157
     *
1158
     * @throws InvalidArgumentException
1159
     */
1160 8
    public static function oneOf($value, array $values, $message = '')
1161
    {
1162 8
        static::inArray($value, $values, $message);
1163 4
    }
1164
1165
    /**
1166
     * Does strict comparison, so Assert::inArray(3, ['3']) does not pass the assertion.
1167
     *
1168
     * @psalm-pure
1169
     *
1170
     * @param mixed  $value
1171
     * @param array  $values
1172
     * @param string $message
1173
     *
1174
     * @throws InvalidArgumentException
1175
     */
1176 16
    public static function inArray($value, array $values, $message = '')
1177
    {
1178 16
        if (!\in_array($value, $values, true)) {
1179 8
            static::reportInvalidArgument(\sprintf(
1180 8
                $message ?: 'Expected one of: %2$s. Got: %s',
1181 8
                static::valueToString($value),
1182 8
                \implode(', ', \array_map(array('static', 'valueToString'), $values))
1183
            ));
1184
        }
1185 8
    }
1186
1187
    /**
1188
     * @psalm-pure
1189
     *
1190
     * @param string $value
1191
     * @param string $subString
1192
     * @param string $message
1193
     *
1194
     * @throws InvalidArgumentException
1195
     */
1196 80 View Code Duplication
    public static function contains($value, $subString, $message = '')
1197
    {
1198 80
        if (false === \strpos($value, $subString)) {
1199 32
            static::reportInvalidArgument(\sprintf(
1200 32
                $message ?: 'Expected a value to contain %2$s. Got: %s',
1201 32
                static::valueToString($value),
1202 32
                static::valueToString($subString)
1203
            ));
1204
        }
1205 48
    }
1206
1207
    /**
1208
     * @psalm-pure
1209
     *
1210
     * @param string $value
1211
     * @param string $subString
1212
     * @param string $message
1213
     *
1214
     * @throws InvalidArgumentException
1215
     */
1216 80 View Code Duplication
    public static function notContains($value, $subString, $message = '')
1217
    {
1218 80
        if (false !== \strpos($value, $subString)) {
1219 48
            static::reportInvalidArgument(\sprintf(
1220 48
                $message ?: '%2$s was not expected to be contained in a value. Got: %s',
1221 48
                static::valueToString($value),
1222 48
                static::valueToString($subString)
1223
            ));
1224
        }
1225 32
    }
1226
1227
    /**
1228
     * @psalm-pure
1229
     *
1230
     * @param string $value
1231
     * @param string $message
1232
     *
1233
     * @throws InvalidArgumentException
1234
     */
1235 40 View Code Duplication
    public static function notWhitespaceOnly($value, $message = '')
1236
    {
1237 40
        if (\preg_match('/^\s*$/', $value)) {
1238 24
            static::reportInvalidArgument(\sprintf(
1239 24
                $message ?: 'Expected a non-whitespace string. Got: %s',
1240 24
                static::valueToString($value)
1241
            ));
1242
        }
1243 16
    }
1244
1245
    /**
1246
     * @psalm-pure
1247
     *
1248
     * @param string $value
1249
     * @param string $prefix
1250
     * @param string $message
1251
     *
1252
     * @throws InvalidArgumentException
1253
     */
1254 48 View Code Duplication
    public static function startsWith($value, $prefix, $message = '')
1255
    {
1256 48
        if (0 !== \strpos($value, $prefix)) {
1257 32
            static::reportInvalidArgument(\sprintf(
1258 32
                $message ?: 'Expected a value to start with %2$s. Got: %s',
1259 32
                static::valueToString($value),
1260 32
                static::valueToString($prefix)
1261
            ));
1262
        }
1263 16
    }
1264
1265
    /**
1266
     * @psalm-pure
1267
     *
1268
     * @param string $value
1269
     * @param string $prefix
1270
     * @param string $message
1271
     *
1272
     * @throws InvalidArgumentException
1273
     */
1274 48 View Code Duplication
    public static function notStartsWith($value, $prefix, $message = '')
1275
    {
1276 48
        if (0 === \strpos($value, $prefix)) {
1277 16
            static::reportInvalidArgument(\sprintf(
1278 16
                $message ?: 'Expected a value not to start with %2$s. Got: %s',
1279 16
                static::valueToString($value),
1280 16
                static::valueToString($prefix)
1281
            ));
1282
        }
1283 32
    }
1284
1285
    /**
1286
     * @psalm-pure
1287
     *
1288
     * @param mixed  $value
1289
     * @param string $message
1290
     *
1291
     * @throws InvalidArgumentException
1292
     */
1293 35
    public static function startsWithLetter($value, $message = '')
1294
    {
1295 35
        static::string($value);
1296
1297 24
        $valid = isset($value[0]);
1298
1299 24
        if ($valid) {
1300 20
            $locale = \setlocale(LC_CTYPE, 0);
1301 20
            \setlocale(LC_CTYPE, 'C');
1302 20
            $valid = \ctype_alpha($value[0]);
1303 20
            \setlocale(LC_CTYPE, $locale);
1304
        }
1305
1306 24
        if (!$valid) {
1307 12
            static::reportInvalidArgument(\sprintf(
1308 12
                $message ?: 'Expected a value to start with a letter. Got: %s',
1309 12
                static::valueToString($value)
1310
            ));
1311
        }
1312 12
    }
1313
1314
    /**
1315
     * @psalm-pure
1316
     *
1317
     * @param string $value
1318
     * @param string $suffix
1319
     * @param string $message
1320
     *
1321
     * @throws InvalidArgumentException
1322
     */
1323 48 View Code Duplication
    public static function endsWith($value, $suffix, $message = '')
1324
    {
1325 48
        if ($suffix !== \substr($value, -\strlen($suffix))) {
1326 32
            static::reportInvalidArgument(\sprintf(
1327 32
                $message ?: 'Expected a value to end with %2$s. Got: %s',
1328 32
                static::valueToString($value),
1329 32
                static::valueToString($suffix)
1330
            ));
1331
        }
1332 16
    }
1333
1334
    /**
1335
     * @psalm-pure
1336
     *
1337
     * @param string $value
1338
     * @param string $suffix
1339
     * @param string $message
1340
     *
1341
     * @throws InvalidArgumentException
1342
     */
1343 48 View Code Duplication
    public static function notEndsWith($value, $suffix, $message = '')
1344
    {
1345 48
        if ($suffix === \substr($value, -\strlen($suffix))) {
1346 16
            static::reportInvalidArgument(\sprintf(
1347 16
                $message ?: 'Expected a value not to end with %2$s. Got: %s',
1348 16
                static::valueToString($value),
1349 16
                static::valueToString($suffix)
1350
            ));
1351
        }
1352 32
    }
1353
1354
    /**
1355
     * @psalm-pure
1356
     *
1357
     * @param string $value
1358
     * @param string $pattern
1359
     * @param string $message
1360
     *
1361
     * @throws InvalidArgumentException
1362
     */
1363 12 View Code Duplication
    public static function regex($value, $pattern, $message = '')
1364
    {
1365 12
        if (!\preg_match($pattern, $value)) {
1366 8
            static::reportInvalidArgument(\sprintf(
1367 8
                $message ?: 'The value %s does not match the expected pattern.',
1368 8
                static::valueToString($value)
1369
            ));
1370
        }
1371 4
    }
1372
1373
    /**
1374
     * @psalm-pure
1375
     *
1376
     * @param string $value
1377
     * @param string $pattern
1378
     * @param string $message
1379
     *
1380
     * @throws InvalidArgumentException
1381
     */
1382 12
    public static function notRegex($value, $pattern, $message = '')
1383
    {
1384 12
        if (\preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) {
1385 4
            static::reportInvalidArgument(\sprintf(
1386 4
                $message ?: 'The value %s matches the pattern %s (at offset %d).',
1387 4
                static::valueToString($value),
1388 4
                static::valueToString($pattern),
1389 4
                $matches[0][1]
1390
            ));
1391
        }
1392 8
    }
1393
1394
    /**
1395
     * @psalm-pure
1396
     *
1397
     * @param mixed  $value
1398
     * @param string $message
1399
     *
1400
     * @throws InvalidArgumentException
1401
     */
1402 28 View Code Duplication
    public static function unicodeLetters($value, $message = '')
1403
    {
1404 28
        static::string($value);
1405
1406 28
        if (!\preg_match('/^\p{L}+$/u', $value)) {
1407 16
            static::reportInvalidArgument(\sprintf(
1408 16
                $message ?: 'Expected a value to contain only Unicode letters. Got: %s',
1409 16
                static::valueToString($value)
1410
            ));
1411
        }
1412 12
    }
1413
1414
    /**
1415
     * @psalm-pure
1416
     *
1417
     * @param mixed  $value
1418
     * @param string $message
1419
     *
1420
     * @throws InvalidArgumentException
1421
     */
1422 20 View Code Duplication
    public static function alpha($value, $message = '')
1423
    {
1424 20
        static::string($value);
1425
1426 12
        $locale = \setlocale(LC_CTYPE, 0);
1427 12
        \setlocale(LC_CTYPE, 'C');
1428 12
        $valid = !\ctype_alpha($value);
1429 12
        \setlocale(LC_CTYPE, $locale);
1430
1431 12
        if ($valid) {
1432 8
            static::reportInvalidArgument(\sprintf(
1433 8
                $message ?: 'Expected a value to contain only letters. Got: %s',
1434 8
                static::valueToString($value)
1435
            ));
1436
        }
1437 4
    }
1438
1439
    /**
1440
     * @psalm-pure
1441
     *
1442
     * @param string $value
1443
     * @param string $message
1444
     *
1445
     * @throws InvalidArgumentException
1446
     */
1447 12 View Code Duplication
    public static function digits($value, $message = '')
1448
    {
1449 12
        $locale = \setlocale(LC_CTYPE, 0);
1450 12
        \setlocale(LC_CTYPE, 'C');
1451 12
        $valid = !\ctype_digit($value);
1452 12
        \setlocale(LC_CTYPE, $locale);
1453
1454 12
        if ($valid) {
1455 8
            static::reportInvalidArgument(\sprintf(
1456 8
                $message ?: 'Expected a value to contain digits only. Got: %s',
1457 8
                static::valueToString($value)
1458
            ));
1459
        }
1460 4
    }
1461
1462
    /**
1463
     * @psalm-pure
1464
     *
1465
     * @param string $value
1466
     * @param string $message
1467
     *
1468
     * @throws InvalidArgumentException
1469
     */
1470 12 View Code Duplication
    public static function alnum($value, $message = '')
1471
    {
1472 12
        $locale = \setlocale(LC_CTYPE, 0);
1473 12
        \setlocale(LC_CTYPE, 'C');
1474 12
        $valid = !\ctype_alnum($value);
1475 12
        \setlocale(LC_CTYPE, $locale);
1476
1477 12
        if ($valid) {
1478 8
            static::reportInvalidArgument(\sprintf(
1479 8
                $message ?: 'Expected a value to contain letters and digits only. Got: %s',
1480 8
                static::valueToString($value)
1481
            ));
1482
        }
1483 4
    }
1484
1485
    /**
1486
     * @psalm-pure
1487
     * @psalm-assert lowercase-string $value
1488
     *
1489
     * @param string $value
1490
     * @param string $message
1491
     *
1492
     * @throws InvalidArgumentException
1493
     */
1494 16 View Code Duplication
    public static function lower($value, $message = '')
1495
    {
1496 16
        $locale = \setlocale(LC_CTYPE, 0);
1497 16
        \setlocale(LC_CTYPE, 'C');
1498 16
        $valid = !\ctype_lower($value);
1499 16
        \setlocale(LC_CTYPE, $locale);
1500
1501 16
        if ($valid) {
1502 12
            static::reportInvalidArgument(\sprintf(
1503 12
                $message ?: 'Expected a value to contain lowercase characters only. Got: %s',
1504 12
                static::valueToString($value)
1505
            ));
1506
        }
1507 4
    }
1508
1509
    /**
1510
     * @psalm-pure
1511
     * @psalm-assert !lowercase-string $value
1512
     *
1513
     * @param string $value
1514
     * @param string $message
1515
     *
1516
     * @throws InvalidArgumentException
1517
     */
1518 16 View Code Duplication
    public static function upper($value, $message = '')
1519
    {
1520 16
        $locale = \setlocale(LC_CTYPE, 0);
1521 16
        \setlocale(LC_CTYPE, 'C');
1522 16
        $valid = !\ctype_upper($value);
1523 16
        \setlocale(LC_CTYPE, $locale);
1524
1525 16
        if ($valid) {
1526 12
            static::reportInvalidArgument(\sprintf(
1527 12
                $message ?: 'Expected a value to contain uppercase characters only. Got: %s',
1528 12
                static::valueToString($value)
1529
            ));
1530
        }
1531 4
    }
1532
1533
    /**
1534
     * @psalm-pure
1535
     *
1536
     * @param string $value
1537
     * @param int    $length
1538
     * @param string $message
1539
     *
1540
     * @throws InvalidArgumentException
1541
     */
1542 36
    public static function length($value, $length, $message = '')
1543
    {
1544 36
        if ($length !== static::strlen($value)) {
1545 24
            static::reportInvalidArgument(\sprintf(
1546 24
                $message ?: 'Expected a value to contain %2$s characters. Got: %s',
1547 24
                static::valueToString($value),
1548 24
                $length
1549
            ));
1550
        }
1551 12
    }
1552
1553
    /**
1554
     * Inclusive min.
1555
     *
1556
     * @psalm-pure
1557
     *
1558
     * @param string    $value
1559
     * @param int|float $min
1560
     * @param string    $message
1561
     *
1562
     * @throws InvalidArgumentException
1563
     */
1564 36
    public static function minLength($value, $min, $message = '')
1565
    {
1566 36
        if (static::strlen($value) < $min) {
1567 12
            static::reportInvalidArgument(\sprintf(
1568 12
                $message ?: 'Expected a value to contain at least %2$s characters. Got: %s',
1569 12
                static::valueToString($value),
1570 12
                $min
1571
            ));
1572
        }
1573 24
    }
1574
1575
    /**
1576
     * Inclusive max.
1577
     *
1578
     * @psalm-pure
1579
     *
1580
     * @param string    $value
1581
     * @param int|float $max
1582
     * @param string    $message
1583
     *
1584
     * @throws InvalidArgumentException
1585
     */
1586 36
    public static function maxLength($value, $max, $message = '')
1587
    {
1588 36
        if (static::strlen($value) > $max) {
1589 12
            static::reportInvalidArgument(\sprintf(
1590 12
                $message ?: 'Expected a value to contain at most %2$s characters. Got: %s',
1591 12
                static::valueToString($value),
1592 12
                $max
1593
            ));
1594
        }
1595 24
    }
1596
1597
    /**
1598
     * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion.
1599
     *
1600
     * @psalm-pure
1601
     *
1602
     * @param string    $value
1603
     * @param int|float $min
1604
     * @param int|float $max
1605
     * @param string    $message
1606
     *
1607
     * @throws InvalidArgumentException
1608
     */
1609 60 View Code Duplication
    public static function lengthBetween($value, $min, $max, $message = '')
1610
    {
1611 60
        $length = static::strlen($value);
1612
1613 60
        if ($length < $min || $length > $max) {
1614 24
            static::reportInvalidArgument(\sprintf(
1615 24
                $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s',
1616 24
                static::valueToString($value),
1617 24
                $min,
1618 24
                $max
1619
            ));
1620
        }
1621 36
    }
1622
1623
    /**
1624
     * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file.
1625
     *
1626
     * @param mixed  $value
1627
     * @param string $message
1628
     *
1629
     * @throws InvalidArgumentException
1630
     */
1631 36 View Code Duplication
    public static function fileExists($value, $message = '')
1632
    {
1633 36
        static::string($value);
1634
1635 36
        if (!\file_exists($value)) {
1636 12
            static::reportInvalidArgument(\sprintf(
1637 12
                $message ?: 'The file %s does not exist.',
1638 12
                static::valueToString($value)
1639
            ));
1640
        }
1641 24
    }
1642
1643
    /**
1644
     * @param mixed  $value
1645
     * @param string $message
1646
     *
1647
     * @throws InvalidArgumentException
1648
     */
1649 12 View Code Duplication
    public static function file($value, $message = '')
1650
    {
1651 12
        static::fileExists($value, $message);
1652
1653 8
        if (!\is_file($value)) {
1654 4
            static::reportInvalidArgument(\sprintf(
1655 4
                $message ?: 'The path %s is not a file.',
1656 4
                static::valueToString($value)
1657
            ));
1658
        }
1659 4
    }
1660
1661
    /**
1662
     * @param mixed  $value
1663
     * @param string $message
1664
     *
1665
     * @throws InvalidArgumentException
1666
     */
1667 12 View Code Duplication
    public static function directory($value, $message = '')
1668
    {
1669 12
        static::fileExists($value, $message);
1670
1671 8
        if (!\is_dir($value)) {
1672 4
            static::reportInvalidArgument(\sprintf(
1673 4
                $message ?: 'The path %s is no directory.',
1674 4
                static::valueToString($value)
1675
            ));
1676
        }
1677 4
    }
1678
1679
    /**
1680
     * @param string $value
1681
     * @param string $message
1682
     *
1683
     * @throws InvalidArgumentException
1684
     */
1685
    public static function readable($value, $message = '')
1686
    {
1687
        if (!\is_readable($value)) {
1688
            static::reportInvalidArgument(\sprintf(
1689
                $message ?: 'The path %s is not readable.',
1690
                static::valueToString($value)
1691
            ));
1692
        }
1693
    }
1694
1695
    /**
1696
     * @param string $value
1697
     * @param string $message
1698
     *
1699
     * @throws InvalidArgumentException
1700
     */
1701
    public static function writable($value, $message = '')
1702
    {
1703
        if (!\is_writable($value)) {
1704
            static::reportInvalidArgument(\sprintf(
1705
                $message ?: 'The path %s is not writable.',
1706
                static::valueToString($value)
1707
            ));
1708
        }
1709
    }
1710
1711
    /**
1712
     * @psalm-assert class-string $value
1713
     *
1714
     * @param mixed  $value
1715
     * @param string $message
1716
     *
1717
     * @throws InvalidArgumentException
1718
     */
1719 8
    public static function classExists($value, $message = '')
1720
    {
1721 8
        if (!\class_exists($value)) {
1722 4
            static::reportInvalidArgument(\sprintf(
1723 4
                $message ?: 'Expected an existing class name. Got: %s',
1724 4
                static::valueToString($value)
1725
            ));
1726
        }
1727 4
    }
1728
1729
    /**
1730
     * @psalm-pure
1731
     * @psalm-template ExpectedType of object
1732
     * @psalm-param class-string<ExpectedType> $class
1733
     * @psalm-assert class-string<ExpectedType>|ExpectedType $value
1734
     *
1735
     * @param mixed         $value
1736
     * @param string|object $class
1737
     * @param string        $message
1738
     *
1739
     * @throws InvalidArgumentException
1740
     */
1741 8
    public static function subclassOf($value, $class, $message = '')
1742
    {
1743 8
        if (!\is_subclass_of($value, $class)) {
1744 4
            static::reportInvalidArgument(\sprintf(
1745 4
                $message ?: 'Expected a sub-class of %2$s. Got: %s',
1746 4
                static::valueToString($value),
1747 4
                static::valueToString($class)
1748
            ));
1749
        }
1750 4
    }
1751
1752
    /**
1753
     * @param mixed  $value
1754
     * @param string $message
1755
     *
1756
     * @throws InvalidArgumentException
1757
     */
1758 8
    public static function interfaceExists($value, $message = '')
1759
    {
1760 8
        if (!\interface_exists($value)) {
1761 4
            static::reportInvalidArgument(\sprintf(
1762 4
                $message ?: 'Expected an existing interface name. got %s',
1763 4
                static::valueToString($value)
1764
            ));
1765
        }
1766 4
    }
1767
1768
    /**
1769
     * @psalm-pure
1770
     * @psalm-template ExpectedType of object
1771
     * @psalm-param class-string<ExpectedType> $interface
1772
     * @psalm-assert class-string<ExpectedType> $value
1773
     *
1774
     * @param mixed  $value
1775
     * @param mixed  $interface
1776
     * @param string $message
1777
     *
1778
     * @throws InvalidArgumentException
1779
     */
1780 8 View Code Duplication
    public static function implementsInterface($value, $interface, $message = '')
1781
    {
1782 8
        if (!\in_array($interface, \class_implements($value))) {
1783 4
            static::reportInvalidArgument(\sprintf(
1784 4
                $message ?: 'Expected an implementation of %2$s. Got: %s',
1785 4
                static::valueToString($value),
1786 4
                static::valueToString($interface)
1787
            ));
1788
        }
1789 4
    }
1790
1791
    /**
1792
     * @psalm-pure
1793
     * @psalm-param class-string|object $classOrObject
1794
     *
1795
     * @param string|object $classOrObject
1796
     * @param mixed         $property
1797
     * @param string        $message
1798
     *
1799
     * @throws InvalidArgumentException
1800
     */
1801 12 View Code Duplication
    public static function propertyExists($classOrObject, $property, $message = '')
1802
    {
1803 12
        if (!\property_exists($classOrObject, $property)) {
1804 4
            static::reportInvalidArgument(\sprintf(
1805 4
                $message ?: 'Expected the property %s to exist.',
1806 4
                static::valueToString($property)
1807
            ));
1808
        }
1809 8
    }
1810
1811
    /**
1812
     * @psalm-pure
1813
     * @psalm-param class-string|object $classOrObject
1814
     *
1815
     * @param string|object $classOrObject
1816
     * @param mixed         $property
1817
     * @param string        $message
1818
     *
1819
     * @throws InvalidArgumentException
1820
     */
1821 12 View Code Duplication
    public static function propertyNotExists($classOrObject, $property, $message = '')
1822
    {
1823 12
        if (\property_exists($classOrObject, $property)) {
1824 8
            static::reportInvalidArgument(\sprintf(
1825 8
                $message ?: 'Expected the property %s to not exist.',
1826 8
                static::valueToString($property)
1827
            ));
1828
        }
1829 4
    }
1830
1831
    /**
1832
     * @psalm-pure
1833
     * @psalm-param class-string|object $classOrObject
1834
     *
1835
     * @param string|object $classOrObject
1836
     * @param mixed         $method
1837
     * @param string        $message
1838
     *
1839
     * @throws InvalidArgumentException
1840
     */
1841 27 View Code Duplication
    public static function methodExists($classOrObject, $method, $message = '')
1842
    {
1843 27
        if (!\method_exists($classOrObject, $method)) {
1844 19
            static::reportInvalidArgument(\sprintf(
1845 19
                $message ?: 'Expected the method %s to exist.',
1846 19
                static::valueToString($method)
1847
            ));
1848
        }
1849 8
    }
1850
1851
    /**
1852
     * @psalm-pure
1853
     * @psalm-param class-string|object $classOrObject
1854
     *
1855
     * @param string|object $classOrObject
1856
     * @param mixed         $method
1857
     * @param string        $message
1858
     *
1859
     * @throws InvalidArgumentException
1860
     */
1861 27 View Code Duplication
    public static function methodNotExists($classOrObject, $method, $message = '')
1862
    {
1863 27
        if (\method_exists($classOrObject, $method)) {
1864 8
            static::reportInvalidArgument(\sprintf(
1865 8
                $message ?: 'Expected the method %s to not exist.',
1866 8
                static::valueToString($method)
1867
            ));
1868
        }
1869 19
    }
1870
1871
    /**
1872
     * @psalm-pure
1873
     *
1874
     * @param array      $array
1875
     * @param string|int $key
1876
     * @param string     $message
1877
     *
1878
     * @throws InvalidArgumentException
1879
     */
1880 12 View Code Duplication
    public static function keyExists($array, $key, $message = '')
1881
    {
1882 12
        if (!(isset($array[$key]) || \array_key_exists($key, $array))) {
1883 4
            static::reportInvalidArgument(\sprintf(
1884 4
                $message ?: 'Expected the key %s to exist.',
1885 4
                static::valueToString($key)
1886
            ));
1887
        }
1888 8
    }
1889
1890
    /**
1891
     * @psalm-pure
1892
     *
1893
     * @param array      $array
1894
     * @param string|int $key
1895
     * @param string     $message
1896
     *
1897
     * @throws InvalidArgumentException
1898
     */
1899 12 View Code Duplication
    public static function keyNotExists($array, $key, $message = '')
1900
    {
1901 12
        if (isset($array[$key]) || \array_key_exists($key, $array)) {
1902 8
            static::reportInvalidArgument(\sprintf(
1903 8
                $message ?: 'Expected the key %s to not exist.',
1904 8
                static::valueToString($key)
1905
            ));
1906
        }
1907 4
    }
1908
1909
    /**
1910
     * Checks if a value is a valid array key (int or string).
1911
     *
1912
     * @psalm-pure
1913
     * @psalm-assert array-key $value
1914
     *
1915
     * @param mixed  $value
1916
     * @param string $message
1917
     *
1918
     * @throws InvalidArgumentException
1919
     */
1920 28
    public static function validArrayKey($value, $message = '')
1921
    {
1922 28
        if (!(\is_int($value) || \is_string($value))) {
1923 20
            static::reportInvalidArgument(\sprintf(
1924 20
                $message ?: 'Expected string or integer. Got: %s',
1925 20
                static::typeToString($value)
1926
            ));
1927
        }
1928 8
    }
1929
1930
    /**
1931
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1932
     *
1933
     * @param Countable|array $array
1934
     * @param int             $number
1935
     * @param string          $message
1936
     *
1937
     * @throws InvalidArgumentException
1938
     */
1939 8
    public static function count($array, $number, $message = '')
1940
    {
1941 8
        static::eq(
1942 8
            \count($array),
1943
            $number,
1944 8
            \sprintf(
1945 8
                $message ?: 'Expected an array to contain %d elements. Got: %d.',
1946 8
                $number,
1947 8
                \count($array)
1948
            )
1949
        );
1950 4
    }
1951
1952
    /**
1953
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1954
     *
1955
     * @param Countable|array $array
1956
     * @param int|float       $min
1957
     * @param string          $message
1958
     *
1959
     * @throws InvalidArgumentException
1960
     */
1961 12 View Code Duplication
    public static function minCount($array, $min, $message = '')
1962
    {
1963 12
        if (\count($array) < $min) {
1964 4
            static::reportInvalidArgument(\sprintf(
1965 4
                $message ?: 'Expected an array to contain at least %2$d elements. Got: %d',
1966 4
                \count($array),
1967 4
                $min
1968
            ));
1969
        }
1970 8
    }
1971
1972
    /**
1973
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1974
     *
1975
     * @param Countable|array $array
1976
     * @param int|float       $max
1977
     * @param string          $message
1978
     *
1979
     * @throws InvalidArgumentException
1980
     */
1981 12 View Code Duplication
    public static function maxCount($array, $max, $message = '')
1982
    {
1983 12
        if (\count($array) > $max) {
1984 4
            static::reportInvalidArgument(\sprintf(
1985 4
                $message ?: 'Expected an array to contain at most %2$d elements. Got: %d',
1986 4
                \count($array),
1987 4
                $max
1988
            ));
1989
        }
1990 8
    }
1991
1992
    /**
1993
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1994
     *
1995
     * @param Countable|array $array
1996
     * @param int|float       $min
1997
     * @param int|float       $max
1998
     * @param string          $message
1999
     *
2000
     * @throws InvalidArgumentException
2001
     */
2002 20
    public static function countBetween($array, $min, $max, $message = '')
2003
    {
2004 20
        $count = \count($array);
2005
2006 20
        if ($count < $min || $count > $max) {
2007 8
            static::reportInvalidArgument(\sprintf(
2008 8
                $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d',
2009 8
                $count,
2010 8
                $min,
2011 8
                $max
2012
            ));
2013
        }
2014 12
    }
2015
2016
    /**
2017
     * @psalm-pure
2018
     * @psalm-assert list $array
2019
     *
2020
     * @param mixed  $array
2021
     * @param string $message
2022
     *
2023
     * @throws InvalidArgumentException
2024
     */
2025 80 View Code Duplication
    public static function isList($array, $message = '')
2026
    {
2027 80
        if (!\is_array($array) || $array !== \array_values($array)) {
2028 32
            static::reportInvalidArgument(
2029 32
                $message ?: 'Expected list - non-associative array.'
2030
            );
2031
        }
2032 48
    }
2033
2034
    /**
2035
     * @psalm-pure
2036
     * @psalm-assert list $array
2037
     * @psalm-assert !empty $array
2038
     *
2039
     * @param mixed  $array
2040
     * @param string $message
2041
     *
2042
     * @throws InvalidArgumentException
2043
     */
2044 40
    public static function isNonEmptyList($array, $message = '')
2045
    {
2046 40
        static::isList($array, $message);
2047 24
        static::notEmpty($array, $message);
2048 20
    }
2049
2050
    /**
2051
     * @psalm-pure
2052
     * @psalm-template T
2053
     * @psalm-param mixed|array<T> $array
2054
     * @psalm-assert array<string, T> $array
2055
     *
2056
     * @param mixed  $array
2057
     * @param string $message
2058
     *
2059
     * @throws InvalidArgumentException
2060
     */
2061 32
    public static function isMap($array, $message = '')
2062
    {
2063
        if (
2064 32
            !\is_array($array) ||
2065 32
            \array_keys($array) !== \array_filter(\array_keys($array), '\is_string')
2066
        ) {
2067 16
            static::reportInvalidArgument(
2068 16
                $message ?: 'Expected map - associative array with string keys.'
2069
            );
2070
        }
2071 16
    }
2072
2073
    /**
2074
     * @psalm-pure
2075
     * @psalm-template T
2076
     * @psalm-param mixed|array<T> $array
2077
     * @psalm-assert array<string, T> $array
2078
     * @psalm-assert !empty $array
2079
     *
2080
     * @param mixed  $array
2081
     * @param string $message
2082
     *
2083
     * @throws InvalidArgumentException
2084
     */
2085 16
    public static function isNonEmptyMap($array, $message = '')
2086
    {
2087 16
        static::isMap($array, $message);
2088 8
        static::notEmpty($array, $message);
2089 4
    }
2090
2091
    /**
2092
     * @psalm-pure
2093
     *
2094
     * @param string $value
2095
     * @param string $message
2096
     *
2097
     * @throws InvalidArgumentException
2098
     */
2099 56
    public static function uuid($value, $message = '')
2100
    {
2101 56
        $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
2102
2103
        // The nil UUID is special form of UUID that is specified to have all
2104
        // 128 bits set to zero.
2105 56
        if ('00000000-0000-0000-0000-000000000000' === $value) {
2106 4
            return;
2107
        }
2108
2109 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)) {
2110 20
            static::reportInvalidArgument(\sprintf(
2111 20
                $message ?: 'Value %s is not a valid UUID.',
2112 20
                static::valueToString($value)
2113
            ));
2114
        }
2115 32
    }
2116
2117
    /**
2118
     * @psalm-param class-string<Throwable>
2119
     *
2120
     * @param Closure $expression
2121
     * @param string  $class
2122
     * @param string  $message
2123
     *
2124
     * @throws InvalidArgumentException
2125
     */
2126 24
    public static function throws(Closure $expression, $class = 'Exception', $message = '')
2127
    {
2128 24
        static::string($class);
2129
2130 24
        $actual = 'none';
2131
2132
        try {
2133 24
            $expression();
2134 24
        } catch (Exception $e) {
2135 20
            $actual = \get_class($e);
2136 20
            if ($e instanceof $class) {
2137 20
                return;
2138
            }
2139 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...
2140 4
            $actual = \get_class($e);
2141 4
            if ($e instanceof $class) {
2142 4
                return;
2143
            }
2144
        }
2145
2146 8
        static::reportInvalidArgument($message ?: \sprintf(
2147 8
            'Expected to throw "%s", got "%s"',
2148 8
            $class,
2149 8
            $actual
2150
        ));
2151
    }
2152
2153
    /**
2154
     * @throws BadMethodCallException
2155
     */
2156 1898
    public static function __callStatic($name, $arguments)
2157
    {
2158 1898
        if ('nullOr' === \substr($name, 0, 6)) {
2159 693
            if (null !== $arguments[0]) {
2160 586
                $method = \lcfirst(\substr($name, 6));
2161 586
                \call_user_func_array(array('static', $method), $arguments);
2162
            }
2163
2164 418
            return;
2165
        }
2166
2167 1205
        if ('all' === \substr($name, 0, 3)) {
2168 1204
            static::isIterable($arguments[0]);
2169
2170 1204
            $method = \lcfirst(\substr($name, 3));
2171 1204
            $args = $arguments;
2172
2173 1204
            foreach ($arguments[0] as $entry) {
2174 1204
                $args[0] = $entry;
2175
2176 1204
                \call_user_func_array(array('static', $method), $args);
2177
            }
2178
2179 630
            return;
2180
        }
2181
2182 1
        throw new BadMethodCallException('No such method: '.$name);
2183
    }
2184
2185
    /**
2186
     * @param mixed $value
2187
     *
2188
     * @return string
2189
     */
2190 839
    protected static function valueToString($value)
2191
    {
2192 839
        if (null === $value) {
2193 20
            return 'null';
2194
        }
2195
2196 821
        if (true === $value) {
2197 15
            return 'true';
2198
        }
2199
2200 811
        if (false === $value) {
2201 25
            return 'false';
2202
        }
2203
2204 786
        if (\is_array($value)) {
2205 21
            return 'array';
2206
        }
2207
2208 765
        if (\is_object($value)) {
2209 3
            if (\method_exists($value, '__toString')) {
2210 1
                return \get_class($value).': '.self::valueToString($value->__toString());
2211
            }
2212
2213 2
            if ($value instanceof DateTime || $value instanceof DateTimeImmutable) {
2214 1
                return \get_class($value).': '.self::valueToString($value->format('c'));
2215
            }
2216
2217 1
            return \get_class($value);
2218
        }
2219
2220 764
        if (\is_resource($value)) {
2221 1
            return 'resource';
2222
        }
2223
2224 764
        if (\is_string($value)) {
2225 662
            return '"'.$value.'"';
2226
        }
2227
2228 114
        return (string) $value;
2229
    }
2230
2231
    /**
2232
     * @param mixed $value
2233
     *
2234
     * @return string
2235
     */
2236 251
    protected static function typeToString($value)
2237
    {
2238 251
        return \is_object($value) ? \get_class($value) : \gettype($value);
2239
    }
2240
2241 168
    protected static function strlen($value)
2242
    {
2243 168
        if (!\function_exists('mb_detect_encoding')) {
2244
            return \strlen($value);
2245
        }
2246
2247 168
        if (false === $encoding = \mb_detect_encoding($value)) {
2248
            return \strlen($value);
2249
        }
2250
2251 168
        return \mb_strlen($value, $encoding);
2252
    }
2253
2254
    /**
2255
     * @param string $message
2256
     *
2257
     * @throws InvalidArgumentException
2258
     *
2259
     * @psalm-pure this method is not supposed to perform side-effects
2260
     */
2261 1153
    protected static function reportInvalidArgument($message)
2262
    {
2263 1153
        throw new InvalidArgumentException($message);
2264
    }
2265
2266
    private function __construct()
2267
    {
2268
    }
2269
}
2270