Failed Conditions
Pull Request — master (#154)
by Gert de
02:52
created

Assert   F

Complexity

Total Complexity 293

Size/Duplication

Total Lines 1695
Duplicated Lines 18.17 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 97.16%

Importance

Changes 0
Metric Value
wmc 293
lcom 1
cbo 0
dl 308
loc 1695
ccs 616
cts 634
cp 0.9716
rs 0.8
c 0
b 0
f 0

89 Methods

Rating   Name   Duplication   Size   Complexity  
A isArray() 0 9 3
A isTraversable() 0 17 4
B throws() 0 26 6
A string() 0 9 3
A stringNotEmpty() 0 5 1
A isEmpty() 0 9 3
A uuid() 0 17 4
A __callStatic() 0 28 5
B valueToString() 0 36 9
A typeToString() 0 4 2
A strlen() 0 12 3
A reportInvalidArgument() 0 4 1
A __construct() 0 3 1
A integer() 0 9 3
A integerish() 0 9 4
A float() 0 9 3
A numeric() 0 9 3
A natural() 0 9 4
A boolean() 0 9 3
A scalar() 0 9 3
A object() 0 9 3
A resource() 0 17 6
A isCallable() 0 9 3
A isArrayAccessible() 9 9 4
A isCountable() 0 14 6
A isIterable() 9 9 4
A isInstanceOf() 0 10 3
A notInstanceOf() 0 10 3
A isInstanceOfAny() 0 14 4
A notEmpty() 0 9 3
A null() 0 9 3
A notNull() 0 8 3
A true() 0 9 3
A false() 0 9 3
A ip() 9 9 3
A ipv4() 0 9 3
A ipv6() 0 9 3
A email() 9 9 3
A uniqueValues() 0 15 4
A eq() 0 10 3
A notEq() 0 9 3
A same() 0 10 3
A notSame() 0 9 3
A greaterThan() 0 10 3
A greaterThanEq() 0 10 3
A lessThan() 0 10 3
A lessThanEq() 0 10 3
A range() 11 11 4
A oneOf() 0 10 3
A contains() 10 10 3
A notContains() 10 10 3
A notWhitespaceOnly() 0 9 3
A startsWith() 10 10 3
A startsWithLetter() 0 20 4
A endsWith() 10 10 3
A regex() 0 9 3
A notRegex() 0 11 3
A unicodeLetters() 11 11 3
A alpha() 16 16 3
A digits() 14 14 3
A alnum() 14 14 3
A lower() 14 14 3
A upper() 14 14 3
A length() 0 10 3
A minLength() 0 10 3
A maxLength() 0 10 3
A lengthBetween() 13 13 4
A fileExists() 11 11 3
A file() 11 11 3
A directory() 11 11 3
A readable() 0 9 3
A writable() 0 9 3
A classExists() 0 9 3
A subclassOf() 0 10 3
A interfaceExists() 0 9 3
A implementsInterface() 10 10 3
A propertyExists() 9 9 3
A propertyNotExists() 9 9 3
A methodExists() 9 9 3
A methodNotExists() 9 9 3
A keyExists() 9 9 4
A keyNotExists() 9 9 4
A validArrayKey() 0 9 4
A count() 0 8 2
A minCount() 10 10 3
A maxCount() 10 10 3
A countBetween() 0 13 4
A isList() 8 8 4
A isMap() 0 11 4

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Assert often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Assert, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * This file is part of the webmozart/assert package.
5
 *
6
 * (c) Bernhard Schussek <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Webmozart\Assert;
13
14
use ArrayAccess;
15
use BadMethodCallException;
16
use Closure;
17
use Countable;
18
use Exception;
19
use InvalidArgumentException;
20
use ResourceBundle;
21
use SimpleXMLElement;
22
use Throwable;
23
use Traversable;
24
25
/**
26
 * Efficient assertions to validate the input/output of your methods.
27
 *
28
 * @method static void nullOrString($value, $message = '')
29
 * @method static void nullOrStringNotEmpty($value, $message = '')
30
 * @method static void nullOrInteger($value, $message = '')
31
 * @method static void nullOrIntegerish($value, $message = '')
32
 * @method static void nullOrFloat($value, $message = '')
33
 * @method static void nullOrNumeric($value, $message = '')
34
 * @method static void nullOrNatural($value, $message = '')
35
 * @method static void nullOrBoolean($value, $message = '')
36
 * @method static void nullOrScalar($value, $message = '')
37
 * @method static void nullOrObject($value, $message = '')
38
 * @method static void nullOrResource($value, $type = null, $message = '')
39
 * @method static void nullOrIsCallable($value, $message = '')
40
 * @method static void nullOrIsArray($value, $message = '')
41
 * @method static void nullOrIsTraversable($value, $message = '')
42
 * @method static void nullOrIsArrayAccessible($value, $message = '')
43
 * @method static void nullOrIsCountable($value, $message = '')
44
 * @method static void nullOrIsIterable($value, $message = '')
45
 * @method static void nullOrIsInstanceOf($value, $class, $message = '')
46
 * @method static void nullOrNotInstanceOf($value, $class, $message = '')
47
 * @method static void nullOrIsInstanceOfAny($value, $classes, $message = '')
48
 * @method static void nullOrIsEmpty($value, $message = '')
49
 * @method static void nullOrNotEmpty($value, $message = '')
50
 * @method static void nullOrTrue($value, $message = '')
51
 * @method static void nullOrFalse($value, $message = '')
52
 * @method static void nullOrIp($value, $message = '')
53
 * @method static void nullOrIpv4($value, $message = '')
54
 * @method static void nullOrIpv6($value, $message = '')
55
 * @method static void nullOrEmail($value, $message = '')
56
 * @method static void nullOrUniqueValues($values, $message = '')
57
 * @method static void nullOrEq($value, $expect, $message = '')
58
 * @method static void nullOrNotEq($value, $expect, $message = '')
59
 * @method static void nullOrSame($value, $expect, $message = '')
60
 * @method static void nullOrNotSame($value, $expect, $message = '')
61
 * @method static void nullOrGreaterThan($value, $limit, $message = '')
62
 * @method static void nullOrGreaterThanEq($value, $limit, $message = '')
63
 * @method static void nullOrLessThan($value, $limit, $message = '')
64
 * @method static void nullOrLessThanEq($value, $limit, $message = '')
65
 * @method static void nullOrRange($value, $min, $max, $message = '')
66
 * @method static void nullOrOneOf($value, $values, $message = '')
67
 * @method static void nullOrContains($value, $subString, $message = '')
68
 * @method static void nullOrNotContains($value, $subString, $message = '')
69
 * @method static void nullOrNotWhitespaceOnly($value, $message = '')
70
 * @method static void nullOrStartsWith($value, $prefix, $message = '')
71
 * @method static void nullOrStartsWithLetter($value, $message = '')
72
 * @method static void nullOrEndsWith($value, $suffix, $message = '')
73
 * @method static void nullOrRegex($value, $pattern, $message = '')
74
 * @method static void nullOrNotRegex($value, $pattern, $message = '')
75
 * @method static void nullOrUnicodeLetters($value, $message = '')
76
 * @method static void nullOrAlpha($value, $message = '')
77
 * @method static void nullOrDigits($value, $message = '')
78
 * @method static void nullOrAlnum($value, $message = '')
79
 * @method static void nullOrLower($value, $message = '')
80
 * @method static void nullOrUpper($value, $message = '')
81
 * @method static void nullOrLength($value, $length, $message = '')
82
 * @method static void nullOrMinLength($value, $min, $message = '')
83
 * @method static void nullOrMaxLength($value, $max, $message = '')
84
 * @method static void nullOrLengthBetween($value, $min, $max, $message = '')
85
 * @method static void nullOrFileExists($value, $message = '')
86
 * @method static void nullOrFile($value, $message = '')
87
 * @method static void nullOrDirectory($value, $message = '')
88
 * @method static void nullOrReadable($value, $message = '')
89
 * @method static void nullOrWritable($value, $message = '')
90
 * @method static void nullOrClassExists($value, $message = '')
91
 * @method static void nullOrSubclassOf($value, $class, $message = '')
92
 * @method static void nullOrInterfaceExists($value, $message = '')
93
 * @method static void nullOrImplementsInterface($value, $interface, $message = '')
94
 * @method static void nullOrPropertyExists($value, $property, $message = '')
95
 * @method static void nullOrPropertyNotExists($value, $property, $message = '')
96
 * @method static void nullOrMethodExists($value, $method, $message = '')
97
 * @method static void nullOrMethodNotExists($value, $method, $message = '')
98
 * @method static void nullOrKeyExists($value, $key, $message = '')
99
 * @method static void nullOrKeyNotExists($value, $key, $message = '')
100
 * @method static void nullOrValidArrayKey($value, $message = '')
101
 * @method static void nullOrCount($value, $key, $message = '')
102
 * @method static void nullOrMinCount($value, $min, $message = '')
103
 * @method static void nullOrMaxCount($value, $max, $message = '')
104
 * @method static void nullOrIsList($value, $message = '')
105
 * @method static void nullOrIsMap($value, $message = '')
106
 * @method static void nullOrCountBetween($value, $min, $max, $message = '')
107
 * @method static void nullOrUuid($values, $message = '')
108
 * @method static void nullOrThrows($expression, $class = 'Exception', $message = '')
109
 * @method static void allString($values, $message = '')
110
 * @method static void allStringNotEmpty($values, $message = '')
111
 * @method static void allInteger($values, $message = '')
112
 * @method static void allIntegerish($values, $message = '')
113
 * @method static void allFloat($values, $message = '')
114
 * @method static void allNumeric($values, $message = '')
115
 * @method static void allNatural($values, $message = '')
116
 * @method static void allBoolean($values, $message = '')
117
 * @method static void allScalar($values, $message = '')
118
 * @method static void allObject($values, $message = '')
119
 * @method static void allResource($values, $type = null, $message = '')
120
 * @method static void allIsCallable($values, $message = '')
121
 * @method static void allIsArray($values, $message = '')
122
 * @method static void allIsTraversable($values, $message = '')
123
 * @method static void allIsArrayAccessible($values, $message = '')
124
 * @method static void allIsCountable($values, $message = '')
125
 * @method static void allIsIterable($values, $message = '')
126
 * @method static void allIsInstanceOf($values, $class, $message = '')
127
 * @method static void allNotInstanceOf($values, $class, $message = '')
128
 * @method static void allIsInstanceOfAny($values, $classes, $message = '')
129
 * @method static void allNull($values, $message = '')
130
 * @method static void allNotNull($values, $message = '')
131
 * @method static void allIsEmpty($values, $message = '')
132
 * @method static void allNotEmpty($values, $message = '')
133
 * @method static void allTrue($values, $message = '')
134
 * @method static void allFalse($values, $message = '')
135
 * @method static void allIp($values, $message = '')
136
 * @method static void allIpv4($values, $message = '')
137
 * @method static void allIpv6($values, $message = '')
138
 * @method static void allEmail($values, $message = '')
139
 * @method static void allUniqueValues($values, $message = '')
140
 * @method static void allEq($values, $expect, $message = '')
141
 * @method static void allNotEq($values, $expect, $message = '')
142
 * @method static void allSame($values, $expect, $message = '')
143
 * @method static void allNotSame($values, $expect, $message = '')
144
 * @method static void allGreaterThan($values, $limit, $message = '')
145
 * @method static void allGreaterThanEq($values, $limit, $message = '')
146
 * @method static void allLessThan($values, $limit, $message = '')
147
 * @method static void allLessThanEq($values, $limit, $message = '')
148
 * @method static void allRange($values, $min, $max, $message = '')
149
 * @method static void allOneOf($values, $values, $message = '')
150
 * @method static void allContains($values, $subString, $message = '')
151
 * @method static void allNotContains($values, $subString, $message = '')
152
 * @method static void allNotWhitespaceOnly($values, $message = '')
153
 * @method static void allStartsWith($values, $prefix, $message = '')
154
 * @method static void allStartsWithLetter($values, $message = '')
155
 * @method static void allEndsWith($values, $suffix, $message = '')
156
 * @method static void allRegex($values, $pattern, $message = '')
157
 * @method static void allNotRegex($values, $pattern, $message = '')
158
 * @method static void allUnicodeLetters($values, $message = '')
159
 * @method static void allAlpha($values, $message = '')
160
 * @method static void allDigits($values, $message = '')
161
 * @method static void allAlnum($values, $message = '')
162
 * @method static void allLower($values, $message = '')
163
 * @method static void allUpper($values, $message = '')
164
 * @method static void allLength($values, $length, $message = '')
165
 * @method static void allMinLength($values, $min, $message = '')
166
 * @method static void allMaxLength($values, $max, $message = '')
167
 * @method static void allLengthBetween($values, $min, $max, $message = '')
168
 * @method static void allFileExists($values, $message = '')
169
 * @method static void allFile($values, $message = '')
170
 * @method static void allDirectory($values, $message = '')
171
 * @method static void allReadable($values, $message = '')
172
 * @method static void allWritable($values, $message = '')
173
 * @method static void allClassExists($values, $message = '')
174
 * @method static void allSubclassOf($values, $class, $message = '')
175
 * @method static void allInterfaceExists($values, $message = '')
176
 * @method static void allImplementsInterface($values, $interface, $message = '')
177
 * @method static void allPropertyExists($values, $property, $message = '')
178
 * @method static void allPropertyNotExists($values, $property, $message = '')
179
 * @method static void allMethodExists($values, $method, $message = '')
180
 * @method static void allMethodNotExists($values, $method, $message = '')
181
 * @method static void allKeyExists($values, $key, $message = '')
182
 * @method static void allKeyNotExists($values, $key, $message = '')
183
 * @method static void allValidArrayKey($values, $message = '')
184
 * @method static void allCount($values, $key, $message = '')
185
 * @method static void allMinCount($values, $min, $message = '')
186
 * @method static void allMaxCount($values, $max, $message = '')
187
 * @method static void allCountBetween($values, $min, $max, $message = '')
188
 * @method static void allIsList($values, $message = '')
189
 * @method static void allIsMap($values, $message = '')
190
 * @method static void allUuid($values, $message = '')
191
 * @method static void allThrows($expressions, $class = 'Exception', $message = '')
192
 *
193
 * @since  1.0
194
 *
195
 * @author Bernhard Schussek <[email protected]>
196
 */
197
class Assert
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
198
{
199
    /**
200
     * @psalm-assert string $value
201
     *
202
     * @param mixed  $value
203
     * @param string $message
204
     *
205
     * @throws InvalidArgumentException
206
     */
207 177
    public static function string($value, $message = '')
208
    {
209 177
        if (!\is_string($value)) {
210 33
            static::reportInvalidArgument(\sprintf(
211 33
                $message ?: 'Expected a string. Got: %s',
212 33
                static::typeToString($value)
213
            ));
214
        }
215 144
    }
216
217
    /**
218
     * @param mixed  $value
219
     * @param string $message
220
     *
221
     * @throws InvalidArgumentException
222
     */
223 16
    public static function stringNotEmpty($value, $message = '')
224
    {
225 16
        static::string($value, $message);
226 12
        static::notEq($value, '', $message);
227 8
    }
228
229
    /**
230
     * @psalm-assert int $value
231
     *
232
     * @param mixed  $value
233
     * @param string $message
234
     *
235
     * @throws InvalidArgumentException
236
     */
237 17
    public static function integer($value, $message = '')
238
    {
239 17
        if (!\is_int($value)) {
240 13
            static::reportInvalidArgument(\sprintf(
241 13
                $message ?: 'Expected an integer. Got: %s',
242 13
                static::typeToString($value)
243
            ));
244
        }
245 4
    }
246
247
    /**
248
     * @psalm-assert numeric $value
249
     *
250
     * @param mixed  $value
251
     * @param string $message
252
     *
253
     * @throws InvalidArgumentException
254
     */
255 16
    public static function integerish($value, $message = '')
256
    {
257 16
        if (!\is_numeric($value) || $value != (int) $value) {
258 4
            static::reportInvalidArgument(\sprintf(
259 4
                $message ?: 'Expected an integerish value. Got: %s',
260 4
                static::typeToString($value)
261
            ));
262
        }
263 12
    }
264
265
    /**
266
     * @psalm-assert float $value
267
     *
268
     * @param mixed  $value
269
     * @param string $message
270
     *
271
     * @throws InvalidArgumentException
272
     */
273 16
    public static function float($value, $message = '')
274
    {
275 16
        if (!\is_float($value)) {
276 8
            static::reportInvalidArgument(\sprintf(
277 8
                $message ?: 'Expected a float. Got: %s',
278 8
                static::typeToString($value)
279
            ));
280
        }
281 8
    }
282
283
    /**
284
     * @psalm-assert numeric $value
285
     *
286
     * @param mixed  $value
287
     * @param string $message
288
     *
289
     * @throws InvalidArgumentException
290
     */
291 20
    public static function numeric($value, $message = '')
292
    {
293 20
        if (!\is_numeric($value)) {
294 4
            static::reportInvalidArgument(\sprintf(
295 4
                $message ?: 'Expected a numeric. Got: %s',
296 4
                static::typeToString($value)
297
            ));
298
        }
299 16
    }
300
301
    /**
302
     * @psalm-assert int $value
303
     *
304
     * @param mixed  $value
305
     * @param string $message
306
     *
307
     * @throws InvalidArgumentException
308
     */
309 24
    public static function natural($value, $message = '')
310
    {
311 24
        if (!\is_int($value) || $value < 0) {
312 16
            static::reportInvalidArgument(\sprintf(
313 16
                $message ?: 'Expected a non-negative integer. Got %s',
314 16
                static::valueToString($value)
315
            ));
316
        }
317 8
    }
318
319
    /**
320
     * @psalm-assert bool $value
321
     *
322
     * @param mixed  $value
323
     * @param string $message
324
     *
325
     * @throws InvalidArgumentException
326
     */
327 16
    public static function boolean($value, $message = '')
328
    {
329 16
        if (!\is_bool($value)) {
330 8
            static::reportInvalidArgument(\sprintf(
331 8
                $message ?: 'Expected a boolean. Got: %s',
332 8
                static::typeToString($value)
333
            ));
334
        }
335 8
    }
336
337
    /**
338
     * @psalm-assert scalar $value
339
     *
340
     * @param mixed  $value
341
     * @param string $message
342
     *
343
     * @throws InvalidArgumentException
344
     */
345 23
    public static function scalar($value, $message = '')
346
    {
347 23
        if (!\is_scalar($value)) {
348 11
            static::reportInvalidArgument(\sprintf(
349 11
                $message ?: 'Expected a scalar. Got: %s',
350 11
                static::typeToString($value)
351
            ));
352
        }
353 12
    }
354
355
    /**
356
     * @psalm-assert object $value
357
     *
358
     * @param mixed  $value
359
     * @param string $message
360
     *
361
     * @throws InvalidArgumentException
362
     */
363 23
    public static function object($value, $message = '')
364
    {
365 23
        if (!\is_object($value)) {
366 15
            static::reportInvalidArgument(\sprintf(
367 15
                $message ?: 'Expected an object. Got: %s',
368 15
                static::typeToString($value)
369
            ));
370
        }
371 8
    }
372
373
    /**
374
     * @psalm-assert resource $value
375
     *
376
     * @param mixed       $value
377
     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
378
     * @param string      $message
379
     *
380
     * @throws InvalidArgumentException
381
     */
382 16
    public static function resource($value, $type = null, $message = '')
383
    {
384 16
        if (!\is_resource($value)) {
385 4
            static::reportInvalidArgument(\sprintf(
386 4
                $message ?: 'Expected a resource. Got: %s',
387 4
                static::typeToString($value)
388
            ));
389
        }
390
391 12
        if ($type && $type !== \get_resource_type($value)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $type of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
392 4
            static::reportInvalidArgument(\sprintf(
393 4
                $message ?: 'Expected a resource of type %2$s. Got: %s',
394 4
                static::typeToString($value),
395 4
                $type
396
            ));
397
        }
398 8
    }
399
400
    /**
401
     * @psalm-assert callable $value
402
     *
403
     * @param mixed  $value
404
     * @param string $message
405
     *
406
     * @throws InvalidArgumentException
407
     */
408 20
    public static function isCallable($value, $message = '')
409
    {
410 20
        if (!\is_callable($value)) {
411 8
            static::reportInvalidArgument(\sprintf(
412 8
                $message ?: 'Expected a callable. Got: %s',
413 8
                static::typeToString($value)
414
            ));
415
        }
416 12
    }
417
418
    /**
419
     * @psalm-assert array $value
420
     *
421
     * @param mixed  $value
422
     * @param string $message
423
     *
424
     * @throws InvalidArgumentException
425
     */
426 20
    public static function isArray($value, $message = '')
427
    {
428 20
        if (!\is_array($value)) {
429 12
            static::reportInvalidArgument(\sprintf(
430 12
                $message ?: 'Expected an array. Got: %s',
431 12
                static::typeToString($value)
432
            ));
433
        }
434 8
    }
435
436
    /**
437
     * @psalm-assert iterable $value
438
     *
439
     * @deprecated use "isIterable" or "isInstanceOf" instead
440
     *
441
     * @param mixed  $value
442
     * @param string $message
443
     *
444
     * @throws InvalidArgumentException
445
     */
446 20
    public static function isTraversable($value, $message = '')
447
    {
448 20
        @\trigger_error(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
449 20
            \sprintf(
450 20
                'The "%s" assertion is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "isIterable" or "isInstanceOf" instead.',
451 20
                __METHOD__
452
            ),
453 20
            \E_USER_DEPRECATED
454
        );
455
456 20
        if (!\is_array($value) && !($value instanceof Traversable)) {
457 8
            static::reportInvalidArgument(\sprintf(
458 8
                $message ?: 'Expected a traversable. Got: %s',
459 8
                static::typeToString($value)
460
            ));
461
        }
462 12
    }
463
464
    /**
465
     * @param mixed  $value
466
     * @param string $message
467
     *
468
     * @throws InvalidArgumentException
469
     */
470 20 View Code Duplication
    public static function isArrayAccessible($value, $message = '')
471
    {
472 20
        if (!\is_array($value) && !($value instanceof ArrayAccess)) {
473 8
            static::reportInvalidArgument(\sprintf(
474 8
                $message ?: 'Expected an array accessible. Got: %s',
475 8
                static::typeToString($value)
476
            ));
477
        }
478 12
    }
479
480
    /**
481
     * @psalm-assert countable $value
482
     *
483
     * @param mixed  $value
484
     * @param string $message
485
     *
486
     * @throws InvalidArgumentException
487
     */
488 28
    public static function isCountable($value, $message = '')
489
    {
490
        if (
491 28
            !\is_array($value)
492 28
            && !($value instanceof Countable)
493 28
            && !($value instanceof ResourceBundle)
0 ignored issues
show
Bug introduced by
The class ResourceBundle does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
494 28
            && !($value instanceof SimpleXMLElement)
495
        ) {
496 12
            static::reportInvalidArgument(\sprintf(
497 12
                $message ?: 'Expected a countable. Got: %s',
498 12
                static::typeToString($value)
499
            ));
500
        }
501 16
    }
502
503
    /**
504
     * @psalm-assert iterable $value
505
     *
506
     * @param mixed  $value
507
     * @param string $message
508
     *
509
     * @throws InvalidArgumentException
510
     */
511 922 View Code Duplication
    public static function isIterable($value, $message = '')
512
    {
513 922
        if (!\is_array($value) && !($value instanceof Traversable)) {
514 8
            static::reportInvalidArgument(\sprintf(
515 8
                $message ?: 'Expected an iterable. Got: %s',
516 8
                static::typeToString($value)
517
            ));
518
        }
519 918
    }
520
521
    /**
522
     * @psalm-template ExpectedType of object
523
     * @psalm-param class-string<ExpectedType> $class
524
     * @psalm-assert ExpectedType $value
525
     *
526
     * @param mixed         $value
527
     * @param string|object $class
528
     * @param string        $message
529
     *
530
     * @throws InvalidArgumentException
531
     */
532 19
    public static function isInstanceOf($value, $class, $message = '')
533
    {
534 19
        if (!($value instanceof $class)) {
535 15
            static::reportInvalidArgument(\sprintf(
536 15
                $message ?: 'Expected an instance of %2$s. Got: %s',
537 15
                static::typeToString($value),
538 15
                $class
539
            ));
540
        }
541 4
    }
542
543
    /**
544
     * @psalm-template ExpectedType of object
545
     * @psalm-param class-string<ExpectedType> $class
546
     * @psalm-assert !ExpectedType $value
547
     *
548
     * @param mixed         $value
549
     * @param string|object $class
550
     * @param string        $message
551
     *
552
     * @throws InvalidArgumentException
553
     */
554 16
    public static function notInstanceOf($value, $class, $message = '')
555
    {
556 16
        if ($value instanceof $class) {
557 4
            static::reportInvalidArgument(\sprintf(
558 4
                $message ?: 'Expected an instance other than %2$s. Got: %s',
559 4
                static::typeToString($value),
560 4
                $class
561
            ));
562
        }
563 12
    }
564
565
    /**
566
     * @param mixed                $value
567
     * @param array<object|string> $classes
568
     * @param string               $message
569
     *
570
     * @throws InvalidArgumentException
571
     */
572 20
    public static function isInstanceOfAny($value, array $classes, $message = '')
573
    {
574 20
        foreach ($classes as $class) {
575 20
            if ($value instanceof $class) {
576 8
                return;
577
            }
578
        }
579
580 12
        static::reportInvalidArgument(\sprintf(
581 12
            $message ?: 'Expected an instance of any of %2$s. Got: %s',
582 12
            static::typeToString($value),
583 12
            \implode(', ', \array_map(array('static', 'valueToString'), $classes))
584
        ));
585
    }
586
587
    /**
588
     * @psalm-assert empty $value
589
     *
590
     * @param mixed  $value
591
     * @param string $message
592
     *
593
     * @throws InvalidArgumentException
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
     * @throws InvalidArgumentException
612
     */
613 23
    public static function notEmpty($value, $message = '')
614
    {
615 23
        if (empty($value)) {
616 15
            static::reportInvalidArgument(\sprintf(
617 15
                $message ?: 'Expected a non-empty value. Got: %s',
618 15
                static::valueToString($value)
619
            ));
620
        }
621 8
    }
622
623
    /**
624
     * @psalm-assert null $value
625
     *
626
     * @param mixed  $value
627
     * @param string $message
628
     *
629
     * @throws InvalidArgumentException
630
     */
631 11
    public static function null($value, $message = '')
632
    {
633 11
        if (null !== $value) {
634 8
            static::reportInvalidArgument(\sprintf(
635 8
                $message ?: 'Expected null. Got: %s',
636 8
                static::valueToString($value)
637
            ));
638
        }
639 3
    }
640
641
    /**
642
     * @psalm-assert !null $value
643
     *
644
     * @param mixed  $value
645
     * @param string $message
646
     *
647
     * @throws InvalidArgumentException
648
     */
649 11
    public static function notNull($value, $message = '')
650
    {
651 11
        if (null === $value) {
652 3
            static::reportInvalidArgument(
653 3
                $message ?: 'Expected a value other than null.'
654
            );
655
        }
656 8
    }
657
658
    /**
659
     * @psalm-assert true $value
660
     *
661
     * @param mixed  $value
662
     * @param string $message
663
     *
664
     * @throws InvalidArgumentException
665
     */
666 15
    public static function true($value, $message = '')
667
    {
668 15
        if (true !== $value) {
669 11
            static::reportInvalidArgument(\sprintf(
670 11
                $message ?: 'Expected a value to be true. Got: %s',
671 11
                static::valueToString($value)
672
            ));
673
        }
674 4
    }
675
676
    /**
677
     * @psalm-assert false $value
678
     *
679
     * @param mixed  $value
680
     * @param string $message
681
     *
682
     * @throws InvalidArgumentException
683
     */
684 19
    public static function false($value, $message = '')
685
    {
686 19
        if (false !== $value) {
687 15
            static::reportInvalidArgument(\sprintf(
688 15
                $message ?: 'Expected a value to be false. Got: %s',
689 15
                static::valueToString($value)
690
            ));
691
        }
692 4
    }
693
694
    /**
695
     * @param mixed  $value
696
     * @param string $message
697
     *
698
     * @throws InvalidArgumentException
699
     */
700 51 View Code Duplication
    public static function ip($value, $message = '')
701
    {
702 51
        if (false === \filter_var($value, \FILTER_VALIDATE_IP)) {
703 19
            static::reportInvalidArgument(\sprintf(
704 19
                $message ?: 'Expected a value to be an IP. Got: %s',
705 19
                static::valueToString($value)
706
            ));
707
        }
708 32
    }
709
710
    /**
711
     * @param mixed  $value
712
     * @param string $message
713
     *
714
     * @throws InvalidArgumentException
715
     */
716 51
    public static function ipv4($value, $message = '')
717
    {
718 51
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
719 35
            static::reportInvalidArgument(\sprintf(
720 35
                $message ?: 'Expected a value to be an IPv4. Got: %s',
721 35
                static::valueToString($value)
722
            ));
723
        }
724 16
    }
725
726
    /**
727
     * @param mixed  $value
728
     * @param string $message
729
     *
730
     * @throws InvalidArgumentException
731
     */
732 51
    public static function ipv6($value, $message = '')
733
    {
734 51
        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
735 31
            static::reportInvalidArgument(\sprintf(
736 31
                $message ?: 'Expected a value to be an IPv6. Got %s',
737 31
                static::valueToString($value)
738
            ));
739
        }
740 20
    }
