Failed Conditions
Pull Request — master (#148)
by Gert de
02:57
created

Assert::writable()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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