Failed Conditions
Pull Request — master (#140)
by
unknown
04:08
created

Assert::validArrayKey()   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 Throwable;
21
use Traversable;
22
23
/**
24
 * Efficient assertions to validate the input/output of your methods.
25
 *
26
 * @method static void nullOrString($value, $message = '')
27
 * @method static void nullOrStringNotEmpty($value, $message = '')
28
 * @method static void nullOrInteger($value, $message = '')
29
 * @method static void nullOrIntegerish($value, $message = '')
30
 * @method static void nullOrFloat($value, $message = '')
31
 * @method static void nullOrNumeric($value, $message = '')
32
 * @method static void nullOrNatural($value, $message = '')
33
 * @method static void nullOrBoolean($value, $message = '')
34
 * @method static void nullOrScalar($value, $message = '')
35
 * @method static void nullOrObject($value, $message = '')
36
 * @method static void nullOrResource($value, $type = null, $message = '')
37
 * @method static void nullOrIsCallable($value, $message = '')
38
 * @method static void nullOrIsArray($value, $message = '')
39
 * @method static void nullOrIsTraversable($value, $message = '')
40
 * @method static void nullOrIsArrayAccessible($value, $message = '')
41
 * @method static void nullOrIsCountable($value, $message = '')
42
 * @method static void nullOrIsIterable($value, $message = '')
43
 * @method static void nullOrIsInstanceOf($value, $class, $message = '')
44
 * @method static void nullOrNotInstanceOf($value, $class, $message = '')
45
 * @method static void nullOrIsInstanceOfAny($value, $classes, $message = '')
46
 * @method static void nullOrIsEmpty($value, $message = '')
47
 * @method static void nullOrNotEmpty($value, $message = '')
48
 * @method static void nullOrTrue($value, $message = '')
49
 * @method static void nullOrFalse($value, $message = '')
50
 * @method static void nullOrIp($value, $message = '')
51
 * @method static void nullOrIpv4($value, $message = '')
52
 * @method static void nullOrIpv6($value, $message = '')
53
 * @method static void nullOrEmail($value, $message = '')
54
 * @method static void nullOrUniqueValues($values, $message = '')
55
 * @method static void nullOrEq($value, $expect, $message = '')
56
 * @method static void nullOrNotEq($value, $expect, $message = '')
57
 * @method static void nullOrSame($value, $expect, $message = '')
58
 * @method static void nullOrNotSame($value, $expect, $message = '')
59
 * @method static void nullOrGreaterThan($value, $limit, $message = '')
60
 * @method static void nullOrGreaterThanEq($value, $limit, $message = '')
61
 * @method static void nullOrLessThan($value, $limit, $message = '')
62
 * @method static void nullOrLessThanEq($value, $limit, $message = '')
63
 * @method static void nullOrRange($value, $min, $max, $message = '')
64
 * @method static void nullOrOneOf($value, $values, $message = '')
65
 * @method static void nullOrContains($value, $subString, $message = '')
66
 * @method static void nullOrNotContains($value, $subString, $message = '')
67
 * @method static void nullOrNotWhitespaceOnly($value, $message = '')
68
 * @method static void nullOrStartsWith($value, $prefix, $message = '')
69
 * @method static void nullOrStartsWithLetter($value, $message = '')
70
 * @method static void nullOrEndsWith($value, $suffix, $message = '')
71
 * @method static void nullOrRegex($value, $pattern, $message = '')
72
 * @method static void nullOrNotRegex($value, $pattern, $message = '')
73
 * @method static void nullOrUnicodeLetters($value, $message = '')
74
 * @method static void nullOrAlpha($value, $message = '')
75
 * @method static void nullOrDigits($value, $message = '')
76
 * @method static void nullOrAlnum($value, $message = '')
77
 * @method static void nullOrLower($value, $message = '')
78
 * @method static void nullOrUpper($value, $message = '')
79
 * @method static void nullOrLength($value, $length, $message = '')
80
 * @method static void nullOrMinLength($value, $min, $message = '')
81
 * @method static void nullOrMaxLength($value, $max, $message = '')
82
 * @method static void nullOrLengthBetween($value, $min, $max, $message = '')
83
 * @method static void nullOrFileExists($value, $message = '')
84
 * @method static void nullOrFile($value, $message = '')
85
 * @method static void nullOrDirectory($value, $message = '')
86
 * @method static void nullOrReadable($value, $message = '')
87
 * @method static void nullOrWritable($value, $message = '')
88
 * @method static void nullOrClassExists($value, $message = '')
89
 * @method static void nullOrSubclassOf($value, $class, $message = '')
90
 * @method static void nullOrInterfaceExists($value, $message = '')
91
 * @method static void nullOrImplementsInterface($value, $interface, $message = '')
92
 * @method static void nullOrPropertyExists($value, $property, $message = '')
93
 * @method static void nullOrPropertyNotExists($value, $property, $message = '')
94
 * @method static void nullOrMethodExists($value, $method, $message = '')
95
 * @method static void nullOrMethodNotExists($value, $method, $message = '')
96
 * @method static void nullOrKeyExists($value, $key, $message = '')
97
 * @method static void nullOrKeyNotExists($value, $key, $message = '')
98
 * @method static void nullOrValidArrayKey($value, $message = '')
99
 * @method static void nullOrCount($value, $key, $message = '')
100
 * @method static void nullOrMinCount($value, $min, $message = '')
101
 * @method static void nullOrMaxCount($value, $max, $message = '')
102
 * @method static void nullOrIsList($value, $message = '')
103
 * @method static void nullOrIsMap($value, $message = '')
104
 * @method static void nullOrCountBetween($value, $min, $max, $message = '')
105
 * @method static void nullOrUuid($values, $message = '')
106
 * @method static void nullOrThrows($expression, $class = 'Exception', $message = '')
107
 * @method static void allString($values, $message = '')
108
 * @method static void allStringNotEmpty($values, $message = '')
109
 * @method static void allInteger($values, $message = '')
110
 * @method static void allIntegerish($values, $message = '')
111
 * @method static void allFloat($values, $message = '')
112
 * @method static void allNumeric($values, $message = '')
113
 * @method static void allNatural($values, $message = '')
114
 * @method static void allBoolean($values, $message = '')
115
 * @method static void allScalar($values, $message = '')
116
 * @method static void allObject($values, $message = '')
117
 * @method static void allResource($values, $type = null, $message = '')
118
 * @method static void allIsCallable($values, $message = '')
119
 * @method static void allIsArray($values, $message = '')
120
 * @method static void allIsTraversable($values, $message = '')
121
 * @method static void allIsArrayAccessible($values, $message = '')
122
 * @method static void allIsCountable($values, $message = '')
123
 * @method static void allIsIterable($values, $message = '')
124
 * @method static void allIsInstanceOf($values, $class, $message = '')
125
 * @method static void allNotInstanceOf($values, $class, $message = '')
126
 * @method static void allIsInstanceOfAny($values, $classes, $message = '')
127
 * @method static void allNull($values, $message = '')
128
 * @method static void allNotNull($values, $message = '')
129
 * @method static void allIsEmpty($values, $message = '')
130
 * @method static void allNotEmpty($values, $message = '')
131
 * @method static void allTrue($values, $message = '')
132
 * @method static void allFalse($values, $message = '')
133
 * @method static void allIp($values, $message = '')
134
 * @method static void allIpv4($values, $message = '')
135
 * @method static void allIpv6($values, $message = '')
136
 * @method static void allEmail($values, $message = '')
137
 * @method static void allUniqueValues($values, $message = '')
138
 * @method static void allEq($values, $expect, $message = '')
139
 * @method static void allNotEq($values, $expect, $message = '')
140
 * @method static void allSame($values, $expect, $message = '')
141
 * @method static void allNotSame($values, $expect, $message = '')
142
 * @method static void allGreaterThan($values, $limit, $message = '')
143
 * @method static void allGreaterThanEq($values, $limit, $message = '')
144
 * @method static void allLessThan($values, $limit, $message = '')
145
 * @method static void allLessThanEq($values, $limit, $message = '')
146
 * @method static void allRange($values, $min, $max, $message = '')
147
 * @method static void allOneOf($values, $values, $message = '')
148
 * @method static void allContains($values, $subString, $message = '')
149
 * @method static void allNotContains($values, $subString, $message = '')
150
 * @method static void allNotWhitespaceOnly($values, $message = '')
151
 * @method static void allStartsWith($values, $prefix, $message = '')
152
 * @method static void allStartsWithLetter($values, $message = '')
153
 * @method static void allEndsWith($values, $suffix, $message = '')
154
 * @method static void allRegex($values, $pattern, $message = '')
155
 * @method static void allNotRegex($values, $pattern, $message = '')
156
 * @method static void allUnicodeLetters($values, $message = '')
157
 * @method static void allAlpha($values, $message = '')
158
 * @method static void allDigits($values, $message = '')
159
 * @method static void allAlnum($values, $message = '')
160
 * @method static void allLower($values, $message = '')
161
 * @method static void allUpper($values, $message = '')
162
 * @method static void allLength($values, $length, $message = '')
163
 * @method static void allMinLength($values, $min, $message = '')
164
 * @method static void allMaxLength($values, $max, $message = '')
165
 * @method static void allLengthBetween($values, $min, $max, $message = '')
166
 * @method static void allFileExists($values, $message = '')
167
 * @method static void allFile($values, $message = '')
168
 * @method static void allDirectory($values, $message = '')
169
 * @method static void allReadable($values, $message = '')
170
 * @method static void allWritable($values, $message = '')
171
 * @method static void allClassExists($values, $message = '')
172
 * @method static void allSubclassOf($values, $class, $message = '')
173
 * @method static void allInterfaceExists($values, $message = '')
174
 * @method static void allImplementsInterface($values, $interface, $message = '')
175
 * @method static void allPropertyExists($values, $property, $message = '')
176
 * @method static void allPropertyNotExists($values, $property, $message = '')
177
 * @method static void allMethodExists($values, $method, $message = '')
178
 * @method static void allMethodNotExists($values, $method, $message = '')
179
 * @method static void allKeyExists($values, $key, $message = '')
180
 * @method static void allKeyNotExists($values, $key, $message = '')
181
 * @method static void allValidArrayKey($values, $message = '')
182
 * @method static void allCount($values, $key, $message = '')
183
 * @method static void allMinCount($values, $min, $message = '')
184
 * @method static void allMaxCount($values, $max, $message = '')
185
 * @method static void allCountBetween($values, $min, $max, $message = '')
186
 * @method static void allIsList($values, $message = '')
187
 * @method static void allIsMap($values, $message = '')
188
 * @method static void allUuid($values, $message = '')
189
 * @method static void allThrows($expressions, $class = 'Exception', $message = '')
190
 *
191
 * @since  1.0
192
 *
193
 * @author Bernhard Schussek <[email protected]>
194
 */
195
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...
196
{
197
    /**
198
     * @psalm-assert string $value
199
     *
200
     * @param mixed  $value
201
     * @param string $message
202
     *
203
     * @throws InvalidArgumentException
204
     */
205 350
    public static function string($value, $message = '')
206
    {
207 350
        if (!\is_string($value)) {
208 98
            static::reportInvalidArgument(\sprintf(
209 98
                $message ?: 'Expected a string. Got: %s',
210 98
                static::typeToString($value)
211
            ));
212
        }
213 252
    }
214
215
    /**
216
     * @psalm-assert string $value
217
     *
218
     * @param mixed  $value
219
     * @param string $message
220
     *
221
     * @throws InvalidArgumentException
222
     */
223 16
    public static function stringNotEmpty($value, $message = '')
224
    {
225 16
        static::string($value, $message);
226 12
        static::notEq($value, '', $message);
227 8
    }
228
229
    /**
230
     * @psalm-assert int $value
231
     *
232
     * @param mixed  $value
233
     * @param string $message
234
     *
235
     * @throws InvalidArgumentException
236
     */
237 17
    public static function integer($value, $message = '')
238
    {
239 17
        if (!\is_int($value)) {
240 13
            static::reportInvalidArgument(\sprintf(
241 13
                $message ?: 'Expected an integer. Got: %s',
242 13
                static::typeToString($value)
243
            ));
244
        }
245 4
    }
246
247
    /**
248
     * @psalm-assert numeric $value
249
     *
250
     * @param mixed  $value
251
     * @param string $message
252
     *
253
     * @throws InvalidArgumentException
254
     */
255 16
    public static function integerish($value, $message = '')
256
    {
257 16
        if (!\is_numeric($value) || $value != (int) $value) {
258 4
            static::reportInvalidArgument(\sprintf(
259 4
                $message ?: 'Expected an integerish value. Got: %s',
260 4
                static::typeToString($value)
261
            ));
262
        }
263 12
    }
264
265
    /**
266
     * @psalm-assert float $value
267
     *
268
     * @param mixed  $value
269
     * @param string $message
270
     *
271
     * @throws InvalidArgumentException
272
     */
273 16
    public static function float($value, $message = '')
274
    {
275 16
        if (!\is_float($value)) {
276 8
            static::reportInvalidArgument(\sprintf(
277 8
                $message ?: 'Expected a float. Got: %s',
278 8
                static::typeToString($value)
279
            ));
280
        }
281 8
    }
282
283
    /**
284
     * @psalm-assert numeric $value
285
     *
286
     * @param mixed  $value
287
     * @param string $message
288
     *
289
     * @throws InvalidArgumentException
290
     */
291 20
    public static function numeric($value, $message = '')
292
    {
293 20
        if (!\is_numeric($value)) {
294 4
            static::reportInvalidArgument(\sprintf(
295 4
                $message ?: 'Expected a numeric. Got: %s',
296 4
                static::typeToString($value)
297
            ));
298
        }
299 16
    }
300
301
    /**
302
     * @psalm-assert int $value
303
     *
304
     * @param mixed  $value
305
     * @param string $message
306
     *
307
     * @throws InvalidArgumentException
308
     */
309 24
    public static function natural($value, $message = '')
310
    {
311 24
        if (!\is_int($value) || $value < 0) {
312 16
            static::reportInvalidArgument(\sprintf(
313 16
                $message ?: 'Expected a non-negative integer. Got %s',
314 16
                static::valueToString($value)
315
            ));
316
        }
317 8
    }
318
319
    /**
320
     * @psalm-assert bool $value
321
     *
322
     * @param mixed  $value
323
     * @param string $message
324
     *
325
     * @throws InvalidArgumentException
326
     */
327 16
    public static function boolean($value, $message = '')
328
    {
329 16
        if (!\is_bool($value)) {
330 8
            static::reportInvalidArgument(\sprintf(
331 8
                $message ?: 'Expected a boolean. Got: %s',
332 8
                static::typeToString($value)
333
            ));
334
        }
335 8
    }
336
337
    /**
338
     * @psalm-assert scalar $value
339
     *
340
     * @param mixed  $value
341
     * @param string $message
342
     *
343
     * @throws InvalidArgumentException
344
     */
345 23
    public static function scalar($value, $message = '')
346
    {
347 23
        if (!\is_scalar($value)) {
348 11
            static::reportInvalidArgument(\sprintf(
349 11
                $message ?: 'Expected a scalar. Got: %s',
350 11
                static::typeToString($value)
351
            ));
352
        }
353 12
    }
354
355
    /**
356
     * @psalm-assert object $value
357
     *
358
     * @param mixed  $value
359
     * @param string $message
360
     *
361
     * @throws InvalidArgumentException
362
     */
363 23
    public static function object($value, $message = '')
364
    {
365 23
        if (!\is_object($value)) {
366 15
            static::reportInvalidArgument(\sprintf(
367 15
                $message ?: 'Expected an object. Got: %s',
368 15
                static::typeToString($value)
369
            ));
370
        }
371 8
    }
372
373
    /**
374
     * @psalm-assert resource $value
375
     *
376
     * @param mixed       $value
377
     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
378
     * @param string      $message
379
     *
380
     * @throws InvalidArgumentException
381
     */
382 16
    public static function resource($value, $type = null, $message = '')
383
    {
384 16
        if (!\is_resource($value)) {
385 4
            static::reportInvalidArgument(\sprintf(
386 4
                $message ?: 'Expected a resource. Got: %s',
387 4
                static::typeToString($value)
388
            ));
389
        }
390
391 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...
392 4
            static::reportInvalidArgument(\sprintf(
393 4
                $message ?: 'Expected a resource of type %2$s. Got: %s',
394 4
                static::typeToString($value),
395 4
                $type
396
            ));
397
        }
398 8
    }
399
400
    /**
401
     * @psalm-assert callable $value
402
     *
403
     * @param mixed  $value
404
     * @param string $message
405
     *
406
     * @throws InvalidArgumentException
407
     */
408 20
    public static function isCallable($value, $message = '')
409
    {
410 20
        if (!\is_callable($value)) {
411 8
            static::reportInvalidArgument(\sprintf(
412 8
                $message ?: 'Expected a callable. Got: %s',
413 8
                static::typeToString($value)
414
            ));
415
        }
416 12
    }
417
418
    /**
419
     * @psalm-assert array $value
420
     *
421
     * @param mixed  $value
422
     * @param string $message
423
     *
424
     * @throws InvalidArgumentException
425
     */
426 20
    public static function isArray($value, $message = '')
427
    {
428 20
        if (!\is_array($value)) {
429 12
            static::reportInvalidArgument(\sprintf(
430 12
                $message ?: 'Expected an array. Got: %s',
431 12
                static::typeToString($value)
432
            ));
433
        }
434 8
    }
435
436
    /**
437
     * @psalm-assert iterable $value
438
     *
439
     * @deprecated use "isIterable" or "isInstanceOf" instead
440
     *
441
     * @param mixed  $value
442
     * @param string $message
443
     *
444
     * @throws InvalidArgumentException
445
     */
446 20
    public static function isTraversable($value, $message = '')
447
    {
448 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...
449 20
            \sprintf(
450 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.',
451 20
                __METHOD__
452
            ),
453 20
            \E_USER_DEPRECATED
454
        );
455
456 20
        if (!\is_array($value) && !($value instanceof Traversable)) {
457 8
            static::reportInvalidArgument(\sprintf(
458 8
                $message ?: 'Expected a traversable. Got: %s',
459 8
                static::typeToString($value)
460
            ));
461
        }
462 12
    }