741
742
    /**
743
     * @param mixed  $value
744
     * @param string $message
745
     *
746
     * @throws InvalidArgumentException
747
     */
748 20 View Code Duplication
    public static function email($value, $message = '')
749
    {
750 20
        if (false === \filter_var($value, FILTER_VALIDATE_EMAIL)) {
751 12
            static::reportInvalidArgument(\sprintf(
752 12
                $message ?: 'Expected a value to be a valid e-mail address. Got %s',
753 12
                static::valueToString($value)
754
            ));
755
        }
756 8
    }
757
758
    /**
759
     * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion.
760
     *
761
     * @param array  $values
762
     * @param string $message
763
     *
764
     * @throws InvalidArgumentException
765
     */
766 12
    public static function uniqueValues(array $values, $message = '')
767
    {
768 12
        $allValues = \count($values);
769 12
        $uniqueValues = \count(\array_unique($values));
770
771 12
        if ($allValues !== $uniqueValues) {
772 8
            $difference = $allValues - $uniqueValues;
773
774 8
            static::reportInvalidArgument(\sprintf(
775 8
                $message ?: 'Expected an array of unique values, but %s of them %s duplicated',
776 8
                $difference,
777 8
                (1 === $difference ? 'is' : 'are')
778
            ));
779
        }
780 4
    }
