Failed Conditions
Pull Request — master (#118)
by Gert de
16:40
created

Assert::same()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

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