463
464
    /**
465
     * @param mixed  $value
466
     * @param string $message
467
     *
468
     * @throws InvalidArgumentException
469
     */
470 20 View Code Duplication
    public static function isArrayAccessible($value, $message = '')
471
    {
472 20
        if (!\is_array($value) && !($value instanceof ArrayAccess)) {
473 8
            static::reportInvalidArgument(\sprintf(
474 8
                $message ?: 'Expected an array accessible. Got: %s',
475 8
                static::typeToString($value)
476
            ));
477
        }
478 12
    }
479
480
    /**
481
     * @psalm-assert countable $value
482
     *
483
     * @param mixed  $value
484
     * @param string $message
485
     *
486
     * @throws InvalidArgumentException
487
     */
488 24 View Code Duplication
    public static function isCountable($value, $message = '')
489
    {
490 24
        if (!\is_array($value) && !($value instanceof Countable)) {
491 12
            static::reportInvalidArgument(\sprintf(
492 12
                $message ?: 'Expected a countable. Got: %s',
493 12
                static::typeToString($value)
494
            ));
495
        }
496 12
    }
497
498
    /**
499
     * @psalm-assert iterable $value
500
     *
501
     * @param mixed  $value
502
     * @param string $message
503
     *
504
     * @throws InvalidArgumentException
505
     */