781
782
    /**
783
     * @param mixed  $value
784
     * @param mixed  $expect
785
     * @param string $message
786
     *
787
     * @throws InvalidArgumentException
788
     */
789 33
    public static function eq($value, $expect, $message = '')
790
    {
791 33
        if ($expect != $value) {
792 17
            static::reportInvalidArgument(\sprintf(
793 17
                $message ?: 'Expected a value equal to %2$s. Got: %s',
794 17
                static::valueToString($value),
795 17
                static::valueToString($expect)
796
            ));
797
        }
798 16
    }
799
800
    /**
801
     * @param mixed  $value
802
     * @param mixed  $expect
803
     * @param string $message
804
     *
805
     * @throws InvalidArgumentException
806
     */
807 28
    public static function notEq($value, $expect, $message = '')
808
    {
809 28
        if ($expect == $value) {
810 16
            static::reportInvalidArgument(\sprintf(
811 16
                $message ?: 'Expected a different value than %s.',
812 16
                static::valueToString($expect)
813
            ));
814
        }
815 12
    }
816
817
    /**
818
     * @param mixed  $value
819
     * @param mixed  $expect
820
     * @param string $message
821
     *
822
     * @throws InvalidArgumentException
823
     */
824 16
    public static function same($value, $expect, $message = '')
