Failed Conditions
Pull Request — master (#106)
by Simon
04:01
created

Assert::isInstanceOf()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

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