506 912 View Code Duplication
    public static function isIterable($value, $message = '')
507
    {
508 912
        if (!\is_array($value) && !($value instanceof Traversable)) {
509 8
            static::reportInvalidArgument(\sprintf(
510 8
                $message ?: 'Expected an iterable. Got: %s',
511 8
                static::typeToString($value)
512
            ));
513
        }
514 908
    }
515
516
    /**
517
     * @psalm-template ExpectedType of object
518
     * @psalm-param class-string<ExpectedType> $class
519
     * @psalm-assert ExpectedType $value
520
     *
521
     * @param mixed         $value
522
     * @param string|object $class
523
     * @param string        $message
524
     *
525
     * @throws InvalidArgumentException
526
     */
527 19
    public static function isInstanceOf($value, $class, $message = '')
528
    {
529 19
        if (!($value instanceof $class)) {
530 15
            static::reportInvalidArgument(\sprintf(
531 15
                $message ?: 'Expected an instance of %2$s. Got: %s',
532 15
                static::typeToString($value),
533 15
                $class
534
            ));
535
        }
536 4
    }
537
538
    /**
539
     * @psalm-template ExpectedType of object
540
     * @psalm-param class-string<ExpectedType> $class
541
     * @psalm-assert !ExpectedType $value
542
     *
543
     * @param mixed         $value
544
     * @param string|object $class
545
     * @param string        $message
546
     *
547
     * @throws InvalidArgumentException
548
     */
549 16
    public static function notInstanceOf($value, $class, $message = '')
550
    {
551 16
        if ($value instanceof $class) {
552 4
            static::reportInvalidArgument(\sprintf(
553 4
                $message ?: 'Expected an instance other than %2$s. Got: %s',
554 4
                static::typeToString($value),
555 4
                $class
556
            ));
557
        }
558 12
    }
559
560
    /**
561
     * @param mixed                $value
562
     * @param array<object|string> $classes
563
     * @param string               $message
564
     *
565
     * @throws InvalidArgumentException
566
     */
567 20
    public static function isInstanceOfAny($value, array $classes, $message = '')
568
    {
569 20
        foreach ($classes as $class) {
570 20
            if ($value instanceof $class) {
571 8
                return;
572
            }
573
        }
574
575 12
        static::reportInvalidArgument(\sprintf(
576 12
            $message ?: 'Expected an instance of any of %2$s. Got: %s',
577 12
            static::typeToString($value),
578 12
            \implode(', ', \array_map(array('static', 'valueToString'), $classes))
579
        ));
580
    }
581
582
    /**
583
     * @psalm-assert empty $value
584
     *
585
     * @param mixed  $value
586
     * @param string $message
587
     *
588
     * @throws InvalidArgumentException
589
     */
590 23
    public static function isEmpty($value, $message = '')
591
    {
592 23
        if (!empty($value)) {
593 8
            static::reportInvalidArgument(\sprintf(
594 8
                $message ?: 'Expected an empty value. Got: %s',
595 8
                static::valueToString($value)
596
            ));
597
        }
598 15
    }
599
600
    /**
601
     * @psalm-assert !empty $value
602
     *
603
     * @param mixed  $value
604
     * @param string $message
605
     *
606
     * @throws InvalidArgumentException
607
     */
608 23
    public static function notEmpty($value, $message = '')
609
    {
610 23
        if (empty($value)) {
611 15
            static::reportInvalidArgument(\sprintf(
612 15
                $message ?: 'Expected a non-empty value. Got: %s',
613 15
                static::valueToString($value)
614
            ));
615
        }
616 8
    }
617
618
    /**
619
     * @psalm-assert null $value
620
     *
621
     * @param mixed  $value
622
     * @param string $message
623
     *
624
     * @throws InvalidArgumentException
625
     */
626 11
    public static function null($value, $message = '')
627
    {
628 11
        if (null !== $value) {
629 8
            static::reportInvalidArgument(\sprintf(
630 8
                $message ?: 'Expected null. Got: %s',
631 8
                static::valueToString($value)
632
            ));
633
        }
634 3
    }
635
636
    /**
637
     * @psalm-assert !null $value
638
     *
639
     * @param mixed  $value
640
     * @param string $message
641
     *
642
     * @throws InvalidArgumentException
643
     */
644 11
    public static function notNull($value, $message = '')
645
    {
646 11
        if (null === $value) {
647 3
            static::reportInvalidArgument(
648 3
                $message ?: 'Expected a value other than null.'
649
            );
650
        }
651 8
    }