825
    {
826 16
        if ($expect !== $value) {
827 12
            static::reportInvalidArgument(\sprintf(
828 12
                $message ?: 'Expected a value identical to %2$s. Got: %s',
829 12
                static::valueToString($value),
830 12
                static::valueToString($expect)
831
            ));
832
        }
833 4
    }
834
835
    /**
836
     * @param mixed  $value
837
     * @param mixed  $expect
838
     * @param string $message
839
     *
840
     * @throws InvalidArgumentException
841
     */
842 16
    public static function notSame($value, $expect, $message = '')
843
    {
844 16
        if ($expect === $value) {
845 4
            static::reportInvalidArgument(\sprintf(
846 4
                $message ?: 'Expected a value not identical to %s.',
847 4
                static::valueToString($expect)
848
            ));
849
        }
850 12
    }
851
852
    /**
853
     * @param mixed  $value
854
     * @param mixed  $limit
855
     * @param string $message
856
     *
857
     * @throws InvalidArgumentException
858
     */
859 8
    public static function greaterThan($value, $limit, $message = '')
860
    {
861 8
        if ($value <= $limit) {
862 4
            static::reportInvalidArgument(\sprintf(
863 4
                $message ?: 'Expected a value greater than %2$s. Got: %s',
864 4
                static::valueToString($value),
865 4
                static::valueToString($limit)
866
            ));
867
        }
868 4
    }
