Failed Conditions
Pull Request — master (#164)
by Ruud
17:19
created

Assert::minLength()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

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