652
653
    /**
654
     * @psalm-assert true $value
655
     *
656
     * @param mixed  $value
657
     * @param string $message
658
     *
659
     * @throws InvalidArgumentException
660
     */
661 15
    public static function true($value, $message = '')
662
    {
663 15
        if (true !== $value) {
664 11
            static::reportInvalidArgument(\sprintf(
665 11
                $message ?: 'Expected a value to be true. Got: %s',
666 11
                static::valueToString($value)
667
            ));
668
        }
669 4
    }
670
671
    /**
672
     * @psalm-assert false $value
673
     *
674
     * @param mixed  $value
675
     * @param string $message
676
     *
677
     * @throws InvalidArgumentException
678
     */
679 19
    public static function false($value, $message = '')
680
    {
681 19
        if (false !== $value) {
682 15
            static::reportInvalidArgument(\sprintf(
683 15
                $message ?: 'Expected a value to be false. Got: %s',
684 15
                static::valueToString($value)
685
            ));
686
        }
687 4
    }
688
689
    /**
690
     * @psalm-assert string $value
691
     *
692
     * @param mixed  $value
693
     * @param string $message
694
     *
695
     * @throws InvalidArgumentException
696
     */
697 51 View Code Duplication
    public static function ip($value, $message = '')
698
    {
699 51
        static::string($value, $message);
700 32
        if (false === \filter_var($value, \FILTER_VALIDATE_IP)) {
701 4
            static::reportInvalidArgument(\sprintf(
702 4
                $message ?: 'Expected a value to be an IP. Got: %s',
703 4
                static::valueToString($value)
704
            ));
705
        }
706 28
    }
707
708
    /**
709
     * @psalm-assert string $value
710
     *
711
     * @param mixed  $value
712
     * @param string $message
713
     *
714
     * @throws InvalidArgumentException
715
     */
716 51 View Code Duplication
    public static function ipv4($value, $message = '')
717
    {
718 51
        static::string($value, $message);
719 32
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
720 20
            static::reportInvalidArgument(\sprintf(
721 20
                $message ?: 'Expected a value to be an IPv4. Got: %s',
722 20
                static::valueToString($value)
723
            ));
724
        }
725 12
    }
726
727
    /**
728
     * @psalm-assert string $value
729
     *
730
     * @param mixed  $value
731
     * @param string $message
732
     *
733
     * @throws InvalidArgumentException
734
     */
735 51 View Code Duplication
    public static function ipv6($value, $message = '')
736
    {
737 51
        static::string($value, $message);
738 32
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
739 16
            static::reportInvalidArgument(\sprintf(
740 16
                $message ?: 'Expected a value to be an IPv6. Got %s',
741 16
                static::valueToString($value)
742
            ));
743
        }
744 16
    }
745
746
    /**
747
     * @psalm-assert string $value
748
     *
749
     * @param mixed  $value
750
     * @param string $message
751
     *
752
     * @throws InvalidArgumentException
753
     */
754 20 View Code Duplication
    public static function email($value, $message = '')
755
    {
756 20
        static::string($value, $message);
757 12
        if (false === \filter_var($value, FILTER_VALIDATE_EMAIL)) {
758 8
            static::reportInvalidArgument(\sprintf(
759 8
                $message ?: 'Expected a value to be a valid e-mail address. Got %s',
760 8
                static::valueToString($value)
761
            ));
762
        }
763 4
    }
764
765
    /**
766
     * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion.
767
     *
768
     * @param array  $values
769
     * @param string $message
770
     *
771
     * @throws InvalidArgumentException
772
     */
773 12
    public static function uniqueValues(array $values, $message = '')
774
    {
775 12
        $allValues = \count($values);
776 12
        $uniqueValues = \count(\array_unique($values));
777
778 12
        if ($allValues !== $uniqueValues) {
779 8
            $difference = $allValues - $uniqueValues;
780
781 8
            static::reportInvalidArgument(\sprintf(
782 8
                $message ?: 'Expected an array of unique values, but %s of them %s duplicated',
783 8
                $difference,
784 8
                (1 === $difference ? 'is' : 'are')
785
            ));
786
        }
787 4
    }
788
789
    /**
790
     * @param mixed  $value
791
     * @param mixed  $expect
792
     * @param string $message
793
     *
794
     * @throws InvalidArgumentException
795
     */
796 33
    public static function eq($value, $expect, $message = '')
797
    {
798 33
        if ($expect != $value) {
799 17
            static::reportInvalidArgument(\sprintf(
800 17
                $message ?: 'Expected a value equal to %2$s. Got: %s',
801 17
                static::valueToString($value),
802 17
                static::valueToString($expect)
803
            ));
804
        }
805 16
    }
806
807
    /**
808
     * @param mixed  $value
809
     * @param mixed  $expect
810
     * @param string $message
811
     *
812
     * @throws InvalidArgumentException
813
     */
814 28
    public static function notEq($value, $expect, $message = '')
815
    {
816 28
        if ($expect == $value) {
817 16
            static::reportInvalidArgument(\sprintf(
818 16
                $message ?: 'Expected a different value than %s.',
819 16
                static::valueToString($expect)
820
            ));
821
        }
822 12
    }
823
824
    /**
825
     * @psalm-template ExpectedType
826
     * @psalm-param ExpectedType $expect
827
     * @psalm-assert =ExpectedType $value
828
     *
829
     * @param mixed  $value
830
     * @param mixed  $expect
831
     * @param string $message
832
     *
833
     * @throws InvalidArgumentException
834
     */
835 16
    public static function same($value, $expect, $message = '')
836
    {
837 16
        if ($expect !== $value) {
838 12
            static::reportInvalidArgument(\sprintf(
839 12
                $message ?: 'Expected a value identical to %2$s. Got: %s',
840 12
                static::valueToString($value),
841 12
                static::valueToString($expect)
842
            ));
843
        }
844 4
    }
845
846
    /**
847
     * @param mixed  $value
848
     * @param mixed  $expect
849
     * @param string $message
850
     *
851
     * @throws InvalidArgumentException
852
     */
853 16
    public static function notSame($value, $expect, $message = '')
854
    {
855 16
        if ($expect === $value) {
856 4
            static::reportInvalidArgument(\sprintf(
857 4
                $message ?: 'Expected a value not identical to %s.',
858 4
                static::valueToString($expect)
859
            ));
860
        }
861 12
    }
862
863
    /**
864
     * @param mixed  $value
865
     * @param mixed  $limit
866
     * @param string $message
867
     *
868
     * @throws InvalidArgumentException
869
     */
870 8
    public static function greaterThan($value, $limit, $message = '')
871
    {
872 8
        if ($value <= $limit) {
873 4
            static::reportInvalidArgument(\sprintf(
874 4
                $message ?: 'Expected a value greater than %2$s. Got: %s',
875 4
                static::valueToString($value),
876 4
                static::valueToString($limit)
877
            ));
878
        }
879 4
    }
880
881
    /**
882
     * @param mixed  $value
883
     * @param mixed  $limit
884
     * @param string $message
885
     *
886
     * @throws InvalidArgumentException
887
     */
888 12
    public static function greaterThanEq($value, $limit, $message = '')
889
    {
890 12
        if ($value < $limit) {
891 4
            static::reportInvalidArgument(\sprintf(
892 4
                $message ?: 'Expected a value greater than or equal to %2$s. Got: %s',
893 4
                static::valueToString($value),
894 4
                static::valueToString($limit)
895
            ));
896
        }
897 8
    }
898
899
    /**
900
     * @param mixed  $value
901
     * @param mixed  $limit
902
     * @param string $message
903
     *
904
     * @throws InvalidArgumentException
905
     */
906 8
    public static function lessThan($value, $limit, $message = '')
907
    {
908 8
        if ($value >= $limit) {
909 4
            static::reportInvalidArgument(\sprintf(
910 4
                $message ?: 'Expected a value less than %2$s. Got: %s',
911 4
                static::valueToString($value),
912 4
                static::valueToString($limit)
913
            ));
914
        }
915 4
    }
916
917
    /**
918
     * @param mixed  $value
919
     * @param mixed  $limit
920
     * @param string $message
921
     *
922
     * @throws InvalidArgumentException
923
     */