869
870
    /**
871
     * @param mixed  $value
872
     * @param mixed  $limit
873
     * @param string $message
874
     *
875
     * @throws InvalidArgumentException
876
     */
877 12
    public static function greaterThanEq($value, $limit, $message = '')
878
    {
879 12
        if ($value < $limit) {
880 4
            static::reportInvalidArgument(\sprintf(
881 4
                $message ?: 'Expected a value greater than or equal to %2$s. Got: %s',
882 4
                static::valueToString($value),
883 4
                static::valueToString($limit)
884
            ));
885
        }
886 8
    }
887
888
    /**
889
     * @param mixed  $value
890
     * @param mixed  $limit
891
     * @param string $message
892
     *
893
     * @throws InvalidArgumentException
894
     */
895 8
    public static function lessThan($value, $limit, $message = '')
896
    {
897 8
        if ($value >= $limit) {
898 4
            static::reportInvalidArgument(\sprintf(
899 4
                $message ?: 'Expected a value less than %2$s. Got: %s',
900 4
                static::valueToString($value),
901 4
                static::valueToString($limit)
902
            ));
903
        }
904 4
    }
905
906
    /**
907
     * @param mixed  $value
908
     * @param mixed  $limit
909
     * @param string $message
910
     *
911
     * @throws InvalidArgumentException
912
     */
913 12
    public static function lessThanEq($value, $limit, $message = '')
914
    {
915 12
        if ($value > $limit) {
916 4
            static::reportInvalidArgument(\sprintf(
917 4
                $message ?: 'Expected a value less than or equal to %2$s. Got: %s',
918 4
                static::valueToString($value),
919 4
                static::valueToString($limit)
920
            ));
921
        }
922 8
    }
923
924
    /**
925
     * Inclusive range, so Assert::(3, 3, 5) passes.
926
     *
927
     * @param mixed  $value
928
     * @param mixed  $min
929
     * @param mixed  $max
930
     * @param string $message
931
     *
932
     * @throws InvalidArgumentException
933
     */
934 16 View Code Duplication
    public static function range($value, $min, $max, $message = '')
935
    {
936 16
        if ($value < $min || $value > $max) {
937 8
            static::reportInvalidArgument(\sprintf(
938 8
                $message ?: 'Expected a value between %2$s and %3$s. Got: %s',
939 8
                static::valueToString($value),
940 8
                static::valueToString($min),
941 8
                static::valueToString($max)
942
            ));
943
        }
944 8
    }
945
946
    /**
947
     * Does strict comparison, so Assert::oneOf(3, ['3']) does not pass the assertion.
948
     *
949
     * @param mixed  $value
950
     * @param array  $values
951
     * @param string $message
952
     *
953
     * @throws InvalidArgumentException
954
     */
955 8
    public static function oneOf($value, array $values, $message = '')
956
    {
957 8
        if (!\in_array($value, $values, true)) {
958 4
            static::reportInvalidArgument(\sprintf(
959 4
                $message ?: 'Expected one of: %2$s. Got: %s',
960 4
                static::valueToString($value),
961 4
                \implode(', ', \array_map(array('static', 'valueToString'), $values))
962
            ));
963
        }
964 4
    }
965
966
    /**
967
     * @param mixed  $value
968
     * @param string $subString
969
     * @param string $message
970
     *
971
     * @throws InvalidArgumentException
972
     */
973 80 View Code Duplication
    public static function contains($value, $subString, $message = '')
974
    {
975 80
        if (false === \strpos($value, $subString)) {
976 32
            static::reportInvalidArgument(\sprintf(
977 32
                $message ?: 'Expected a value to contain %2$s. Got: %s',
978 32
                static::valueToString($value),
979 32
                static::valueToString($subString)
980
            ));
981
        }
982 48
    }
983
984
    /**
985
     * @param mixed  $value
986
     * @param string $subString
987
     * @param string $message
988
     *
989
     * @throws InvalidArgumentException
990
     */
991 80 View Code Duplication
    public static function notContains($value, $subString, $message = '')
992
    {
993 80
        if (false !== \strpos($value, $subString)) {
994 48
            static::reportInvalidArgument(\sprintf(
995 48
                $message ?: '%2$s was not expected to be contained in a value. Got: %s',
996 48
                static::valueToString($value),
997 48
                static::valueToString($subString)
998
            ));
999
        }
1000 32
    }
1001
1002
    /**
1003
     * @param mixed  $value
1004
     * @param string $message
1005
     *
1006
     * @throws InvalidArgumentException
1007
     */
1008 40
    public static function notWhitespaceOnly($value, $message = '')
1009
    {
1010 40
        if (\preg_match('/^\s*$/', $value)) {
1011 24
            static::reportInvalidArgument(\sprintf(
1012 24
                $message ?: 'Expected a non-whitespace string. Got: %s',
1013 24
                static::valueToString($value)
1014
            ));
1015
        }
1016 16
    }
1017
1018
    /**
1019
     * @param mixed  $value
1020
     * @param string $prefix
1021
     * @param string $message
1022
     *
1023
     * @throws InvalidArgumentException
1024
     */
1025 48 View Code Duplication
    public static function startsWith($value, $prefix, $message = '')
1026
    {
1027 48
        if (0 !== \strpos($value, $prefix)) {
1028 32
            static::reportInvalidArgument(\sprintf(
1029 32
                $message ?: 'Expected a value to start with %2$s. Got: %s',
1030 32
                static::valueToString($value),
1031 32
                static::valueToString($prefix)
1032
            ));
1033
        }
1034 16
    }
1035
1036
    /**
1037
     * @param mixed  $value
1038
     * @param string $message
1039
     *
1040
     * @throws InvalidArgumentException
1041
     */
1042 35
    public static function startsWithLetter($value, $message = '')
1043
    {
1044 35
        static::string($value);
1045
1046 24
        $valid = isset($value[0]);
1047
1048 24
        if ($valid) {
1049 20
            $locale = \setlocale(LC_CTYPE, 0);
1050 20
            \setlocale(LC_CTYPE, 'C');
1051 20
            $valid = \ctype_alpha($value[0]);
1052 20
            \setlocale(LC_CTYPE, $locale);
1053
        }
1054
1055 24
        if (!$valid) {
1056 12
            static::reportInvalidArgument(\sprintf(
1057 12
                $message ?: 'Expected a value to start with a letter. Got: %s',
1058 12
                static::valueToString($value)
1059
            ));
1060
        }
1061 12
    }
1062
1063
    /**
1064
     * @param mixed  $value
1065
     * @param string $suffix
1066
     * @param string $message
1067
     *
1068
     * @throws InvalidArgumentException
1069
     */
1070 48 View Code Duplication
    public static function endsWith($value, $suffix, $message = '')
1071
    {
1072 48
        if ($suffix !== \substr($value, -\strlen($suffix))) {
1073 32
            static::reportInvalidArgument(\sprintf(
1074 32
                $message ?: 'Expected a value to end with %2$s. Got: %s',
1075 32
                static::valueToString($value),
1076 32
                static::valueToString($suffix)
1077
            ));
1078
        }
1079 16
    }
1080
1081
    /**
1082
     * @param mixed  $value
1083
     * @param mixed  $pattern
1084
     * @param string $message
1085
     *
1086
     * @throws InvalidArgumentException
1087
     */
1088 12
    public static function regex($value, $pattern, $message = '')
1089
    {
1090 12
        if (!\preg_match($pattern, $value)) {
1091 8
            static::reportInvalidArgument(\sprintf(
1092 8
                $message ?: 'The value %s does not match the expected pattern.',
1093 8
                static::valueToString($value)
1094
            ));
1095
        }
1096 4
    }
1097
1098
    /**
1099
     * @param mixed  $value
1100
     * @param mixed  $pattern
1101
     * @param string $message
1102
     *
1103
     * @throws InvalidArgumentException
1104
     */
1105 12
    public static function notRegex($value, $pattern, $message = '')
1106
    {
1107 12
        if (\preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) {
1108 4
            static::reportInvalidArgument(\sprintf(
1109 4
                $message ?: 'The value %s matches the pattern %s (at offset %d).',
1110 4
                static::valueToString($value),
1111 4
                static::valueToString($pattern),
1112 4
                $matches[0][1]
1113
            ));
1114
        }
1115 8
    }
1116
1117
    /**
1118
     * @param mixed  $value
1119
     * @param string $message
1120
     *
1121
     * @throws InvalidArgumentException
1122
     */
1123 28 View Code Duplication
    public static function unicodeLetters($value, $message = '')
1124
    {
1125 28
        static::string($value);
1126
1127 28
        if (!\preg_match('/^\p{L}+$/u', $value)) {
1128 16
            static::reportInvalidArgument(\sprintf(
1129 16
                $message ?: 'Expected a value to contain only Unicode letters. Got: %s',
1130 16
                static::valueToString($value)
1131
            ));
1132
        }
1133 12
    }
1134
1135
    /**
1136
     * @param mixed  $value
1137
     * @param string $message
1138
     *
1139
     * @throws InvalidArgumentException
1140
     */
1141 20 View Code Duplication
    public static function alpha($value, $message = '')
1142
    {
1143 20
        static::string($value);
1144
1145 12
        $locale = \setlocale(LC_CTYPE, 0);
1146 12
        \setlocale(LC_CTYPE, 'C');
1147 12
        $valid = !\ctype_alpha($value);
1148 12
        \setlocale(LC_CTYPE, $locale);
1149
1150 12
        if ($valid) {
1151 8
            static::reportInvalidArgument(\sprintf(
1152 8
                $message ?: 'Expected a value to contain only letters. Got: %s',
1153 8
                static::valueToString($value)
1154
            ));
1155
        }
1156 4
    }
1157
1158
    /**
1159
     * @param mixed  $value
1160
     * @param string $message
1161
     *
1162
     * @throws InvalidArgumentException
1163
     */
1164 12 View Code Duplication
    public static function digits($value, $message = '')
1165
    {
1166 12
        $locale = \setlocale(LC_CTYPE, 0);
1167 12
        \setlocale(LC_CTYPE, 'C');
1168 12
        $valid = !\ctype_digit($value);
1169 12
        \setlocale(LC_CTYPE, $locale);
1170
1171 12
        if ($valid) {
1172 8
            static::reportInvalidArgument(\sprintf(
1173 8
                $message ?: 'Expected a value to contain digits only. Got: %s',
1174 8
                static::valueToString($value)
1175
            ));
1176
        }
1177 4
    }
1178
1179
    /**
1180
     * @param mixed  $value
1181
     * @param string $message
1182
     *
1183
     * @throws InvalidArgumentException
1184
     */
1185 12 View Code Duplication
    public static function alnum($value, $message = '')
1186
    {
1187 12
        $locale = \setlocale(LC_CTYPE, 0);
1188 12
        \setlocale(LC_CTYPE, 'C');
1189 12
        $valid = !\ctype_alnum($value);
1190 12
        \setlocale(LC_CTYPE, $locale);
1191
1192 12
        if ($valid) {
1193 8
            static::reportInvalidArgument(\sprintf(
1194 8
                $message ?: 'Expected a value to contain letters and digits only. Got: %s',
1195 8
                static::valueToString($value)
1196
            ));
1197
        }
1198 4
    }
1199
1200
    /**
1201
     * @param mixed  $value
1202
     * @param string $message
1203
     *
1204
     * @throws InvalidArgumentException
1205
     */
1206 16 View Code Duplication
    public static function lower($value, $message = '')
1207
    {
1208 16
        $locale = \setlocale(LC_CTYPE, 0);
1209 16
        \setlocale(LC_CTYPE, 'C');
1210 16
        $valid = !\ctype_lower($value);
1211 16
        \setlocale(LC_CTYPE, $locale);
1212
1213 16
        if ($valid) {
1214 12
            static::reportInvalidArgument(\sprintf(
1215 12
                $message ?: 'Expected a value to contain lowercase characters only. Got: %s',
1216 12
                static::valueToString($value)
1217
            ));
1218
        }
1219 4
    }
1220
1221
    /**
1222
     * @param mixed  $value
1223
     * @param string $message
1224
     *
1225
     * @throws InvalidArgumentException
1226
     */
1227 16 View Code Duplication
    public static function upper($value, $message = '')
1228
    {
1229 16
        $locale = \setlocale(LC_CTYPE, 0);
1230 16
        \setlocale(LC_CTYPE, 'C');
1231 16
        $valid = !\ctype_upper($value);
1232 16
        \setlocale(LC_CTYPE, $locale);
1233
1234 16
        if ($valid) {
1235 12
            static::reportInvalidArgument(\sprintf(
1236 12
                $message ?: 'Expected a value to contain uppercase characters only. Got: %s',
1237 12
                static::valueToString($value)
1238
            ));
1239
        }
1240 4
    }
1241
1242
    /**
1243
     * @param mixed  $value
1244
     * @param mixed  $length
1245
     * @param string $message
1246
     *
1247
     * @throws InvalidArgumentException
1248
     */
1249 36
    public static function length($value, $length, $message = '')
1250
    {
1251 36
        if ($length !== static::strlen($value)) {
1252 24
            static::reportInvalidArgument(\sprintf(
1253 24
                $message ?: 'Expected a value to contain %2$s characters. Got: %s',
1254 24
                static::valueToString($value),
1255 24
                $length
1256
            ));
1257
        }
1258 12
    }
1259
1260
    /**
1261
     * Inclusive min.
1262
     *
1263
     * @param mixed  $value
1264
     * @param mixed  $min
1265
     * @param string $message
1266
     *
1267
     * @throws InvalidArgumentException
1268
     */
1269 36
    public static function minLength($value, $min, $message = '')
1270
    {
1271 36
        if (static::strlen($value) < $min) {
1272 12
            static::reportInvalidArgument(\sprintf(
1273 12
                $message ?: 'Expected a value to contain at least %2$s characters. Got: %s',
1274 12
                static::valueToString($value),
1275 12
                $min
1276
            ));
1277
        }
1278 24
    }
1279
1280
    /**
1281
     * Inclusive max.
1282
     *
1283
     * @param mixed  $value
1284
     * @param mixed  $max
1285
     * @param string $message
1286
     *
1287
     * @throws InvalidArgumentException
1288
     */
1289 36
    public static function maxLength($value, $max, $message = '')
1290
    {
1291 36
        if (static::strlen($value) > $max) {
1292 12
            static::reportInvalidArgument(\sprintf(
1293 12
                $message ?: 'Expected a value to contain at most %2$s characters. Got: %s',
1294 12
                static::valueToString($value),
1295 12
                $max
1296
            ));
1297
        }
1298 24
    }
1299
1300
    /**
1301
     * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion.
1302
     *
1303
     * @param mixed  $value
1304
     * @param mixed  $min
1305
     * @param mixed  $max
1306
     * @param string $message
1307
     *
1308
     * @throws InvalidArgumentException
1309
     */
1310 60 View Code Duplication
    public static function lengthBetween($value, $min, $max, $message = '')
1311
    {
1312 60
        $length = static::strlen($value);
1313
1314 60
        if ($length < $min || $length > $max) {
1315 24
            static::reportInvalidArgument(\sprintf(
1316 24
                $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s',
1317 24
                static::valueToString($value),
1318 24
                $min,
1319 24
                $max
1320
            ));
1321
        }
1322 36
    }
1323
1324
    /**
1325
     * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file.
1326
     *
1327
     * @param mixed  $value
1328
     * @param string $message
1329
     *
1330
     * @throws InvalidArgumentException
1331
     */
1332 36 View Code Duplication
    public static function fileExists($value, $message = '')
1333
    {
1334 36
        static::string($value);
1335
1336 36
        if (!\file_exists($value)) {
1337 12
            static::reportInvalidArgument(\sprintf(
1338 12
                $message ?: 'The file %s does not exist.',
1339 12
                static::valueToString($value)
1340
            ));
1341
        }
1342 24
    }
1343
1344
    /**
1345
     * @param mixed  $value
1346
     * @param string $message
1347
     *
1348
     * @throws InvalidArgumentException
1349
     */
1350 12 View Code Duplication
    public static function file($value, $message = '')