924 12
    public static function lessThanEq($value, $limit, $message = '')
925
    {
926 12
        if ($value > $limit) {
927 4
            static::reportInvalidArgument(\sprintf(
928 4
                $message ?: 'Expected a value less than or equal to %2$s. Got: %s',
929 4
                static::valueToString($value),
930 4
                static::valueToString($limit)
931
            ));
932
        }
933 8
    }
934
935
    /**
936
     * Inclusive range, so Assert::(3, 3, 5) passes.
937
     *
938
     * @param mixed  $value
939
     * @param mixed  $min
940
     * @param mixed  $max
941
     * @param string $message
942
     *
943
     * @throws InvalidArgumentException
944
     */
945 16 View Code Duplication
    public static function range($value, $min, $max, $message = '')
946
    {
947 16
        if ($value < $min || $value > $max) {
948 8
            static::reportInvalidArgument(\sprintf(
949 8
                $message ?: 'Expected a value between %2$s and %3$s. Got: %s',
950 8
                static::valueToString($value),
951 8
                static::valueToString($min),
952 8
                static::valueToString($max)
953
            ));
954
        }
955 8
    }
956
957
    /**
958
     * Does strict comparison, so Assert::oneOf(3, ['3']) does not pass the assertion.
959
     *
960
     * @psalm-template ExpectedType
961
     * @psalm-param array<ExpectedType> $values
962
     * @psalm-assert ExpectedType $value
963
     *
964
     * @param mixed  $value
965
     * @param array  $values
966
     * @param string $message
967
     *
968
     * @throws InvalidArgumentException
969
     */
970 8
    public static function oneOf($value, array $values, $message = '')
971
    {
972 8
        if (!\in_array($value, $values, true)) {
973 4
            static::reportInvalidArgument(\sprintf(
974 4
                $message ?: 'Expected one of: %2$s. Got: %s',
975 4
                static::valueToString($value),
976 4
                \implode(', ', \array_map(array('static', 'valueToString'), $values))
977
            ));
978
        }
979 4
    }
980
981
    /**
982
     * @param mixed  $value
983
     * @param string $subString
984
     * @param string $message
985
     *
986
     * @throws InvalidArgumentException
987
     */
988 80 View Code Duplication
    public static function contains($value, $subString, $message = '')
989
    {
990 80
        if (false === \strpos($value, $subString)) {
991 32
            static::reportInvalidArgument(\sprintf(
992 32
                $message ?: 'Expected a value to contain %2$s. Got: %s',
993 32
                static::valueToString($value),
994 32
                static::valueToString($subString)
995
            ));
996
        }
997 48
    }
998
999
    /**
1000
     * @param mixed  $value
1001
     * @param string $subString
1002
     * @param string $message
1003
     *
1004
     * @throws InvalidArgumentException
1005
     */
1006 80 View Code Duplication
    public static function notContains($value, $subString, $message = '')
1007
    {
1008 80
        if (false !== \strpos($value, $subString)) {
1009 48
            static::reportInvalidArgument(\sprintf(
1010 48
                $message ?: '%2$s was not expected to be contained in a value. Got: %s',
1011 48
                static::valueToString($value),
1012 48
                static::valueToString($subString)
1013
            ));
1014
        }
1015 32
    }
1016
1017
    /**
1018
     * @param mixed  $value
1019
     * @param string $message
1020
     *
1021
     * @throws InvalidArgumentException
1022
     */
1023 40
    public static function notWhitespaceOnly($value, $message = '')
1024
    {
1025 40
        if (\preg_match('/^\s*$/', $value)) {
1026 24
            static::reportInvalidArgument(\sprintf(
1027 24
                $message ?: 'Expected a non-whitespace string. Got: %s',
1028 24
                static::valueToString($value)
1029
            ));
1030
        }
1031 16
    }
1032
1033
    /**
1034
     * @param mixed  $value
1035
     * @param string $prefix
1036
     * @param string $message
1037
     *
1038
     * @throws InvalidArgumentException
1039
     */
1040 48 View Code Duplication
    public static function startsWith($value, $prefix, $message = '')
1041
    {
1042 48
        if (0 !== \strpos($value, $prefix)) {
1043 32
            static::reportInvalidArgument(\sprintf(
1044 32
                $message ?: 'Expected a value to start with %2$s. Got: %s',
1045 32
                static::valueToString($value),
1046 32
                static::valueToString($prefix)
1047
            ));
1048
        }
1049 16
    }
1050
1051
    /**
1052
     * @psalm-assert string $value
1053
     *
1054
     * @param mixed  $value
1055
     * @param string $message
1056
     *
1057
     * @throws InvalidArgumentException
1058
     */
1059 35
    public static function startsWithLetter($value, $message = '')
1060
    {
1061 35
        static::string($value);
1062
1063 24
        $valid = isset($value[0]);
1064
1065 24
        if ($valid) {
1066 20
            $locale = \setlocale(LC_CTYPE, 0);
1067 20
            \setlocale(LC_CTYPE, 'C');
1068 20
            $valid = \ctype_alpha($value[0]);
1069 20
            \setlocale(LC_CTYPE, $locale);
1070
        }
1071
1072 24
        if (!$valid) {
1073 12
            static::reportInvalidArgument(\sprintf(
1074 12
                $message ?: 'Expected a value to start with a letter. Got: %s',
1075 12
                static::valueToString($value)
1076
            ));
1077
        }
1078 12
    }
1079
1080
    /**
1081
     * @param mixed  $value
1082
     * @param string $suffix
1083
     * @param string $message
1084
     *
1085
     * @throws InvalidArgumentException
1086
     */
1087 48 View Code Duplication
    public static function endsWith($value, $suffix, $message = '')
1088
    {
1089 48
        if ($suffix !== \substr($value, -\strlen($suffix))) {
1090 32
            static::reportInvalidArgument(\sprintf(
1091 32
                $message ?: 'Expected a value to end with %2$s. Got: %s',
1092 32
                static::valueToString($value),
1093 32
                static::valueToString($suffix)
1094
            ));
1095
        }
1096 16
    }
1097
1098
    /**
1099
     * @param mixed  $value
1100
     * @param mixed  $pattern
1101
     * @param string $message
1102
     *
1103
     * @throws InvalidArgumentException
1104
     */
1105 12
    public static function regex($value, $pattern, $message = '')
1106
    {
1107 12
        if (!\preg_match($pattern, $value)) {
1108 8
            static::reportInvalidArgument(\sprintf(
1109 8
                $message ?: 'The value %s does not match the expected pattern.',
1110 8
                static::valueToString($value)
1111
            ));
1112
        }
1113 4
    }
1114
1115
    /**
1116
     * @param mixed  $value
1117
     * @param mixed  $pattern
1118
     * @param string $message
1119
     *
1120
     * @throws InvalidArgumentException
1121
     */
1122 12
    public static function notRegex($value, $pattern, $message = '')
1123
    {
1124 12
        if (\preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) {
1125 4
            static::reportInvalidArgument(\sprintf(
1126 4
                $message ?: 'The value %s matches the pattern %s (at offset %d).',
1127 4
                static::valueToString($value),
1128 4
                static::valueToString($pattern),
1129 4
                $matches[0][1]
1130
            ));
1131
        }
1132 8
    }
1133
1134
    /**
1135
     * @psalm-assert !numeric $value
1136
     *
1137
     * @param mixed  $value
1138
     * @param string $message
1139
     *
1140
     * @throws InvalidArgumentException
1141
     */
1142 28 View Code Duplication
    public static function unicodeLetters($value, $message = '')
1143
    {
1144 28
        static::string($value);
1145
1146 28
        if (!\preg_match('/^\p{L}+$/u', $value)) {
1147 16
            static::reportInvalidArgument(\sprintf(
1148 16
                $message ?: 'Expected a value to contain only Unicode letters. Got: %s',
1149 16
                static::valueToString($value)
1150
            ));
1151
        }
1152 12
    }
1153
1154
    /**
1155
     * @psalm-assert string $value
1156
     *
1157
     * @param mixed  $value
1158
     * @param string $message
1159
     *
1160
     * @throws InvalidArgumentException
1161
     */