1351
    {
1352 12
        static::fileExists($value, $message);
1353
1354 8
        if (!\is_file($value)) {
1355 4
            static::reportInvalidArgument(\sprintf(
1356 4
                $message ?: 'The path %s is not a file.',
1357 4
                static::valueToString($value)
1358
            ));
1359
        }
1360 4
    }
1361
1362
    /**
1363
     * @param mixed  $value
1364
     * @param string $message
1365
     *
1366
     * @throws InvalidArgumentException
1367
     */
1368 12 View Code Duplication
    public static function directory($value, $message = '')
1369
    {
1370 12
        static::fileExists($value, $message);
1371
1372 8
        if (!\is_dir($value)) {
1373 4
            static::reportInvalidArgument(\sprintf(
1374 4
                $message ?: 'The path %s is no directory.',
1375 4
                static::valueToString($value)
1376
            ));
1377
        }
1378 4
    }
1379
1380
    /**
1381
     * @param mixed  $value
1382
     * @param string $message
1383
     *
1384
     * @throws InvalidArgumentException
1385
     */
1386
    public static function readable($value, $message = '')
1387
    {
1388
        if (!\is_readable($value)) {
1389
            static::reportInvalidArgument(\sprintf(
1390
                $message ?: 'The path %s is not readable.',
1391
                static::valueToString($value)
1392
            ));
1393
        }
1394
    }
1395
1396
    /**
1397
     * @param mixed  $value
1398
     * @param string $message
1399
     *
1400
     * @throws InvalidArgumentException
1401
     */
1402
    public static function writable($value, $message = '')
1403
    {
1404
        if (!\is_writable($value)) {
1405
            static::reportInvalidArgument(\sprintf(
1406
                $message ?: 'The path %s is not writable.',
1407
                static::valueToString($value)
1408
            ));
1409
        }
1410
    }
1411
1412
    /**
1413
     * @psalm-assert class-string $value
1414
     *
1415
     * @param mixed  $value
1416
     * @param string $message
1417
     *
1418
     * @throws InvalidArgumentException
1419
     */
1420 8
    public static function classExists($value, $message = '')
1421
    {
1422 8
        if (!\class_exists($value)) {
1423 4
            static::reportInvalidArgument(\sprintf(
1424 4
                $message ?: 'Expected an existing class name. Got: %s',
1425 4
                static::valueToString($value)
1426
            ));
1427
        }
1428 4
    }
1429
1430
    /**
1431
     * @param mixed         $value
1432
     * @param string|object $class
1433
     * @param string        $message
1434
     *
1435
     * @throws InvalidArgumentException
1436
     */
1437 8
    public static function subclassOf($value, $class, $message = '')
1438
    {
1439 8
        if (!\is_subclass_of($value, $class)) {
1440 4
            static::reportInvalidArgument(\sprintf(
1441 4
                $message ?: 'Expected a sub-class of %2$s. Got: %s',
1442 4
                static::valueToString($value),
1443 4
                static::valueToString($class)
1444
            ));
1445
        }
1446 4
    }
1447
1448
    /**
1449
     * @psalm-assert class-string $value
1450
     *
1451
     * @param mixed  $value
1452
     * @param string $message
1453
     *
1454
     * @throws InvalidArgumentException
1455
     */
1456 8
    public static function interfaceExists($value, $message = '')
1457
    {
1458 8
        if (!\interface_exists($value)) {
1459 4
            static::reportInvalidArgument(\sprintf(
1460 4
                $message ?: 'Expected an existing interface name. got %s',
1461 4
                static::valueToString($value)
1462
            ));
1463
        }
1464 4
    }
1465
1466
    /**
1467
     * @param mixed  $value
1468
     * @param mixed  $interface
1469
     * @param string $message
1470
     *
1471
     * @throws InvalidArgumentException
1472
     */
1473 8 View Code Duplication
    public static function implementsInterface($value, $interface, $message = '')
1474
    {
1475 8
        if (!\in_array($interface, \class_implements($value))) {
1476 4
            static::reportInvalidArgument(\sprintf(
1477 4
                $message ?: 'Expected an implementation of %2$s. Got: %s',
1478 4
                static::valueToString($value),
1479 4
                static::valueToString($interface)
1480
            ));
1481
        }
1482 4
    }
1483
1484
    /**
1485
     * @param string|object $classOrObject
1486
     * @param mixed         $property
1487
     * @param string        $message
1488
     *
1489
     * @throws InvalidArgumentException
1490
     */
1491 12 View Code Duplication
    public static function propertyExists($classOrObject, $property, $message = '')
1492
    {
1493 12
        if (!\property_exists($classOrObject, $property)) {
1494 4
            static::reportInvalidArgument(\sprintf(
1495 4
                $message ?: 'Expected the property %s to exist.',
1496 4
                static::valueToString($property)
1497
            ));
1498
        }
1499 8
    }
1500
1501
    /**
1502
     * @param string|object $classOrObject
1503
     * @param mixed         $property
1504
     * @param string        $message
1505
     *
1506
     * @throws InvalidArgumentException
1507
     */
1508 12 View Code Duplication
    public static function propertyNotExists($classOrObject, $property, $message = '')
1509
    {
1510 12
        if (\property_exists($classOrObject, $property)) {
1511 8
            static::reportInvalidArgument(\sprintf(
1512 8
                $message ?: 'Expected the property %s to not exist.',
1513 8
                static::valueToString($property)
1514
            ));
1515
        }
1516 4
    }
1517
1518
    /**
1519
     * @param string|object $classOrObject
1520
     * @param mixed         $method
1521
     * @param string        $message
1522
     *
1523
     * @throws InvalidArgumentException
1524
     */
1525 27 View Code Duplication
    public static function methodExists($classOrObject, $method, $message = '')
1526
    {
1527 27
        if (!\method_exists($classOrObject, $method)) {
1528 19
            static::reportInvalidArgument(\sprintf(
1529 19
                $message ?: 'Expected the method %s to exist.',
1530 19
                static::valueToString($method)
1531
            ));
1532
        }
1533 8
    }
1534
1535
    /**
1536
     * @param string|object $classOrObject
1537
     * @param mixed         $method
1538
     * @param string        $message
1539
     *
1540
     * @throws InvalidArgumentException
1541
     */
1542 27 View Code Duplication
    public static function methodNotExists($classOrObject, $method, $message = '')
1543
    {
1544 27
        if (\method_exists($classOrObject, $method)) {
1545 8
            static::reportInvalidArgument(\sprintf(
1546 8
                $message ?: 'Expected the method %s to not exist.',
1547 8
                static::valueToString($method)
1548
            ));
1549
        }
1550 19
    }
1551
1552
    /**
1553
     * @param array      $array
1554
     * @param string|int $key
1555
     * @param string     $message
1556
     *
1557
     * @throws InvalidArgumentException
1558
     */
1559 12 View Code Duplication
    public static function keyExists($array, $key, $message = '')
1560
    {
1561 12
        if (!(isset($array[$key]) || \array_key_exists($key, $array))) {
1562 4
            static::reportInvalidArgument(\sprintf(
1563 4
                $message ?: 'Expected the key %s to exist.',
1564 4
                static::valueToString($key)
1565
            ));
1566
        }
1567 8
    }
1568
1569
    /**
1570
     * @param array      $array
1571
     * @param string|int $key
1572
     * @param string     $message
1573
     *
1574
     * @throws InvalidArgumentException
1575
     */
1576 12 View Code Duplication
    public static function keyNotExists($array, $key, $message = '')
1577
    {
1578 12
        if (isset($array[$key]) || \array_key_exists($key, $array)) {
1579 8
            static::reportInvalidArgument(\sprintf(
1580 8
                $message ?: 'Expected the key %s to not exist.',
1581 8
                static::valueToString($key)
1582
            ));
1583
        }
1584 4
    }
1585
1586
    /**
1587
     * Checks if a value is a valid array key (int or string).
1588
     *
1589
     * @psalm-assert array-key $value
1590
     *
1591
     * @param mixed  $value
1592
     * @param string $message
1593
     *
1594
     * @throws InvalidArgumentException
1595
     */
1596 28
    public static function validArrayKey($value, $message = '')
1597
    {
1598 28
        if (!(\is_int($value) || \is_string($value))) {
1599 20
            static::reportInvalidArgument(\sprintf(
1600 20
                $message ?: 'Expected string or integer. Got: %s',
1601 20
                static::typeToString($value)
1602
            ));
1603
        }
1604 8
    }