1162 20 View Code Duplication
    public static function alpha($value, $message = '')
1163
    {
1164 20
        static::string($value);
1165
1166 12
        $locale = \setlocale(LC_CTYPE, 0);
1167 12
        \setlocale(LC_CTYPE, 'C');
1168 12
        $valid = !\ctype_alpha($value);
1169 12
        \setlocale(LC_CTYPE, $locale);
1170
1171 12
        if ($valid) {
1172 8
            static::reportInvalidArgument(\sprintf(
1173 8
                $message ?: 'Expected a value to contain only letters. Got: %s',
1174 8
                static::valueToString($value)
1175
            ));
1176
        }
1177 4
    }
1178
1179
    /**
1180
     * @param mixed  $value
1181
     * @param string $message
1182
     *
1183
     * @throws InvalidArgumentException
1184
     */
1185 12 View Code Duplication
    public static function digits($value, $message = '')
1186
    {
1187 12
        $locale = \setlocale(LC_CTYPE, 0);
1188 12
        \setlocale(LC_CTYPE, 'C');
1189 12
        $valid = !\ctype_digit($value);
1190 12
        \setlocale(LC_CTYPE, $locale);
1191
1192 12
        if ($valid) {
1193 8
            static::reportInvalidArgument(\sprintf(
1194 8
                $message ?: 'Expected a value to contain digits only. Got: %s',
1195 8
                static::valueToString($value)
1196
            ));
1197
        }
1198 4
    }
1199
1200
    /**
1201
     * @param mixed  $value
1202
     * @param string $message
1203
     *
1204
     * @throws InvalidArgumentException
1205
     */
1206 12 View Code Duplication
    public static function alnum($value, $message = '')
1207
    {
1208 12
        $locale = \setlocale(LC_CTYPE, 0);
1209 12
        \setlocale(LC_CTYPE, 'C');
1210 12
        $valid = !\ctype_alnum($value);
1211 12
        \setlocale(LC_CTYPE, $locale);
1212
1213 12
        if ($valid) {
1214 8
            static::reportInvalidArgument(\sprintf(
1215 8
                $message ?: 'Expected a value to contain letters and digits only. Got: %s',
1216 8
                static::valueToString($value)
1217
            ));
1218
        }
1219 4
    }
1220
1221
    /**
1222
     * @param mixed  $value
1223
     * @param string $message
1224
     *
1225
     * @throws InvalidArgumentException
1226
     */
1227 16 View Code Duplication
    public static function lower($value, $message = '')
1228
    {
1229 16
        $locale = \setlocale(LC_CTYPE, 0);
1230 16
        \setlocale(LC_CTYPE, 'C');
1231 16
        $valid = !\ctype_lower($value);
1232 16
        \setlocale(LC_CTYPE, $locale);
1233
1234 16
        if ($valid) {
1235 12
            static::reportInvalidArgument(\sprintf(
1236 12
                $message ?: 'Expected a value to contain lowercase characters only. Got: %s',
1237 12
                static::valueToString($value)
1238
            ));
1239
        }
1240 4
    }
1241
1242
    /**
1243
     * @param mixed  $value
1244
     * @param string $message
1245
     *
1246
     * @throws InvalidArgumentException
1247
     */
1248 16 View Code Duplication
    public static function upper($value, $message = '')
1249
    {
1250 16
        $locale = \setlocale(LC_CTYPE, 0);
1251 16
        \setlocale(LC_CTYPE, 'C');
1252 16
        $valid = !\ctype_upper($value);
1253 16
        \setlocale(LC_CTYPE, $locale);
1254
1255 16
        if ($valid) {
1256 12
            static::reportInvalidArgument(\sprintf(
1257 12
                $message ?: 'Expected a value to contain uppercase characters only. Got: %s',
1258 12
                static::valueToString($value)
1259
            ));
1260
        }
1261 4
    }
1262
1263
    /**
1264
     * @param mixed  $value
1265
     * @param mixed  $length
1266
     * @param string $message
1267
     *
1268
     * @throws InvalidArgumentException
1269
     */
1270 36
    public static function length($value, $length, $message = '')
1271
    {
1272 36
        if ($length !== static::strlen($value)) {
1273 24
            static::reportInvalidArgument(\sprintf(
1274 24
                $message ?: 'Expected a value to contain %2$s characters. Got: %s',
1275 24
                static::valueToString($value),
1276 24
                $length
1277
            ));
1278
        }
1279 12
    }
1280
1281
    /**
1282
     * Inclusive min.
1283
     *
1284
     * @param mixed  $value
1285
     * @param mixed  $min
1286
     * @param string $message
1287
     *
1288
     * @throws InvalidArgumentException
1289
     */
1290 36
    public static function minLength($value, $min, $message = '')
1291
    {
1292 36
        if (static::strlen($value) < $min) {
1293 12
            static::reportInvalidArgument(\sprintf(
1294 12
                $message ?: 'Expected a value to contain at least %2$s characters. Got: %s',
1295 12
                static::valueToString($value),
1296 12
                $min
1297
            ));
1298
        }
1299 24
    }
1300
1301
    /**
1302
     * Inclusive max.
1303
     *
1304
     * @param mixed  $value
1305
     * @param mixed  $max
1306
     * @param string $message
1307
     *
1308
     * @throws InvalidArgumentException
1309
     */
1310 36
    public static function maxLength($value, $max, $message = '')
1311
    {
1312 36
        if (static::strlen($value) > $max) {
1313 12
            static::reportInvalidArgument(\sprintf(
1314 12
                $message ?: 'Expected a value to contain at most %2$s characters. Got: %s',
1315 12
                static::valueToString($value),
1316 12
                $max
1317
            ));
1318
        }
1319 24
    }
1320
1321
    /**
1322
     * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion.
1323
     *
1324
     * @param mixed  $value
1325
     * @param mixed  $min
1326
     * @param mixed  $max
1327
     * @param string $message
1328
     *
1329
     * @throws InvalidArgumentException
1330
     */
1331 60 View Code Duplication
    public static function lengthBetween($value, $min, $max, $message = '')
1332
    {
1333 60
        $length = static::strlen($value);
1334
1335 60
        if ($length < $min || $length > $max) {
1336 24
            static::reportInvalidArgument(\sprintf(
1337 24
                $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s',
1338 24
                static::valueToString($value),
1339 24
                $min,
1340 24
                $max
1341
            ));
1342
        }
1343 36
    }
1344
1345
    /**
1346
     * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file.
1347
     *
1348
     * @param mixed  $value
1349
     * @param string $message
1350
     *
1351
     * @throws InvalidArgumentException
1352
     */
1353 36 View Code Duplication
    public static function fileExists($value, $message = '')
1354
    {
1355 36
        static::string($value);
1356
1357 36
        if (!\file_exists($value)) {
1358 12
            static::reportInvalidArgument(\sprintf(
1359 12
                $message ?: 'The file %s does not exist.',
1360 12
                static::valueToString($value)
1361
            ));
1362
        }
1363 24
    }
1364
1365
    /**
1366
     * @param mixed  $value
1367
     * @param string $message
1368
     *
1369
     * @throws InvalidArgumentException
1370
     */
1371 12 View Code Duplication
    public static function file($value, $message = '')
1372
    {
1373 12
        static::fileExists($value, $message);
1374
1375 8
        if (!\is_file($value)) {
1376 4
            static::reportInvalidArgument(\sprintf(
1377 4
                $message ?: 'The path %s is not a file.',
1378 4
                static::valueToString($value)
1379
            ));
1380
        }
1381 4
    }
1382
1383
    /**
1384
     * @param mixed  $value
1385
     * @param string $message
1386
     *
1387
     * @throws InvalidArgumentException
1388
     */
1389 12 View Code Duplication
    public static function directory($value, $message = '')
1390
    {
1391 12
        static::fileExists($value, $message);
1392
1393 8
        if (!\is_dir($value)) {
1394 4
            static::reportInvalidArgument(\sprintf(
1395 4
                $message ?: 'The path %s is no directory.',
1396 4
                static::valueToString($value)
1397
            ));
1398
        }
1399 4
    }
1400
1401
    /**
1402
     * @param mixed  $value
1403
     * @param string $message
1404
     *
1405
     * @throws InvalidArgumentException
1406
     */
1407
    public static function readable($value, $message = '')
1408
    {
1409
        if (!\is_readable($value)) {
1410
            static::reportInvalidArgument(\sprintf(
1411
                $message ?: 'The path %s is not readable.',
1412
                static::valueToString($value)
1413
            ));
1414
        }
1415
    }
1416
1417
    /**
1418
     * @param mixed  $value
1419
     * @param string $message
1420
     *
1421
     * @throws InvalidArgumentException
1422
     */
1423
    public static function writable($value, $message = '')
1424
    {
1425
        if (!\is_writable($value)) {
1426
            static::reportInvalidArgument(\sprintf(
1427
                $message ?: 'The path %s is not writable.',
1428
                static::valueToString($value)
1429
            ));
1430
        }
1431
    }
1432
1433
    /**
1434
     * @psalm-assert class-string $value
1435
     *
1436
     * @param mixed  $value
1437
     * @param string $message
1438
     *
1439
     * @throws InvalidArgumentException
1440
     */
1441 8
    public static function classExists($value, $message = '')
1442
    {
1443 8
        if (!\class_exists($value)) {
1444 4
            static::reportInvalidArgument(\sprintf(
1445 4
                $message ?: 'Expected an existing class name. Got: %s',
1446 4
                static::valueToString($value)
1447
            ));
1448
        }
1449 4
    }
1450
1451
    /**
1452
     * @param mixed         $value
1453
     * @param string|object $class
1454
     * @param string        $message
1455
     *
1456
     * @throws InvalidArgumentException
1457
     */
1458 8
    public static function subclassOf($value, $class, $message = '')
1459
    {
1460 8
        if (!\is_subclass_of($value, $class)) {
1461 4
            static::reportInvalidArgument(\sprintf(
1462 4
                $message ?: 'Expected a sub-class of %2$s. Got: %s',
1463 4
                static::valueToString($value),
1464 4
                static::valueToString($class)
1465
            ));
1466
        }
1467 4
    }
1468
1469
    /**
1470
     * @psalm-assert class-string $value
1471
     *
1472
     * @param mixed  $value
1473
     * @param string $message
1474
     *
1475
     * @throws InvalidArgumentException
1476
     */
1477 8
    public static function interfaceExists($value, $message = '')
1478
    {
1479 8
        if (!\interface_exists($value)) {
1480 4
            static::reportInvalidArgument(\sprintf(
1481 4
                $message ?: 'Expected an existing interface name. got %s',
1482 4
                static::valueToString($value)
1483
            ));
1484
        }
1485 4
    }
1486
1487
    /**
1488
     * @param mixed  $value
1489
     * @param mixed  $interface
1490
     * @param string $message
1491
     *
1492
     * @throws InvalidArgumentException
1493
     */
1494 8 View Code Duplication
    public static function implementsInterface($value, $interface, $message = '')
1495
    {
1496 8
        if (!\in_array($interface, \class_implements($value))) {
1497 4
            static::reportInvalidArgument(\sprintf(
1498 4
                $message ?: 'Expected an implementation of %2$s. Got: %s',
1499 4
                static::valueToString($value),
1500 4
                static::valueToString($interface)
1501
            ));
1502
        }
1503 4
    }
1504
1505
    /**
1506
     * @param string|object $classOrObject
1507
     * @param mixed         $property
1508
     * @param string        $message
1509
     *
1510
     * @throws InvalidArgumentException
1511
     */
1512 12 View Code Duplication
    public static function propertyExists($classOrObject, $property, $message = '')
1513
    {
1514 12
        if (!\property_exists($classOrObject, $property)) {
1515 4
            static::reportInvalidArgument(\sprintf(
1516 4
                $message ?: 'Expected the property %s to exist.',
1517 4
                static::valueToString($property)
1518
            ));
1519
        }
1520 8
    }
1521
1522
    /**
1523
     * @param string|object $classOrObject
1524
     * @param mixed         $property
1525
     * @param string        $message
1526
     *
1527
     * @throws InvalidArgumentException
1528
     */
1529 12 View Code Duplication
    public static function propertyNotExists($classOrObject, $property, $message = '')
1530
    {
1531 12
        if (\property_exists($classOrObject, $property)) {
1532 8
            static::reportInvalidArgument(\sprintf(
1533 8
                $message ?: 'Expected the property %s to not exist.',
1534 8
                static::valueToString($property)
1535
            ));
1536
        }
1537 4
    }
1538
1539
    /**
1540
     * @param string|object $classOrObject
1541
     * @param mixed         $method
1542
     * @param string        $message
1543
     *
1544
     * @throws InvalidArgumentException
1545
     */
1546 27 View Code Duplication
    public static function methodExists($classOrObject, $method, $message = '')
1547
    {
1548 27
        if (!\method_exists($classOrObject, $method)) {
1549 19
            static::reportInvalidArgument(\sprintf(
1550 19
                $message ?: 'Expected the method %s to exist.',
1551 19
                static::valueToString($method)
1552
            ));
1553
        }
1554 8
    }
1555
1556
    /**
1557
     * @param string|object $classOrObject
1558
     * @param mixed         $method
1559
     * @param string        $message
1560
     *
1561
     * @throws InvalidArgumentException
1562
     */
1563 27 View Code Duplication
    public static function methodNotExists($classOrObject, $method, $message = '')
1564
    {
1565 27
        if (\method_exists($classOrObject, $method)) {
1566 8
            static::reportInvalidArgument(\sprintf(
1567 8
                $message ?: 'Expected the method %s to not exist.',
1568 8
                static::valueToString($method)
1569
            ));
1570
        }
1571 19
    }
1572
1573
    /**
1574
     * @param array      $array
1575
     * @param string|int $key
1576
     * @param string     $message
1577
     *
1578
     * @throws InvalidArgumentException
1579
     */
1580 12 View Code Duplication
    public static function keyExists($array, $key, $message = '')
1581
    {
1582 12
        if (!(isset($array[$key]) || \array_key_exists($key, $array))) {
1583 4
            static::reportInvalidArgument(\sprintf(
1584 4
                $message ?: 'Expected the key %s to exist.',
1585 4
                static::valueToString($key)
1586
            ));
1587
        }
1588 8
    }
1589
1590
    /**
1591
     * @param array      $array
1592
     * @param string|int $key
1593
     * @param string     $message
1594
     *
1595
     * @throws InvalidArgumentException
1596
     */
1597 12 View Code Duplication
    public static function keyNotExists($array, $key, $message = '')
1598
    {
1599 12
        if (isset($array[$key]) || \array_key_exists($key, $array)) {
1600 8
            static::reportInvalidArgument(\sprintf(
1601 8
                $message ?: 'Expected the key %s to not exist.',
1602 8
                static::valueToString($key)
1603
            ));
1604
        }
1605 4
    }
1606
1607
    /**
1608
     * Checks if a value is a valid array key (int or string).
1609
     *
1610
     * @param mixed  $key
0 ignored issues
show
Bug introduced by
There is no parameter named $key. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1611
     * @param string $message
1612
     *
1613
     * @throws InvalidArgumentException
1614
     */
1615 28
    public static function validArrayKey($value, $message = '')
1616
    {
1617 28
        if (!(\is_int($value) || \is_string($value))) {
1618 20
            static::reportInvalidArgument(\sprintf(
1619 20
                $message ?: 'Expected string or integer. Got: %s',
1620 20
                static::typeToString($value)
1621
            ));
1622
        }
1623 8
    }
1624
1625
    /**
1626
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1627
     *
1628
     * @param mixed  $array
1629
     * @param mixed  $number
1630
     * @param string $message
1631
     *
1632
     * @throws InvalidArgumentException
1633
     */
1634 8
    public static function count($array, $number, $message = '')
1635
    {
1636 8
        static::eq(
1637 8
            \count($array),
1638
            $number,
1639 8
            $message ?: \sprintf('Expected an array to contain %d elements. Got: %d.', $number, \count($array))
1640
        );
1641 4
    }