1605
1606
    /**
1607
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1608
     *
1609
     * @param mixed  $array
1610
     * @param mixed  $number
1611
     * @param string $message
1612
     *
1613
     * @throws InvalidArgumentException
1614
     */
1615 8
    public static function count($array, $number, $message = '')
1616
    {
1617 8
        static::eq(
1618 8
            \count($array),
1619
            $number,
1620 8
            $message ?: \sprintf('Expected an array to contain %d elements. Got: %d.', $number, \count($array))
1621
        );
1622 4
    }
1623
1624
    /**
1625
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1626
     *
1627
     * @param mixed  $array
1628
     * @param mixed  $min
1629
     * @param string $message
1630
     *
1631
     * @throws InvalidArgumentException
1632
     */
1633 12 View Code Duplication
    public static function minCount($array, $min, $message = '')
1634
    {
1635 12
        if (\count($array) < $min) {
1636 4
            static::reportInvalidArgument(\sprintf(
1637 4
                $message ?: 'Expected an array to contain at least %2$d elements. Got: %d',
1638 4
                \count($array),
1639 4
                $min
1640
            ));
1641
        }
1642 8
    }
1643
1644
    /**
1645
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1646
     *
1647
     * @param mixed  $array
1648
     * @param mixed  $max
1649
     * @param string $message
1650
     *
1651
     * @throws InvalidArgumentException
1652
     */
1653 12 View Code Duplication
    public static function maxCount($array, $max, $message = '')
1654
    {
1655 12
        if (\count($array) > $max) {
1656 4
            static::reportInvalidArgument(\sprintf(
1657 4
                $message ?: 'Expected an array to contain at most %2$d elements. Got: %d',
1658 4
                \count($array),
1659 4
                $max
1660
            ));
1661
        }
1662 8
    }
1663
1664
    /**
1665
     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
1666
     *
1667
     * @param mixed  $array
1668
     * @param mixed  $min
1669
     * @param mixed  $max
1670
     * @param string $message
1671
     *
1672
     * @throws InvalidArgumentException
1673
     */
1674 20
    public static function countBetween($array, $min, $max, $message = '')
1675
    {
1676 20
        $count = \count($array);
1677
1678 20
        if ($count < $min || $count > $max) {
1679 8
            static::reportInvalidArgument(\sprintf(
1680 8
                $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d',
1681 8
                $count,
1682 8
                $min,
1683 8
                $max
1684
            ));
1685
        }
1686 12
    }
1687
1688
    /**
1689
     * @psalm-assert list $array
1690
     *
1691
     * @param mixed  $array
1692
     * @param string $message
1693
     *
1694
     * @throws InvalidArgumentException
1695
     */
1696 40 View Code Duplication
    public static function isList($array, $message = '')
1697
    {
1698 40
        if (!\is_array($array) || $array !== \array_values($array)) {
1699 16
            static::reportInvalidArgument(
1700 16
                $message ?: 'Expected list - non-associative array.'
1701
            );
1702
        }
1703 24
    }
1704
1705
    /**
1706
     * @param mixed  $array
1707
     * @param string $message
1708
     *
1709
     * @throws InvalidArgumentException
1710
     */
1711 16
    public static function isMap($array, $message = '')
1712
    {
1713
        if (
1714 16
            !\is_array($array) ||
1715 16
            \array_keys($array) !== \array_filter(\array_keys($array), 'is_string')
1716
        ) {
1717 8
            static::reportInvalidArgument(
1718 8
                $message ?: 'Expected map - associative array with string keys.'
1719
            );
1720
        }
1721 8
    }
1722
1723
    /**
1724
     * @param mixed  $value
1725
     * @param string $message
1726
     *
1727
     * @throws InvalidArgumentException
1728
     */
1729 56
    public static function uuid($value, $message = '')
1730
    {
1731 56
        $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
1732
1733
        // The nil UUID is special form of UUID that is specified to have all
1734
        // 128 bits set to zero.
1735 56
        if ('00000000-0000-0000-0000-000000000000' === $value) {
1736 4
            return;
1737
        }
1738
1739 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)) {
1740 20
            static::reportInvalidArgument(\sprintf(
1741 20
                $message ?: 'Value %s is not a valid UUID.',
1742 20
                static::valueToString($value)
1743
            ));
1744
        }
1745 32
    }
1746
1747
    /**
1748
     * @param Closure       $expression
1749
     * @param string|object $class
1750
     * @param string        $message
1751
     *
1752
     * @throws InvalidArgumentException
1753
     */
1754 24
    public static function throws(Closure $expression, $class = 'Exception', $message = '')
1755
    {
1756 24
        static::string($class);
1757
1758 24
        $actual = 'none';
1759
1760
        try {
1761 24
            $expression();
1762 24
        } catch (Exception $e) {
1763 20
            $actual = \get_class($e);
1764 20
            if ($e instanceof $class) {
1765 20
                return;
1766
            }
1767 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...
1768 4
            $actual = \get_class($e);
1769 4
            if ($e instanceof $class) {
1770 4
                return;
1771
            }
1772
        }
1773
1774 8
        static::reportInvalidArgument($message ?: \sprintf(
1775 8
            'Expected to throw "%s", got "%s"',
1776 8
            $class,
1777 8
            $actual
1778
        ));
1779
    }
1780
1781
    /**
1782
     * @throws BadMethodCallException
1783
     */
1784 1450
    public static function __callStatic($name, $arguments)
1785
    {
1786 1450
        if ('nullOr' === \substr($name, 0, 6)) {
1787 537
            if (null !== $arguments[0]) {
1788 441
                $method = \lcfirst(\substr($name, 6));
1789 441
                \call_user_func_array(array('static', $method), $arguments);
1790
            }
1791
1792 312
            return;
1793
        }
1794
1795 913
        if ('all' === \substr($name, 0, 3)) {
1796 912
            static::isIterable($arguments[0]);
1797
1798 912
            $method = \lcfirst(\substr($name, 3));
1799 912
            $args = $arguments;
1800
1801 912
            foreach ($arguments[0] as $entry) {
1802 912
                $args[0] = $entry;
1803
1804 912
                \call_user_func_array(array('static', $method), $args);
1805
            }
1806
1807 438
            return;
1808
        }
1809
1810 1
        throw new BadMethodCallException('No such method: '.$name);
1811
    }
1812
1813
    /**
1814
     * @param mixed $value
1815
     *
1816
     * @return string
1817
     */
1818 694
    protected static function valueToString($value)
1819
    {
1820 694
        if (null === $value) {
1821 20
            return 'null';
1822
        }
1823
1824 676
        if (true === $value) {
1825 15
            return 'true';
1826
        }
1827
1828 666
        if (false === $value) {
1829 25
            return 'false';
1830
        }
1831
1832 641
        if (\is_array($value)) {
1833 13
            return 'array';
1834
        }
1835
1836 628
        if (\is_object($value)) {
1837 2
            if (\method_exists($value, '__toString')) {
1838 1
                return \get_class($value).': '.self::valueToString($value->__toString());
1839
            }
1840
1841 1
            return \get_class($value);
1842
        }
1843
1844 627
        if (\is_resource($value)) {
1845 1
            return 'resource';
1846
        }
1847
1848 627
        if (\is_string($value)) {
1849 525
            return '"'.$value.'"';
1850
        }
1851
1852 110
        return (string) $value;
1853
    }
1854
1855
    /**
1856
     * @param mixed $value
1857
     *
1858
     * @return string
1859
     */
1860 211
    protected static function typeToString($value)
1861
    {
1862 211
        return \is_object($value) ? \get_class($value) : \gettype($value);
1863
    }
1864
1865 168
    protected static function strlen($value)
1866
    {
1867 168
        if (!\function_exists('mb_detect_encoding')) {
1868
            return \strlen($value);
1869
        }
1870
1871 168
        if (false === $encoding = \mb_detect_encoding($value)) {
1872
            return \strlen($value);
1873
        }
1874
1875 168
        return \mb_strlen($value, $encoding);
1876
    }
1877
1878
    /**
1879
     * @param string $message
1880
     *
1881
     * @throws InvalidArgumentException
1882
     */
1883 952
    protected static function reportInvalidArgument($message)
1884
    {
1885 952
        throw new InvalidArgumentException($message);
1886
    }
1887
1888
    private function __construct()
1889
    {
1890
    }
1891
}
1892