1642
1643
    /**
1644
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1645
     *
1646
     * @param mixed  $array
1647
     * @param mixed  $min
1648
     * @param string $message
1649
     *
1650
     * @throws InvalidArgumentException
1651
     */
1652 12 View Code Duplication
    public static function minCount($array, $min, $message = '')
1653
    {
1654 12
        if (\count($array) < $min) {
1655 4
            static::reportInvalidArgument(\sprintf(
1656 4
                $message ?: 'Expected an array to contain at least %2$d elements. Got: %d',
1657 4
                \count($array),
1658 4
                $min
1659
            ));
1660
        }
1661 8
    }
1662
1663
    /**
1664
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1665
     *
1666
     * @param mixed  $array
1667
     * @param mixed  $max
1668
     * @param string $message
1669
     *
1670
     * @throws InvalidArgumentException
1671
     */
1672 12 View Code Duplication
    public static function maxCount($array, $max, $message = '')
1673
    {
1674 12
        if (\count($array) > $max) {
1675 4
            static::reportInvalidArgument(\sprintf(
1676 4
                $message ?: 'Expected an array to contain at most %2$d elements. Got: %d',
1677 4
                \count($array),
1678 4
                $max
1679
            ));
1680
        }
1681 8
    }
1682
1683
    /**
1684
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1685
     *
1686
     * @param mixed  $array
1687
     * @param mixed  $min
1688
     * @param mixed  $max
1689
     * @param string $message
1690
     *
1691
     * @throws InvalidArgumentException
1692
     */
1693 20
    public static function countBetween($array, $min, $max, $message = '')
1694
    {
1695 20
        $count = \count($array);
1696
1697 20
        if ($count < $min || $count > $max) {
1698 8
            static::reportInvalidArgument(\sprintf(
1699 8
                $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d',
1700 8
                $count,
1701 8
                $min,
1702 8
                $max
1703
            ));
1704
        }
1705 12
    }
1706
1707
    /**
1708
     * @param mixed  $array
1709
     * @param string $message
1710
     *
1711
     * @throws InvalidArgumentException
1712
     */
1713 24
    public static function isList($array, $message = '')
1714
    {
1715 24
        if (!\is_array($array) || !$array || \array_keys($array) !== \range(0, \count($array) - 1)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $array of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

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

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

Loading history...
1716 20
            static::reportInvalidArgument(
1717 20
                $message ?: 'Expected list - non-associative array.'
1718
            );
1719
        }
1720 4
    }
1721
1722
    /**
1723
     * @param mixed  $array
1724
     * @param string $message
1725
     *
1726
     * @throws InvalidArgumentException
1727
     */
1728 16
    public static function isMap($array, $message = '')
1729
    {
1730
        if (
1731 16
            !\is_array($array) ||
1732 16
            !$array ||
0 ignored issues
show
Bug Best Practice introduced by
The expression $array of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

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

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

Loading history...
1733
            \array_keys($array) !== \array_filter(\array_keys($array), function ($key) {
1734 12
                return \is_string($key);
1735 16
            })
1736
        ) {
1737 12
            static::reportInvalidArgument(
1738 12
                $message ?: 'Expected map - associative array with string keys.'
1739
            );
1740
        }
1741 4
    }
1742
1743
    /**
1744
     * @param mixed  $value
1745
     * @param string $message
1746
     *
1747
     * @throws InvalidArgumentException
1748
     */
1749 56
    public static function uuid($value, $message = '')
1750
    {
1751 56
        $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
1752
1753
        // The nil UUID is special form of UUID that is specified to have all
1754
        // 128 bits set to zero.
1755 56
        if ('00000000-0000-0000-0000-000000000000' === $value) {
1756 4
            return;
1757
        }
1758
1759 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)) {
1760 20
            static::reportInvalidArgument(\sprintf(
1761 20
                $message ?: 'Value %s is not a valid UUID.',
1762 20
                static::valueToString($value)
1763
            ));
1764
        }
1765 32
    }
1766
1767
    /**
1768
     * @param Closure       $expression
1769
     * @param string|object $class
1770
     * @param string        $message
1771
     *
1772
     * @throws InvalidArgumentException
1773
     */
1774 24
    public static function throws(Closure $expression, $class = 'Exception', $message = '')
1775
    {
1776 24
        static::string($class);
1777
1778 24
        $actual = 'none';
1779
1780
        try {
1781 24
            $expression();
1782 24
        } catch (Exception $e) {
1783 20
            $actual = \get_class($e);
1784 20
            if ($e instanceof $class) {
1785 20
                return;
1786
            }
1787 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...
1788 4
            $actual = \get_class($e);
1789 4
            if ($e instanceof $class) {
1790 4
                return;
1791
            }
1792
        }
1793
1794 8
        static::reportInvalidArgument($message ?: \sprintf(
1795 8
            'Expected to throw "%s", got "%s"',
1796 8
            $class,
1797 8
            $actual
1798
        ));
1799
    }
1800
1801
    /**
1802
     * @throws BadMethodCallException
1803
     */
1804 1435
    public static function __callStatic($name, $arguments)
1805
    {
1806 1435
        if ('nullOr' === \substr($name, 0, 6)) {
1807 532
            if (null !== $arguments[0]) {
1808 436
                $method = \lcfirst(\substr($name, 6));
1809 436
                \call_user_func_array(array('static', $method), $arguments);
1810
            }
1811
1812 301
            return;
1813
        }
1814
1815 903
        if ('all' === \substr($name, 0, 3)) {
1816 902
            static::isIterable($arguments[0]);
1817
1818 902
            $method = \lcfirst(\substr($name, 3));
1819 902
            $args = $arguments;
1820
1821 902
            foreach ($arguments[0] as $entry) {
1822 902
                $args[0] = $entry;
1823
1824 902
                \call_user_func_array(array('static', $method), $args);
1825
            }
1826
1827 416
            return;
1828
        }
1829
1830 1
        throw new BadMethodCallException('No such method: '.$name);
1831
    }
1832
1833
    /**
1834
     * @param mixed $value
1835
     *
1836
     * @return string
1837
     */
1838 645
    protected static function valueToString($value)
1839
    {
1840 645
        if (null === $value) {
1841 11
            return 'null';
1842
        }
1843
1844 636
        if (true === $value) {
1845 15
            return 'true';
1846
        }
1847
1848 626
        if (false === $value) {
1849 13
            return 'false';
1850
        }
1851
1852 613
        if (\is_array($value)) {
1853 1
            return 'array';
1854
        }
1855
1856 612
        if (\is_object($value)) {
1857 2
            if (\method_exists($value, '__toString')) {
1858 1
                return \get_class($value).': '.self::valueToString($value->__toString());
1859
            }
1860
1861 1
            return \get_class($value);
1862
        }
1863
1864 611
        if (\is_resource($value)) {
1865 1
            return 'resource';
1866
        }
1867
1868 611
        if (\is_string($value)) {
1869 525
            return '"'.$value.'"';
1870
        }
1871
1872 94
        return (string) $value;
1873
    }
1874
1875
    /**
1876
     * @param mixed $value
1877
     *
1878
     * @return string
1879
     */
1880 276
    protected static function typeToString($value)
1881
    {
1882 276
        return \is_object($value) ? \get_class($value) : \gettype($value);
1883
    }
1884
1885 168
    protected static function strlen($value)
1886
    {
1887 168
        if (!\function_exists('mb_detect_encoding')) {
1888
            return \strlen($value);
1889
        }
1890
1891 168
        if (false === $encoding = \mb_detect_encoding($value)) {
1892
            return \strlen($value);
1893
        }
1894
1895 168
        return \mb_strlen($value, $encoding);
1896
    }
1897
1898
    /**
1899
     * @param string $message
1900
     *
1901
     * @throws InvalidArgumentException
1902
     */
1903 976
    protected static function reportInvalidArgument($message)
1904
    {
1905 976
        throw new InvalidArgumentException($message);
1906
    }
1907
1908
    private function __construct()
1909
    {
1910
    }
1911
}
1912