Completed
Pull Request — master (#148)
by
unknown
02:57
created

Assertion::isCallable()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
eloc 6
c 1
b 0
f 1
nc 2
nop 3
dl 0
loc 11
rs 9.4285
1
<?php
2
/**
3
 * Assert
4
 *
5
 * LICENSE
6
 *
7
 * This source file is subject to the new BSD license that is bundled
8
 * with this package in the file LICENSE.txt.
9
 * If you did not receive a copy of the license and are unable to
10
 * obtain it through the world-wide-web, please send an email
11
 * to [email protected] so I can send you a copy immediately.
12
 */
13
14
namespace Assert;
15
16
use BadMethodCallException;
17
18
/**
19
 * Assert library
20
 *
21
 * @author Benjamin Eberlei <[email protected]>
22
 *
23
 * METHODSTART
24
 * @method static void nullOrEq($value, $value2, $message = null, $propertyPath = null)
25
 * @method static void nullOrSame($value, $value2, $message = null, $propertyPath = null)
26
 * @method static void nullOrNotEq($value1, $value2, $message = null, $propertyPath = null)
27
 * @method static void nullOrNotSame($value1, $value2, $message = null, $propertyPath = null)
28
 * @method static void nullOrInteger($value, $message = null, $propertyPath = null)
29
 * @method static void nullOrFloat($value, $message = null, $propertyPath = null)
30
 * @method static void nullOrDigit($value, $message = null, $propertyPath = null)
31
 * @method static void nullOrIntegerish($value, $message = null, $propertyPath = null)
32
 * @method static void nullOrBoolean($value, $message = null, $propertyPath = null)
33
 * @method static void nullOrScalar($value, $message = null, $propertyPath = null)
34
 * @method static void nullOrNotEmpty($value, $message = null, $propertyPath = null)
35
 * @method static void nullOrNoContent($value, $message = null, $propertyPath = null)
36
 * @method static void nullOrNotNull($value, $message = null, $propertyPath = null)
37
 * @method static void nullOrString($value, $message = null, $propertyPath = null)
38
 * @method static void nullOrRegex($value, $pattern, $message = null, $propertyPath = null)
39
 * @method static void nullOrLength($value, $length, $message = null, $propertyPath = null, $encoding = "utf8")
40
 * @method static void nullOrMinLength($value, $minLength, $message = null, $propertyPath = null, $encoding = "utf8")
41
 * @method static void nullOrMaxLength($value, $maxLength, $message = null, $propertyPath = null, $encoding = "utf8")
42
 * @method static void nullOrBetweenLength($value, $minLength, $maxLength, $message = null, $propertyPath = null, $encoding = "utf8")
43
 * @method static void nullOrStartsWith($string, $needle, $message = null, $propertyPath = null, $encoding = "utf8")
44
 * @method static void nullOrEndsWith($string, $needle, $message = null, $propertyPath = null, $encoding = "utf8")
45
 * @method static void nullOrContains($string, $needle, $message = null, $propertyPath = null, $encoding = "utf8")
46
 * @method static void nullOrChoice($value, $choices, $message = null, $propertyPath = null)
47
 * @method static void nullOrInArray($value, $choices, $message = null, $propertyPath = null)
48
 * @method static void nullOrNumeric($value, $message = null, $propertyPath = null)
49
 * @method static void nullOrIsArray($value, $message = null, $propertyPath = null)
50
 * @method static void nullOrIsTraversable($value, $message = null, $propertyPath = null)
51
 * @method static void nullOrIsArrayAccessible($value, $message = null, $propertyPath = null)
52
 * @method static void nullOrKeyExists($value, $key, $message = null, $propertyPath = null)
53
 * @method static void nullOrKeyIsset($value, $key, $message = null, $propertyPath = null)
54
 * @method static void nullOrNotEmptyKey($value, $key, $message = null, $propertyPath = null)
55
 * @method static void nullOrNotBlank($value, $message = null, $propertyPath = null)
56
 * @method static void nullOrIsInstanceOf($value, $className, $message = null, $propertyPath = null)
57
 * @method static void nullOrNotIsInstanceOf($value, $className, $message = null, $propertyPath = null)
58
 * @method static void nullOrSubclassOf($value, $className, $message = null, $propertyPath = null)
59
 * @method static void nullOrRange($value, $minValue, $maxValue, $message = null, $propertyPath = null)
60
 * @method static void nullOrMin($value, $minValue, $message = null, $propertyPath = null)
61
 * @method static void nullOrMax($value, $maxValue, $message = null, $propertyPath = null)
62
 * @method static void nullOrFile($value, $message = null, $propertyPath = null)
63
 * @method static void nullOrDirectory($value, $message = null, $propertyPath = null)
64
 * @method static void nullOrReadable($value, $message = null, $propertyPath = null)
65
 * @method static void nullOrWriteable($value, $message = null, $propertyPath = null)
66
 * @method static void nullOrEmail($value, $message = null, $propertyPath = null)
67
 * @method static void nullOrUrl($value, $message = null, $propertyPath = null)
68
 * @method static void nullOrAlnum($value, $message = null, $propertyPath = null)
69
 * @method static void nullOrTrue($value, $message = null, $propertyPath = null)
70
 * @method static void nullOrFalse($value, $message = null, $propertyPath = null)
71
 * @method static void nullOrClassExists($value, $message = null, $propertyPath = null)
72
 * @method static void nullOrImplementsInterface($class, $interfaceName, $message = null, $propertyPath = null)
73
 * @method static void nullOrIsJsonString($value, $message = null, $propertyPath = null)
74
 * @method static void nullOrUuid($value, $message = null, $propertyPath = null)
75
 * @method static void nullOrCount($countable, $count, $message = null, $propertyPath = null)
76
 * @method static void nullOrChoicesNotEmpty($values, $choices, $message = null, $propertyPath = null)
77
 * @method static void nullOrMethodExists($value, $object, $message = null, $propertyPath = null)
78
 * @method static void nullOrIsObject($value, $message = null, $propertyPath = null)
79
 * @method static void nullOrDate($value, $format, $message = null, $propertyPath = null)
80
 * @method static void allEq($value, $value2, $message = null, $propertyPath = null)
81
 * @method static void allSame($value, $value2, $message = null, $propertyPath = null)
82
 * @method static void allNotEq($value1, $value2, $message = null, $propertyPath = null)
83
 * @method static void allNotSame($value1, $value2, $message = null, $propertyPath = null)
84
 * @method static void allInteger($value, $message = null, $propertyPath = null)
85
 * @method static void allFloat($value, $message = null, $propertyPath = null)
86
 * @method static void allDigit($value, $message = null, $propertyPath = null)
87
 * @method static void allIntegerish($value, $message = null, $propertyPath = null)
88
 * @method static void allBoolean($value, $message = null, $propertyPath = null)
89
 * @method static void allScalar($value, $message = null, $propertyPath = null)
90
 * @method static void allNotEmpty($value, $message = null, $propertyPath = null)
91
 * @method static void allNoContent($value, $message = null, $propertyPath = null)
92
 * @method static void allNotNull($value, $message = null, $propertyPath = null)
93
 * @method static void allString($value, $message = null, $propertyPath = null)
94
 * @method static void allRegex($value, $pattern, $message = null, $propertyPath = null)
95
 * @method static void allLength($value, $length, $message = null, $propertyPath = null, $encoding = "utf8")
96
 * @method static void allMinLength($value, $minLength, $message = null, $propertyPath = null, $encoding = "utf8")
97
 * @method static void allMaxLength($value, $maxLength, $message = null, $propertyPath = null, $encoding = "utf8")
98
 * @method static void allBetweenLength($value, $minLength, $maxLength, $message = null, $propertyPath = null, $encoding = "utf8")
99
 * @method static void allStartsWith($string, $needle, $message = null, $propertyPath = null, $encoding = "utf8")
100
 * @method static void allEndsWith($string, $needle, $message = null, $propertyPath = null, $encoding = "utf8")
101
 * @method static void allContains($string, $needle, $message = null, $propertyPath = null, $encoding = "utf8")
102
 * @method static void allChoice($value, $choices, $message = null, $propertyPath = null)
103
 * @method static void allInArray($value, $choices, $message = null, $propertyPath = null)
104
 * @method static void allNumeric($value, $message = null, $propertyPath = null)
105
 * @method static void allIsArray($value, $message = null, $propertyPath = null)
106
 * @method static void allIsTraversable($value, $message = null, $propertyPath = null)
107
 * @method static void allIsArrayAccessible($value, $message = null, $propertyPath = null)
108
 * @method static void allKeyExists($value, $key, $message = null, $propertyPath = null)
109
 * @method static void allKeyIsset($value, $key, $message = null, $propertyPath = null)
110
 * @method static void allNotEmptyKey($value, $key, $message = null, $propertyPath = null)
111
 * @method static void allNotBlank($value, $message = null, $propertyPath = null)
112
 * @method static void allIsInstanceOf($value, $className, $message = null, $propertyPath = null)
113
 * @method static void allNotIsInstanceOf($value, $className, $message = null, $propertyPath = null)
114
 * @method static void allSubclassOf($value, $className, $message = null, $propertyPath = null)
115
 * @method static void allRange($value, $minValue, $maxValue, $message = null, $propertyPath = null)
116
 * @method static void allMin($value, $minValue, $message = null, $propertyPath = null)
117
 * @method static void allMax($value, $maxValue, $message = null, $propertyPath = null)
118
 * @method static void allFile($value, $message = null, $propertyPath = null)
119
 * @method static void allDirectory($value, $message = null, $propertyPath = null)
120
 * @method static void allReadable($value, $message = null, $propertyPath = null)
121
 * @method static void allWriteable($value, $message = null, $propertyPath = null)
122
 * @method static void allEmail($value, $message = null, $propertyPath = null)
123
 * @method static void allUrl($value, $message = null, $propertyPath = null)
124
 * @method static void allAlnum($value, $message = null, $propertyPath = null)
125
 * @method static void allTrue($value, $message = null, $propertyPath = null)
126
 * @method static void allFalse($value, $message = null, $propertyPath = null)
127
 * @method static void allClassExists($value, $message = null, $propertyPath = null)
128
 * @method static void allImplementsInterface($class, $interfaceName, $message = null, $propertyPath = null)
129
 * @method static void allIsJsonString($value, $message = null, $propertyPath = null)
130
 * @method static void allUuid($value, $message = null, $propertyPath = null)
131
 * @method static void allCount($countable, $count, $message = null, $propertyPath = null)
132
 * @method static void allChoicesNotEmpty($values, $choices, $message = null, $propertyPath = null)
133
 * @method static void allMethodExists($value, $object, $message = null, $propertyPath = null)
134
 * @method static void allIsObject($value, $message = null, $propertyPath = null)
135
 * @method static void allDate($value, $format, $message = null, $propertyPath = null)
136
 * METHODEND
137
 */
138
class Assertion
139
{
140
    const INVALID_FLOAT             = 9;
141
    const INVALID_INTEGER           = 10;
142
    const INVALID_DIGIT             = 11;
143
    const INVALID_INTEGERISH        = 12;
144
    const INVALID_BOOLEAN           = 13;
145
    const VALUE_EMPTY               = 14;
146
    const VALUE_NULL                = 15;
147
    const INVALID_STRING            = 16;
148
    const INVALID_REGEX             = 17;
149
    const INVALID_MIN_LENGTH        = 18;
150
    const INVALID_MAX_LENGTH        = 19;
151
    const INVALID_STRING_START      = 20;
152
    const INVALID_STRING_CONTAINS   = 21;
153
    const INVALID_CHOICE            = 22;
154
    const INVALID_NUMERIC           = 23;
155
    const INVALID_ARRAY             = 24;
156
    const INVALID_KEY_EXISTS        = 26;
157
    const INVALID_NOT_BLANK         = 27;
158
    const INVALID_INSTANCE_OF       = 28;
159
    const INVALID_SUBCLASS_OF       = 29;
160
    const INVALID_RANGE             = 30;
161
    const INVALID_ALNUM             = 31;
162
    const INVALID_TRUE              = 32;
163
    const INVALID_EQ                = 33;
164
    const INVALID_SAME              = 34;
165
    const INVALID_MIN               = 35;
166
    const INVALID_MAX               = 36;
167
    const INVALID_LENGTH            = 37;
168
    const INVALID_FALSE             = 38;
169
    const INVALID_STRING_END        = 39;
170
    const INVALID_UUID              = 40;
171
    const INVALID_COUNT             = 41;
172
    const INVALID_NOT_EQ            = 42;
173
    const INVALID_NOT_SAME          = 43;
174
    const INVALID_TRAVERSABLE       = 44;
175
    const INVALID_ARRAY_ACCESSIBLE  = 45;
176
    const INVALID_KEY_ISSET         = 46;
177
    const INVALID_CALLABLE          = 47;
178
    const INVALID_DIRECTORY         = 101;
179
    const INVALID_FILE              = 102;
180
    const INVALID_READABLE          = 103;
181
    const INVALID_WRITEABLE         = 104;
182
    const INVALID_CLASS             = 105;
183
    const INVALID_EMAIL             = 201;
184
    const INTERFACE_NOT_IMPLEMENTED = 202;
185
    const INVALID_URL               = 203;
186
    const INVALID_NOT_INSTANCE_OF   = 204;
187
    const VALUE_NOT_EMPTY           = 205;
188
    const INVALID_JSON_STRING       = 206;
189
    const INVALID_OBJECT            = 207;
190
    const INVALID_METHOD            = 208;
191
    const INVALID_SCALAR            = 209;
192
    const INVALID_LESS              = 210;
193
    const INVALID_LESS_OR_EQUAL     = 211;
194
    const INVALID_GREATER           = 212;
195
    const INVALID_GREATER_OR_EQUAL  = 212;
196
    const INVALID_DATE              = 213;
197
198
    /**
199
     * Exception to throw when an assertion failed.
200
     *
201
     * @var string
202
     */
203
    static protected $exceptionClass = 'Assert\InvalidArgumentException';
204
205
    /**
206
     * Helper method that handles building the assertion failure exceptions.
207
     * They are returned from this method so that the stack trace still shows
208
     * the assertions method.
209
     */
210
    protected static function createException($value, $message, $code, $propertyPath, array $constraints = array())
211
    {
212
        $exceptionClass = static::$exceptionClass;
213
        return new $exceptionClass($message, $code, $propertyPath, $value, $constraints);
214
    }
215
216
    /**
217
     * Assert that two values are equal (using == ).
218
     *
219
     * @param mixed $value
220
     * @param mixed $value2
221
     * @param string|null $message
222
     * @param string|null $propertyPath
223
     * @return void
224
     * @throws \Assert\AssertionFailedException
225
     */
226
    public static function eq($value, $value2, $message = null, $propertyPath = null)
227
    {
228
        if ($value != $value2) {
229
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
230
                $message ?: 'Value "%s" does not equal expected value "%s".',
231
                self::stringify($value),
232
                self::stringify($value2)
233
            );
234
235
            throw static::createException($value, $message, static::INVALID_EQ, $propertyPath, array('expected' => $value2));
236
        }
237
    }
238
239
    /**
240
     * Assert that two values are the same (using ===).
241
     *
242
     * @param mixed $value
243
     * @param mixed $value2
244
     * @param string|null $message
245
     * @param string|null $propertyPath
246
     * @return void
247
     * @throws \Assert\AssertionFailedException
248
     */
249
    public static function same($value, $value2, $message = null, $propertyPath = null)
250
    {
251
        if ($value !== $value2) {
252
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
253
                $message ?: 'Value "%s" is not the same as expected value "%s".',
254
                self::stringify($value),
255
                self::stringify($value2)
256
            );
257
258
            throw static::createException($value, $message, static::INVALID_SAME, $propertyPath, array('expected' => $value2));
259
        }
260
    }
261
262
    /**
263
     * Assert that two values are not equal (using == ).
264
     *
265
     * @param mixed $value1
266
     * @param mixed $value2
267
     * @param string|null $message
268
     * @param string|null $propertyPath
269
     * @return void
270
     * @throws \Assert\AssertionFailedException
271
     */
272
    public static function notEq($value1, $value2, $message = null, $propertyPath = null)
273
    {
274
        if ($value1 == $value2) {
275
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
276
                $message ?: 'Value "%s" is equal to expected value "%s".',
277
                self::stringify($value1),
278
                self::stringify($value2)
279
            );
280
            throw static::createException($value1, $message,static::INVALID_NOT_EQ, $propertyPath, array('expected' => $value2));
281
        }
282
    }
283
284
    /**
285
     * Assert that two values are not the same (using === ).
286
     *
287
     * @param mixed $value1
288
     * @param mixed $value2
289
     * @param string|null $message
290
     * @param string|null $propertyPath
291
     * @return void
292
     * @throws \Assert\AssertionFailedException
293
     */
294
    public static function notSame($value1, $value2, $message = null, $propertyPath = null)
295
    {
296
        if ($value1 === $value2) {
297
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
298
                $message ?: 'Value "%s" is the same as expected value "%s".',
299
                self::stringify($value1),
300
                self::stringify($value2)
301
            );
302
            throw static::createException($value1, $message, static::INVALID_NOT_SAME, $propertyPath, array('expected' => $value2));
303
        }
304
    }
305
306
    /**
307
     * Assert that value is a php integer.
308
     *
309
     * @param mixed $value
310
     * @param string|null $message
311
     * @param string|null $propertyPath
312
     * @return void
313
     * @throws \Assert\AssertionFailedException
314
     */
315
    public static function integer($value, $message = null, $propertyPath = null)
316
    {
317
        if ( ! is_int($value)) {
318
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
319
                $message ?: 'Value "%s" is not an integer.',
320
                self::stringify($value)
321
            );
322
323
            throw static::createException($value, $message, static::INVALID_INTEGER, $propertyPath);
324
        }
325
    }
326
327
    /**
328
     * Assert that value is a php float.
329
     *
330
     * @param mixed $value
331
     * @param string|null $message
332
     * @param string|null $propertyPath
333
     * @return void
334
     * @throws \Assert\AssertionFailedException
335
     */
336
    public static function float($value, $message = null, $propertyPath = null)
337
    {
338
        if ( ! is_float($value)) {
339
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
340
                $message ?: 'Value "%s" is not a float.',
341
                self::stringify($value)
342
            );
343
344
            throw static::createException($value, $message, static::INVALID_FLOAT, $propertyPath);
345
        }
346
    }
347
348
    /**
349
     * Validates if an integer or integerish is a digit.
350
     *
351
     * @param mixed $value
352
     * @param string|null $message
353
     * @param string|null $propertyPath
354
     * @return void
355
     * @throws \Assert\AssertionFailedException
356
     */
357
    public static function digit($value, $message = null, $propertyPath = null)
358
    {
359
        if ( ! ctype_digit((string)$value)) {
360
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
361
                $message ?: 'Value "%s" is not a digit.',
362
                self::stringify($value)
363
            );
364
365
            throw static::createException($value, $message, static::INVALID_DIGIT, $propertyPath);
366
        }
367
    }
368
369
    /**
370
     * Assert that value is a php integer'ish.
371
     * @param mixed $value
372
     * @param string|null $message
373
     * @param string|null $propertyPath
374
     * @return void
375
     * @throws \Assert\AssertionFailedException
376
     */
377
    public static function integerish($value, $message = null, $propertyPath = null)
378
    {
379
        if (is_object($value) || strval(intval($value)) != $value || is_bool($value) || is_null($value)) {
380
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
381
                $message ?: 'Value "%s" is not an integer or a number castable to integer.',
382
                self::stringify($value)
383
            );
384
385
            throw static::createException($value, $message, static::INVALID_INTEGERISH, $propertyPath);
386
        }
387
    }
388
389
    /**
390
     * Assert that value is php boolean
391
     *
392
     * @param mixed $value
393
     * @param string|null $message
394
     * @param string|null $propertyPath
395
     * @return void
396
     * @throws \Assert\AssertionFailedException
397
     */
398
    public static function boolean($value, $message = null, $propertyPath = null)
399
    {
400
        if ( ! is_bool($value)) {
401
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
402
                $message ?: 'Value "%s" is not a boolean.',
403
                self::stringify($value)
404
            );
405
406
            throw static::createException($value, $message, static::INVALID_BOOLEAN, $propertyPath);
407
        }
408
    }
409
410
    /**
411
     * Assert that value is a PHP scalar
412
     *
413
     * @param mixed $value
414
     * @param string|null $message
415
     * @param string|null $propertyPath
416
     * @return void
417
     * @throws \Assert\AssertionFailedException
418
     */
419
    public static function scalar($value, $message = null, $propertyPath = null)
420
    {
421
        if (!is_scalar($value)) {
422
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
423
                $message ?: 'Value "%s" is not a scalar.',
424
                self::stringify($value)
425
            );
426
427
            throw static::createException($value, $message, static::INVALID_SCALAR, $propertyPath);
428
        }
429
    }
430
431
    /**
432
     * Assert that value is not empty
433
     *
434
     * @param mixed $value
435
     * @param string|null $message
436
     * @param string|null $propertyPath
437
     * @return void
438
     * @throws \Assert\AssertionFailedException
439
     */
440
    public static function notEmpty($value, $message = null, $propertyPath = null)
441
    {
442
        if (empty($value)) {
443
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
444
                $message ?: 'Value "%s" is empty, but non empty value was expected.',
445
                self::stringify($value)
446
            );
447
448
            throw static::createException($value, $message, static::VALUE_EMPTY, $propertyPath);
449
        }
450
    }
451
452
    /**
453
     * Assert that value is empty
454
     *
455
     * @param mixed $value
456
     * @param string|null $message
457
     * @param string|null $propertyPath
458
     * @return void
459
     * @throws \Assert\AssertionFailedException
460
     */
461
    public static function noContent($value, $message = null, $propertyPath = null)
462
    {
463
        if (!empty($value)) {
464
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
465
                $message ?: 'Value "%s" is not empty, but empty value was expected.',
466
                self::stringify($value)
467
            );
468
469
            throw static::createException($value, $message, static::VALUE_NOT_EMPTY, $propertyPath);
470
        }
471
    }
472
473
    /**
474
     * Assert that value is not null
475
     *
476
     * @param mixed $value
477
     * @param string|null $message
478
     * @param string|null $propertyPath
479
     * @return void
480
     * @throws \Assert\AssertionFailedException
481
     */
482
    public static function notNull($value, $message = null, $propertyPath = null)
483
    {
484
        if ($value === null) {
485
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
486
                $message ?: 'Value "%s" is null, but non null value was expected.',
487
                self::stringify($value)
488
            );
489
490
            throw static::createException($value, $message, static::VALUE_NULL, $propertyPath);
491
        }
492
    }
493
494
    /**
495
     * Assert that value is a string
496
     *
497
     * @param mixed $value
498
     * @param string|null $message
499
     * @param string|null $propertyPath
500
     * @return void
501
     * @throws \Assert\AssertionFailedException
502
     */
503
    public static function string($value, $message = null, $propertyPath = null)
504
    {
505
        if ( ! is_string($value)) {
506
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
507
                $message ?: 'Value "%s" expected to be string, type %s given.',
508
                self::stringify($value),
509
                gettype($value)
510
            );
511
512
            throw static::createException($value, $message, static::INVALID_STRING, $propertyPath);
513
        }
514
    }
515
516
    /**
517
     * Assert that value matches a regex
518
     *
519
     * @param mixed $value
520
     * @param string $pattern
521
     * @param string|null $message
522
     * @param string|null $propertyPath
523
     * @return void
524
     * @throws \Assert\AssertionFailedException
525
     */
526
    public static function regex($value, $pattern, $message = null, $propertyPath = null)
527
    {
528
        static::string($value, $message, $propertyPath);
529
530
        if ( ! preg_match($pattern, $value)) {
531
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
532
                $message ?: 'Value "%s" does not match expression.',
533
                self::stringify($value)
534
            );
535
536
            throw static::createException($value, $message, static::INVALID_REGEX , $propertyPath, array('pattern' => $pattern));
0 ignored issues
show
Coding Style introduced by
Space found before comma in function call
Loading history...
537
        }
538
    }
539
540
    /**
541
     * Assert that string has a given length.
542
     *
543
     * @param mixed $value
544
     * @param int $length
545
     * @param string|null $message
546
     * @param string|null $propertyPath
547
     * @param string $encoding
548
     * @return void
549
     * @throws \Assert\AssertionFailedException
550
     */
551
    public static function length($value, $length, $message = null, $propertyPath = null, $encoding = 'utf8')
552
    {
553
        static::string($value, $message, $propertyPath);
554
555
        if (mb_strlen($value, $encoding) !== $length) {
556
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
557
                $message ?: 'Value "%s" has to be %d exactly characters long, but length is %d.',
558
                self::stringify($value),
559
                $length,
560
                mb_strlen($value, $encoding)
561
            );
562
563
            $constraints = array('length' => $length, 'encoding' => $encoding);
564
            throw static::createException($value, $message, static::INVALID_LENGTH, $propertyPath, $constraints);
565
        }
566
    }
567
568
    /**
569
     * Assert that a string is at least $minLength chars long.
570
     *
571
     * @param mixed $value
572
     * @param int $minLength
573
     * @param string|null $message
574
     * @param string|null $propertyPath
575
     * @param string $encoding
576
     * @return void
577
     * @throws \Assert\AssertionFailedException
578
     */
579
    public static function minLength($value, $minLength, $message = null, $propertyPath = null, $encoding = 'utf8')
580
    {
581
        static::string($value, $message, $propertyPath);
582
583
        if (mb_strlen($value, $encoding) < $minLength) {
584
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
585
                $message ?: 'Value "%s" is too short, it should have more than %d characters, but only has %d characters.',
586
                self::stringify($value),
587
                $minLength,
588
                mb_strlen($value, $encoding)
589
            );
590
591
            $constraints = array('min_length' => $minLength, 'encoding' => $encoding);
592
            throw static::createException($value, $message, static::INVALID_MIN_LENGTH, $propertyPath, $constraints);
593
        }
594
    }
595
596
    /**
597
     * Assert that string value is not longer than $maxLength chars.
598
     *
599
     * @param mixed $value
600
     * @param integer $maxLength
601
     * @param string|null $message
602
     * @param string|null $propertyPath
603
     * @param string $encoding
604
     * @return void
605
     * @throws \Assert\AssertionFailedException
606
     */
607
    public static function maxLength($value, $maxLength, $message = null, $propertyPath = null, $encoding = 'utf8')
608
    {
609
        static::string($value, $message, $propertyPath);
610
611
        if (mb_strlen($value, $encoding) > $maxLength) {
612
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
613
                $message ?: 'Value "%s" is too long, it should have no more than %d characters, but has %d characters.',
614
                self::stringify($value),
615
                $maxLength,
616
                mb_strlen($value, $encoding)
617
            );
618
619
            $constraints = array('max_length' => $maxLength, 'encoding' => $encoding);
620
            throw static::createException($value, $message, static::INVALID_MAX_LENGTH, $propertyPath, $constraints);
621
        }
622
    }
623
624
    /**
625
     * Assert that string length is between min,max lengths.
626
     *
627
     * @param mixed $value
628
     * @param integer $minLength
629
     * @param integer $maxLength
630
     * @param string|null $message
631
     * @param string|null $propertyPath
632
     * @param string $encoding
633
     * @return void
634
     * @throws \Assert\AssertionFailedException
635
     */
636
    public static function betweenLength($value, $minLength, $maxLength, $message = null, $propertyPath = null, $encoding = 'utf8')
637
    {
638
        static::string($value, $message, $propertyPath);
639
640
        if (mb_strlen($value, $encoding) < $minLength) {
641
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
642
                $message ?: 'Value "%s" is too short, it should have at least %d characters, but only has %d characters.',
643
                self::stringify($value),
644
                $minLength,
645
                mb_strlen($value, $encoding)
646
            );
647
648
            $constraints = array('min_length' => $minLength, 'encoding' => $encoding);
649
            throw static::createException($value, $message, static::INVALID_MIN_LENGTH, $propertyPath, $constraints);
650
        }
651
652
        if (mb_strlen($value, $encoding) > $maxLength) {
653
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
654
                $message ?: 'Value "%s" is too long, it should have no more than %d characters, but has %d characters.',
655
                self::stringify($value),
656
                $maxLength,
657
                mb_strlen($value, $encoding)
658
            );
659
660
            $constraints = array('max_length' => $maxLength, 'encoding' => $encoding);
661
            throw static::createException($value, $message, static::INVALID_MAX_LENGTH, $propertyPath, $constraints);
662
        }
663
    }
664
665
    /**
666
     * Assert that string starts with a sequence of chars.
667
     *
668
     * @param mixed $string
669
     * @param string $needle
670
     * @param string|null $message
671
     * @param string|null $propertyPath
672
     * @param string $encoding
673
     * @return void
674
     * @throws \Assert\AssertionFailedException
675
     */
676
    public static function startsWith($string, $needle, $message = null, $propertyPath = null, $encoding = 'utf8')
677
    {
678
        static::string($string, $message, $propertyPath);
679
680
        if (mb_strpos($string, $needle, null, $encoding) !== 0) {
681
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
682
                $message ?: 'Value "%s" does not start with "%s".',
683
                self::stringify($string),
684
                self::stringify($needle)
685
            );
686
687
            $constraints = array('needle' => $needle, 'encoding' => $encoding);
688
            throw static::createException($string, $message, static::INVALID_STRING_START, $propertyPath, $constraints);
689
        }
690
    }
691
692
    /**
693
     * Assert that string ends with a sequence of chars.
694
     *
695
     * @param mixed $string
696
     * @param string $needle
697
     * @param string|null $message
698
     * @param string|null $propertyPath
699
     * @param string $encoding
700
     * @return void
701
     * @throws \Assert\AssertionFailedException
702
     */
703
    public static function endsWith($string, $needle, $message = null, $propertyPath = null, $encoding = 'utf8')
704
    {
705
        static::string($string, $message, $propertyPath);
706
707
        $stringPosition = mb_strlen($string, $encoding) - mb_strlen($needle, $encoding);
708
709
        if (mb_strripos($string, $needle, null, $encoding) !== $stringPosition) {
710
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
711
                $message ?: 'Value "%s" does not end with "%s".',
712
                self::stringify($string),
713
                self::stringify($needle)
714
            );
715
716
            $constraints = array('needle' => $needle, 'encoding' => $encoding);
717
            throw static::createException($string, $message, static::INVALID_STRING_END, $propertyPath, $constraints);
718
        }
719
    }
720
721
    /**
722
     * Assert that string contains a sequence of chars.
723
     *
724
     * @param mixed $string
725
     * @param string $needle
726
     * @param string|null $message
727
     * @param string|null $propertyPath
728
     * @param string $encoding
729
     * @return void
730
     * @throws \Assert\AssertionFailedException
731
     */
732
    public static function contains($string, $needle, $message = null, $propertyPath = null, $encoding = 'utf8')
733
    {
734
        static::string($string, $message, $propertyPath);
735
736
        if (mb_strpos($string, $needle, null, $encoding) === false) {
737
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
738
                $message ?: 'Value "%s" does not contain "%s".',
739
                self::stringify($string),
740
                self::stringify($needle)
741
            );
742
743
            $constraints = array('needle' => $needle, 'encoding' => $encoding);
744
            throw static::createException($string, $message, static::INVALID_STRING_CONTAINS, $propertyPath, $constraints);
745
        }
746
    }
747
748
    /**
749
     * Assert that value is in array of choices.
750
     *
751
     * @param mixed $value
752
     * @param array $choices
753
     * @param string|null $message
754
     * @param string|null $propertyPath
755
     * @return void
756
     * @throws \Assert\AssertionFailedException
757
     */
758
    public static function choice($value, array $choices, $message = null, $propertyPath = null)
759
    {
760
        if ( ! in_array($value, $choices, true)) {
761
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
762
                $message ?: 'Value "%s" is not an element of the valid values: %s',
763
                self::stringify($value),
764
                implode(", ", array_map('Assert\Assertion::stringify', $choices))
765
            );
766
767
            throw static::createException($value, $message, static::INVALID_CHOICE, $propertyPath, array('choices' => $choices));
768
        }
769
    }
770
771
    /**
772
     * Alias of {@see choice()}
773
     *
774
     * @throws \Assert\AssertionFailedException
775
     */
776
    public static function inArray($value, array $choices, $message = null, $propertyPath = null)
777
    {
778
        static::choice($value, $choices, $message, $propertyPath);
779
    }
780
781
    /**
782
     * Assert that value is numeric.
783
     *
784
     * @param mixed $value
785
     * @param string|null $message
786
     * @param string|null $propertyPath
787
     * @return void
788
     * @throws \Assert\AssertionFailedException
789
     */
790
    public static function numeric($value, $message = null, $propertyPath = null)
791
    {
792
        if ( ! is_numeric($value)) {
793
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
794
                $message ?: 'Value "%s" is not numeric.',
795
                self::stringify($value)
796
            );
797
798
            throw static::createException($value, $message, static::INVALID_NUMERIC, $propertyPath);
799
        }
800
    }
801
802
    /**
803
     * Assert that value is an array.
804
     *
805
     * @param mixed $value
806
     * @param string|null $message
807
     * @param string|null $propertyPath
808
     * @return void
809
     * @throws \Assert\AssertionFailedException
810
     */
811
    public static function isArray($value, $message = null, $propertyPath = null)
812
    {
813
        if ( ! is_array($value)) {
814
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
815
                $message ?: 'Value "%s" is not an array.',
816
                self::stringify($value)
817
            );
818
819
            throw static::createException($value, $message, static::INVALID_ARRAY, $propertyPath);
820
        }
821
    }
822
823
    /**
824
     * Assert that value is an array or a traversable object.
825
     *
826
     * @param mixed $value
827
     * @param string|null $message
828
     * @param string|null $propertyPath
829
     * @return void
830
     * @throws \Assert\AssertionFailedException
831
     */
832
    public static function isTraversable($value, $message = null, $propertyPath = null)
833
    {
834
        if ( ! is_array($value) && ! $value instanceof \Traversable) {
835
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
836
                $message ?: 'Value "%s" is not an array and does not implement Traversable.',
837
                self::stringify($value)
838
            );
839
840
            throw static::createException($value, $message, static::INVALID_TRAVERSABLE, $propertyPath);
841
        }
842
    }
843
844
    /**
845
     * Assert that value is an array or an array-accessible object.
846
     *
847
     * @param mixed $value
848
     * @param string|null $message
849
     * @param string|null $propertyPath
850
     * @return void
851
     * @throws \Assert\AssertionFailedException
852
     */
853
    public static function isArrayAccessible($value, $message = null, $propertyPath = null)
854
    {
855
        if ( ! is_array($value) && ! $value instanceof \ArrayAccess) {
856
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
857
                $message ?: 'Value "%s" is not an array and does not implement ArrayAccess.',
858
                self::stringify($value)
859
            );
860
861
            throw static::createException($value, $message, static::INVALID_ARRAY_ACCESSIBLE, $propertyPath);
862
        }
863
    }
864
865
    /**
866
     * Assert that key exists in an array
867
     *
868
     * @param mixed $value
869
     * @param string|integer $key
870
     * @param string|null $message
871
     * @param string|null $propertyPath
872
     * @return void
873
     * @throws \Assert\AssertionFailedException
874
     */
875
    public static function keyExists($value, $key, $message = null, $propertyPath = null)
876
    {
877
        static::isArray($value, $message, $propertyPath);
878
879
        if ( ! array_key_exists($key, $value)) {
880
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
881
                $message ?: 'Array does not contain an element with key "%s"',
882
                self::stringify($key)
883
            );
884
885
            throw static::createException($value, $message, static::INVALID_KEY_EXISTS, $propertyPath, array('key' => $key));
886
        }
887
    }
888
889
    /**
890
     * Assert that key exists in an array/array-accessible object using isset()
891
     *
892
     * @param mixed $value
893
     * @param string|integer $key
894
     * @param string|null $message
895
     * @param string|null $propertyPath
896
     * @return void
897
     * @throws \Assert\AssertionFailedException
898
     */
899
    public static function keyIsset($value, $key, $message = null, $propertyPath = null)
900
    {
901
        static::isArrayAccessible($value, $message, $propertyPath);
902
903
        if ( ! isset($value[$key])) {
904
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
905
                $message ?: 'The element with key "%s" was not found',
906
                self::stringify($key)
907
            );
908
909
            throw static::createException($value, $message, static::INVALID_KEY_ISSET, $propertyPath, array('key' => $key));
910
        }
911
    }
912
913
    /**
914
     * Assert that key exists in an array/array-accessible object and it's value is not empty.
915
     *
916
     * @param mixed $value
917
     * @param string|integer $key
918
     * @param string|null $message
919
     * @param string|null $propertyPath
920
     * @return void
921
     * @throws \Assert\AssertionFailedException
922
     */
923
    public static function notEmptyKey($value, $key, $message = null, $propertyPath = null)
924
    {
925
        static::keyIsset($value, $key, $message, $propertyPath);
926
        static::notEmpty($value[$key], $message, $propertyPath);
927
    }
928
929
    /**
930
     * Assert that value is not blank
931
     *
932
     * @param mixed $value
933
     * @param string|null $message
934
     * @param string|null $propertyPath
935
     * @return void
936
     * @throws \Assert\AssertionFailedException
937
     */
938
    public static function notBlank($value, $message = null, $propertyPath = null)
939
    {
940
        if (false === $value || (empty($value) && '0' != $value) || (is_string($value) && '' === trim($value))) {
941
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
942
                $message ?: 'Value "%s" is blank, but was expected to contain a value.',
943
                self::stringify($value)
944
            );
945
946
            throw static::createException($value, $message, static::INVALID_NOT_BLANK, $propertyPath);
947
        }
948
    }
949
950
    /**
951
     * Assert that value is instance of given class-name.
952
     *
953
     * @param mixed $value
954
     * @param string $className
955
     * @param string|null $message
956
     * @param string|null $propertyPath
957
     * @return void
958
     * @throws \Assert\AssertionFailedException
959
     */
960
    public static function isInstanceOf($value, $className, $message = null, $propertyPath = null)
961
    {
962
        if ( ! ($value instanceof $className)) {
963
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
964
                $message ?: 'Class "%s" was expected to be instanceof of "%s" but is not.',
965
                self::stringify($value),
966
                $className
967
            );
968
969
            throw static::createException($value, $message, static::INVALID_INSTANCE_OF, $propertyPath, array('class' => $className));
970
        }
971
    }
972
973
    /**
974
     * Assert that value is not instance of given class-name.
975
     *
976
     * @param mixed $value
977
     * @param string $className
978
     * @param string|null $message
979
     * @param string|null $propertyPath
980
     * @return void
981
     * @throws \Assert\AssertionFailedException
982
     */
983
    public static function notIsInstanceOf($value, $className, $message = null, $propertyPath = null)
984
    {
985
        if ($value instanceof $className) {
986
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
987
                $message ?: 'Class "%s" was not expected to be instanceof of "%s".',
988
                self::stringify($value),
989
                $className
990
            );
991
992
            throw static::createException($value, $message, static::INVALID_NOT_INSTANCE_OF, $propertyPath, array('class' => $className));
993
        }
994
    }
995
996
    /**
997
     * Assert that value is subclass of given class-name.
998
     *
999
     * @param mixed $value
1000
     * @param string $className
1001
     * @param string|null $message
1002
     * @param string|null $propertyPath
1003
     * @return void
1004
     * @throws \Assert\AssertionFailedException
1005
     */
1006
    public static function subclassOf($value, $className, $message = null, $propertyPath = null)
1007
    {
1008
        if ( ! is_subclass_of($value, $className)) {
1009
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1010
                $message ?: 'Class "%s" was expected to be subclass of "%s".',
1011
                self::stringify($value),
1012
                $className
1013
            );
1014
1015
            throw static::createException($value, $message, static::INVALID_SUBCLASS_OF, $propertyPath, array('class' => $className));
1016
        }
1017
    }
1018
1019
    /**
1020
     * Assert that value is in range of numbers.
1021
     *
1022
     * @param mixed $value
1023
     * @param integer $minValue
1024
     * @param integer $maxValue
1025
     * @param string|null $message
1026
     * @param string|null $propertyPath
1027
     * @return void
1028
     * @throws \Assert\AssertionFailedException
1029
     */
1030
    public static function range($value, $minValue, $maxValue, $message = null, $propertyPath = null)
1031
    {
1032
        static::numeric($value, $message, $propertyPath);
1033
1034
        if ($value < $minValue || $value > $maxValue) {
1035
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1036
                $message ?: 'Number "%s" was expected to be at least "%d" and at most "%d".',
1037
                self::stringify($value),
1038
                self::stringify($minValue),
1039
                self::stringify($maxValue)
1040
            );
1041
1042
            throw static::createException($value, $message, static::INVALID_RANGE, $propertyPath, array('min' => $minValue, 'max' => $maxValue));
1043
        }
1044
    }
1045
1046
    /**
1047
     * Assert that a value is at least as big as a given limit
1048
     *
1049
     * @param mixed $value
1050
     * @param mixed $minValue
1051
     * @param string|null $message
1052
     * @param string|null $propertyPath
1053
     * @return void
1054
     * @throws \Assert\AssertionFailedException
1055
     */
1056
    public static function min($value, $minValue, $message = null, $propertyPath = null)
1057
    {
1058
        static::numeric($value, $message, $propertyPath);
1059
1060
        if ($value < $minValue) {
1061
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1062
                $message ?: 'Number "%s" was expected to be at least "%d".',
1063
                self::stringify($value),
1064
                self::stringify($minValue)
1065
            );
1066
1067
            throw static::createException($value, $message, static::INVALID_MIN, $propertyPath, array('min' => $minValue));
1068
        }
1069
    }
1070
1071
    /**
1072
     * Assert that a number is smaller as a given limit
1073
     *
1074
     * @param mixed $value
1075
     * @param mixed $maxValue
1076
     * @param string|null $message
1077
     * @param string|null $propertyPath
1078
     * @return void
1079
     * @throws \Assert\AssertionFailedException
1080
     */
1081
    public static function max($value, $maxValue, $message = null, $propertyPath = null)
1082
    {
1083
        static::numeric($value, $message, $propertyPath);
1084
1085
        if ($value > $maxValue) {
1086
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1087
                $message ?: 'Number "%s" was expected to be at most "%d".',
1088
                self::stringify($value),
1089
                self::stringify($maxValue)
1090
            );
1091
1092
            throw static::createException($value, $message, static::INVALID_MAX, $propertyPath, array('max' => $maxValue));
1093
        }
1094
    }
1095
1096
    /**
1097
     * Assert that a file exists
1098
     *
1099
     * @param string $value
1100
     * @param string|null $message
1101
     * @param string|null $propertyPath
1102
     * @return void
1103
     * @throws \Assert\AssertionFailedException
1104
     */
1105
    public static function file($value, $message = null, $propertyPath = null)
1106
    {
1107
        static::string($value, $message, $propertyPath);
1108
        static::notEmpty($value, $message, $propertyPath);
1109
1110
        if ( ! is_file($value)) {
1111
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1112
                $message ?: 'File "%s" was expected to exist.',
1113
                self::stringify($value)
1114
            );
1115
1116
            throw static::createException($value, $message, static::INVALID_FILE, $propertyPath);
1117
        }
1118
    }
1119
1120
    /**
1121
     * Assert that a directory exists
1122
     *
1123
     * @param string $value
1124
     * @param string|null $message
1125
     * @param string|null $propertyPath
1126
     * @return void
1127
     * @throws \Assert\AssertionFailedException
1128
     */
1129
    public static function directory($value, $message = null, $propertyPath = null)
1130
    {
1131
        static::string($value, $message, $propertyPath);
1132
1133
        if ( ! is_dir($value)) {
1134
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1135
                $message ?: 'Path "%s" was expected to be a directory.',
1136
                self::stringify($value)
1137
            );
1138
1139
            throw static::createException($value, $message, static::INVALID_DIRECTORY, $propertyPath);
1140
        }
1141
    }
1142
1143
    /**
1144
     * Assert that the value is something readable
1145
     *
1146
     * @param string $value
1147
     * @param string|null $message
1148
     * @param string|null $propertyPath
1149
     * @return void
1150
     * @throws \Assert\AssertionFailedException
1151
     */
1152
    public static function readable($value, $message = null, $propertyPath = null)
1153
    {
1154
        static::string($value, $message, $propertyPath);
1155
1156
        if ( ! is_readable($value)) {
1157
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1158
                $message ?: 'Path "%s" was expected to be readable.',
1159
                self::stringify($value)
1160
            );
1161
1162
            throw static::createException($value, $message, static::INVALID_READABLE, $propertyPath);
1163
        }
1164
    }
1165
1166
    /**
1167
     * Assert that the value is something writeable
1168
     *
1169
     * @param string $value
1170
     * @param string|null $message
1171
     * @param string|null $propertyPath
1172
     * @return void
1173
     * @throws \Assert\AssertionFailedException
1174
     */
1175
    public static function writeable($value, $message = null, $propertyPath = null)
1176
    {
1177
        static::string($value, $message, $propertyPath);
1178
1179
        if ( ! is_writeable($value)) {
1180
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1181
                $message ?: 'Path "%s" was expected to be writeable.',
1182
                self::stringify($value)
1183
            );
1184
1185
            throw static::createException($value, $message, static::INVALID_WRITEABLE, $propertyPath);
1186
        }
1187
    }
1188
1189
    /**
1190
     * Assert that value is an email adress (using
1191
     * input_filter/FILTER_VALIDATE_EMAIL).
1192
     *
1193
     * @param mixed $value
1194
     * @param string|null $message
1195
     * @param string|null $propertyPath
1196
     * @return void
1197
     * @throws \Assert\AssertionFailedException
1198
     */
1199
    public static function email($value, $message = null, $propertyPath = null)
1200
    {
1201
        static::string($value, $message, $propertyPath);
1202
1203
        if ( ! filter_var($value, FILTER_VALIDATE_EMAIL)) {
1204
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1205
                $message ?: 'Value "%s" was expected to be a valid e-mail address.',
1206
                self::stringify($value)
1207
            );
1208
1209
            throw static::createException($value, $message, static::INVALID_EMAIL, $propertyPath);
1210
        } else {
1211
            $host = substr($value, strpos($value, '@') + 1);
1212
1213
            // Likely not a FQDN, bug in PHP FILTER_VALIDATE_EMAIL prior to PHP 5.3.3
1214
            if (version_compare(PHP_VERSION, '5.3.3', '<') && strpos($host, '.') === false) {
1215
                $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1216
                    $message ?: 'Value "%s" was expected to be a valid e-mail address.',
1217
                    self::stringify($value)
1218
                );
1219
1220
                throw static::createException($value, $message, static::INVALID_EMAIL, $propertyPath);
1221
            }
1222
        }
1223
    }
1224
1225
    /**
1226
     * Assert that value is an URL.
1227
     *
1228
     * This code snipped was taken from the Symfony project and modified to the special demands of this method.
1229
     *
1230
     * @param mixed $value
1231
     * @param string|null $message
1232
     * @param string|null $propertyPath
1233
     * @return void
1234
     * @throws \Assert\AssertionFailedException
1235
     *
1236
     *
1237
     * @link https://github.com/symfony/Validator/blob/master/Constraints/UrlValidator.php
1238
     * @link https://github.com/symfony/Validator/blob/master/Constraints/Url.php
1239
     */
1240
    public static function url($value, $message = null, $propertyPath = null)
1241
    {
1242
        static::string($value, $message, $propertyPath);
1243
1244
        $protocols = array('http', 'https');
1245
1246
        $pattern = '~^
1247
            (%s)://                                 # protocol
1248
            (
1249
                ([\pL\pN\pS-]+\.)+[\pL]+                   # a domain name
1250
                    |                                     #  or
1251
                \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}      # a IP address
1252
                    |                                     #  or
1253
                \[
1254
                    (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::))))
1255
                \]  # a IPv6 address
1256
            )
1257
            (:[0-9]+)?                              # a port (optional)
1258
            (/?|/\S+)                               # a /, nothing or a / with something
1259
        $~ixu';
1260
1261
        $pattern = sprintf($pattern, implode('|', $protocols));
1262
1263
        if (!preg_match($pattern, $value)) {
1264
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1265
                $message ?: 'Value "%s" was expected to be a valid URL starting with http or https',
1266
                self::stringify($value)
1267
            );
1268
1269
            throw static::createException($value, $message, static::INVALID_URL, $propertyPath);
1270
        }
1271
1272
    }
1273
1274
    /**
1275
     * Assert that value is alphanumeric.
1276
     *
1277
     * @param mixed $value
1278
     * @param string|null $message
1279
     * @param string|null $propertyPath
1280
     * @return void
1281
     * @throws \Assert\AssertionFailedException
1282
     */
1283
    public static function alnum($value, $message = null, $propertyPath = null)
1284
    {
1285
        try {
1286
            static::regex($value, '(^([a-zA-Z]{1}[a-zA-Z0-9]*)$)', $message, $propertyPath);
1287
        } catch(AssertionFailedException $e) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after CATCH keyword; 0 found
Loading history...
1288
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1289
                $message ?: 'Value "%s" is not alphanumeric, starting with letters and containing only letters and numbers.',
1290
                self::stringify($value)
1291
            );
1292
1293
            throw static::createException($value, $message, static::INVALID_ALNUM, $propertyPath);
1294
        }
1295
    }
1296
1297
    /**
1298
     * Assert that the value is boolean True.
1299
     *
1300
     * @param mixed $value
1301
     * @param string|null $message
1302
     * @param string|null $propertyPath
1303
     * @return void
1304
     * @throws \Assert\AssertionFailedException
1305
     */
1306
    public static function true($value, $message = null, $propertyPath = null)
1307
    {
1308
        if ($value !== true) {
1309
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1310
                $message ?: 'Value "%s" is not TRUE.',
1311
                self::stringify($value)
1312
            );
1313
1314
            throw static::createException($value, $message, static::INVALID_TRUE, $propertyPath);
1315
        }
1316
    }
1317
1318
    /**
1319
     * Assert that the value is boolean False.
1320
     *
1321
     * @param mixed $value
1322
     * @param string|null $message
1323
     * @param string|null $propertyPath
1324
     * @return void
1325
     * @throws \Assert\AssertionFailedException
1326
     */
1327
    public static function false($value, $message = null, $propertyPath = null)
1328
    {
1329
        if ($value !== false) {
1330
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1331
                $message ?: 'Value "%s" is not FALSE.',
1332
                self::stringify($value)
1333
            );
1334
1335
            throw static::createException($value, $message, static::INVALID_FALSE, $propertyPath);
1336
        }
1337
    }
1338
1339
    /**
1340
     * Assert that the class exists.
1341
     *
1342
     * @param mixed $value
1343
     * @param string|null $message
1344
     * @param string|null $propertyPath
1345
     * @return void
1346
     * @throws \Assert\AssertionFailedException
1347
     */
1348
    public static function classExists($value, $message = null, $propertyPath = null)
1349
    {
1350
        if ( ! class_exists($value)) {
1351
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1352
                $message ?: 'Class "%s" does not exist.',
1353
                self::stringify($value)
1354
            );
1355
1356
            throw static::createException($value, $message, static::INVALID_CLASS, $propertyPath);
1357
        }
1358
    }
1359
1360
    /**
1361
     * Assert that the class implements the interface
1362
     *
1363
     * @param mixed $class
1364
     * @param string $interfaceName
1365
     * @param string|null $message
1366
     * @param string|null $propertyPath
1367
     * @return void
1368
     * @throws \Assert\AssertionFailedException
1369
     */
1370
    public static function implementsInterface($class, $interfaceName, $message = null, $propertyPath = null)
1371
    {
1372
        $reflection = new \ReflectionClass($class);
1373
        if ( ! $reflection->implementsInterface($interfaceName)) {
1374
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1375
                $message ?: 'Class "%s" does not implement interface "%s".',
1376
                self::stringify($class),
1377
                self::stringify($interfaceName)
1378
            );
1379
1380
            throw static::createException($class, $message, static::INTERFACE_NOT_IMPLEMENTED, $propertyPath, array('interface' => $interfaceName));
1381
        }
1382
    }
1383
1384
    /**
1385
     * Assert that the given string is a valid json string.
1386
     *
1387
     * NOTICE:
1388
     * Since this does a json_decode to determine its validity
1389
     * you probably should consider, when using the variable
1390
     * content afterwards, just to decode and check for yourself instead
1391
     * of using this assertion.
1392
     *
1393
     * @param mixed $value
1394
     * @param string|null $message
1395
     * @param string|null $propertyPath
1396
     * @return void
1397
     * @throws \Assert\AssertionFailedException
1398
     */
1399
    public static function isJsonString($value, $message = null, $propertyPath = null)
1400
    {
1401
        if (null === json_decode($value) && JSON_ERROR_NONE !== json_last_error()) {
1402
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1403
                $message ?: 'Value "%s" is not a valid JSON string.',
1404
                self::stringify($value)
1405
            );
1406
1407
            throw static::createException($value, $message, static::INVALID_JSON_STRING, $propertyPath);
1408
        }
1409
    }
1410
1411
    /**
1412
     * Assert that the given string is a valid UUID
1413
     *
1414
     * Uses code from {@link https://github.com/ramsey/uuid} that is MIT licensed.
1415
     *
1416
     * @param string $value
1417
     * @param string|null $message
1418
     * @param string|null $propertyPath
1419
     * @return void
1420
     * @throws \Assert\AssertionFailedException
1421
     */
1422
    public static function uuid($value, $message = null, $propertyPath = null)
1423
    {
1424
        $value = str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $value. This often makes code more readable.
Loading history...
1425
1426
        if ($value === '00000000-0000-0000-0000-000000000000') {
1427
            return;
1428
        }
1429
1430
        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)) {
1431
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1432
                $message ?: 'Value "%s" is not a valid UUID.',
1433
                self::stringify($value)
1434
            );
1435
1436
            throw static::createException($value, $message, static::INVALID_UUID, $propertyPath);
1437
        }
1438
    }
1439
1440
    /**
1441
     * Assert that the count of countable is equal to count.
1442
     *
1443
     * @param array|\Countable $countable
1444
     * @param int              $count
1445
     * @param string           $message
0 ignored issues
show
Documentation introduced by
Should the type for parameter $message not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1446
     * @param string           $propertyPath
0 ignored issues
show
Documentation introduced by
Should the type for parameter $propertyPath not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1447
     * @return void
1448
     * @throws \Assert\AssertionFailedException
1449
     */
1450
    public static function count($countable, $count, $message = null, $propertyPath = null)
1451
    {
1452
        if ($count !== count($countable)) {
1453
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1454
                $message ?: 'List does not contain exactly "%d" elements.',
1455
                self::stringify($count)
1456
            );
1457
1458
            throw static::createException($countable, $message, static::INVALID_COUNT, $propertyPath, array('count' => $count));
1459
        }
1460
    }
1461
1462
    /**
1463
     * static call handler to implement:
1464
     *  - "null or assertion" delegation
1465
     *  - "all" delegation
1466
     */
1467
    public static function __callStatic($method, $args)
1468
    {
1469
        if (strpos($method, "nullOr") === 0) {
1470
            if ( ! array_key_exists(0, $args)) {
1471
                throw new BadMethodCallException("Missing the first argument.");
1472
            }
1473
1474
            if ($args[0] === null) {
1475
                return;
1476
            }
1477
1478
            $method = substr($method, 6);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $method. This often makes code more readable.
Loading history...
1479
1480
            return call_user_func_array(array(get_called_class(), $method), $args);
1481
        }
1482
1483
        if (strpos($method, "all") === 0) {
1484
            if ( ! array_key_exists(0, $args)) {
1485
                throw new BadMethodCallException("Missing the first argument.");
1486
            }
1487
1488
            static::isTraversable($args[0]);
1489
1490
            $method      = substr($method, 3);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $method. This often makes code more readable.
Loading history...
1491
            $values      = array_shift($args);
1492
            $calledClass = get_called_class();
1493
1494
            foreach ($values as $value) {
1495
                call_user_func_array(array($calledClass, $method), array_merge(array($value), $args));
1496
            }
1497
1498
            return;
1499
        }
1500
1501
        throw new BadMethodCallException("No assertion Assertion#" . $method . " exists.");
1502
    }
1503
1504
    /**
1505
     * Determines if the values array has every choice as key and that this choice has content.
1506
     *
1507
     * @param array $values
1508
     * @param array $choices
1509
     * @param null  $message
1510
     * @param null  $propertyPath
1511
     */
1512
    public static function choicesNotEmpty(array $values, array $choices, $message = null, $propertyPath = null)
1513
    {
1514
        self::notEmpty($values, $message, $propertyPath);
1515
1516
        foreach ($choices as $choice) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
1517
1518
            self::notEmptyKey($values, $choice, $message, $propertyPath);
1519
        }
1520
    }
1521
1522
    /**
1523
     * Determines that the named method is defined in the provided object.
1524
     *
1525
     * @param string $value
1526
     * @param mixed  $object
1527
     * @param null   $message
1528
     * @param null   $propertyPath
1529
     *
1530
     * @throws
1531
     */
1532
    public static function methodExists($value, $object, $message = null, $propertyPath = null)
1533
    {
1534
        self::isObject($object, $message, $propertyPath);
1535
1536
        if (!method_exists($object, $value)) {
1537
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1538
                $message ?: 'Expected "%s" does not exist in provided object.',
1539
                self::stringify($value)
1540
            );
1541
1542
            throw static::createException($value, $message, static::INVALID_METHOD, $propertyPath);
1543
        }
1544
    }
1545
1546
    /**
1547
     * Determines that the provided value is an object.
1548
     *
1549
     * @param mixed $value
1550
     * @param null  $message
1551
     * @param null  $propertyPath
1552
     */
1553
    public static function isObject($value, $message = null, $propertyPath = null)
1554
    {
1555
        if (!is_object($value)) {
1556
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1557
                $message ?: 'Provided "%s" is not a valid object.',
1558
                self::stringify($value)
1559
            );
1560
1561
            throw static::createException($value, $message, static::INVALID_OBJECT, $propertyPath);
1562
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
1563
        }
1564
    }
1565
1566
    /**
1567
     * Determines if the value is less than given limit.
1568
     *
1569
     * @param mixed $value
1570
     * @param mixed $limit
1571
     * @param null  $message
1572
     * @param null  $propertyPath
1573
     */
1574
    public static function lessThan($value, $limit, $message = null, $propertyPath = null)
1575
    {
1576
        if ($value >= $limit) {
1577
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1578
                $message ?: 'Provided "%s" is not less than "%s".',
1579
                self::stringify($value),
1580
                self::stringify($limit)
1581
            );
1582
1583
            throw static::createException($value, $message, static::INVALID_LESS, $propertyPath);
1584
        }
1585
    }
1586
1587
    /**
1588
     * Determines if the value is less or than given limit.
1589
     *
1590
     * @param mixed $value
1591
     * @param mixed $limit
1592
     * @param null  $message
1593
     * @param null  $propertyPath
1594
     */
1595
    public static function lessOrEqualThan($value, $limit, $message = null, $propertyPath = null)
1596
    {
1597
        if ($value > $limit) {
1598
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1599
                $message ?: 'Provided "%s" is not less or equal than "%s".',
1600
                self::stringify($value),
1601
                self::stringify($limit)
1602
            );
1603
1604
            throw static::createException($value, $message, static::INVALID_LESS_OR_EQUAL, $propertyPath);
1605
        }
1606
    }
1607
1608
    /**
1609
     * Determines if the value is greater than given limit.
1610
     *
1611
     * @param mixed $value
1612
     * @param mixed $limit
1613
     * @param null  $message
1614
     * @param null  $propertyPath
1615
     */
1616
    public static function greaterThan($value, $limit, $message = null, $propertyPath = null)
1617
    {
1618
        if ($value <= $limit) {
1619
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1620
                $message ?: 'Provided "%s" is not greater than "%s".',
1621
                self::stringify($value),
1622
                self::stringify($limit)
1623
            );
1624
1625
            throw static::createException($value, $message, static::INVALID_GREATER, $propertyPath);
1626
        }
1627
    }
1628
1629
    /**
1630
     * Determines if the value is greater or equal than given limit.
1631
     *
1632
     * @param mixed $value
1633
     * @param mixed $limit
1634
     * @param null  $message
1635
     * @param null  $propertyPath
1636
     */
1637
    public static function greaterOrEqualThan($value, $limit, $message = null, $propertyPath = null)
1638
    {
1639
        if ($value < $limit) {
1640
            $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1641
                $message ?: 'Provided "%s" is not greater or equal than "%s".',
1642
                self::stringify($value),
1643
                self::stringify($limit)
1644
            );
1645
1646
            throw static::createException($value, $message, static::INVALID_GREATER_OR_EQUAL, $propertyPath);
1647
        }
1648
    }
1649
1650
    /**
1651
     * Assert that date is valid and corresponds to the given format.
1652
     *
1653
     * @param string      $value
1654
     * @param string      $format supports all of the options date(), except for the following:
1655
     *                            N, w, W, t, L, o, B, a, A, g, h, I, O, P, Z, c, r.
1656
     * @param string|null $message
1657
     * @param string|null $propertyPath
1658
     *
1659
     * @link http://php.net/manual/function.date.php#refsect1-function.date-parameters
1660
     */
1661
     public static function date($value, $format, $message = null, $propertyPath = null)
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 4 spaces, found 5
Loading history...
1662
     {
1663
         static::string($value, $message, $propertyPath);
1664
         static::string($format, $message, $propertyPath);
1665
1666
         $dateTime = \DateTime::createFromFormat($format, $value);
1667
1668
         if (false === $dateTime || $value !== $dateTime->format($format)) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 9
Loading history...
1669
             $message = sprintf(
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
1670
                 $message ?: 'Date "%s" is invalid or does not match format "%s".',
1671
                 self::stringify($value),
1672
                 self::stringify($format)
1673
             );
1674
1675
             throw static::createException($value, $message, static::INVALID_DATE, $propertyPath, array('format' => $format));
1676
         }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 9
Loading history...
1677
     }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 5
Loading history...
1678
1679
    /**
1680
     * Assert that the value is callable.
1681
     *
1682
     * @param mixed $value
1683
     * @param string|null $message
1684
     * @param string|null $propertyPath
1685
     */
1686
    public static function isCallable ($value, $message = null, $propertyPath = null)
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 4
Loading history...
Coding Style introduced by
Expected "function abc(...)"; found "function abc (...)"
Loading history...
Coding Style introduced by
Expected 0 spaces before opening parenthesis; 1 found
Loading history...
1687
    {
0 ignored issues
show
Coding Style introduced by
It seems like the identation of this line is off (expected at least 8 spaces, but found 4).
Loading history...
1688
        if (!\is_callable($value)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 8
Loading history...
1689
            $message = sprintf(
1 ignored issue
show
Coding Style introduced by
Consider using a different name than the parameter $message. This often makes code more readable.
Loading history...
Coding Style introduced by
It seems like the identation of this line is off (expected at least 16 spaces, but found 12).
Loading history...
1690
                $message ?: 'Provided "%s" is callable.',
1691
                self::stringify($value)
1692
            );
1693
1694
            throw static::createException($value, $message, static::INVALID_CALLABLE, $propertyPath);
1695
        }
1696
    }
1697
1698
    /**
1699
     * Make a string version of a value.
1700
     *
1701
     * @param mixed $value
1702
     * @return string
1703
     */
1704
    protected static function stringify($value)
1705
    {
1706
        if (is_bool($value)) {
1707
            return $value ? '<TRUE>' : '<FALSE>';
1708
        }
1709
1710
        if (is_scalar($value)) {
1711
            $val = (string)$value;
1712
1713
            if (strlen($val) > 100) {
1714
                $val = substr($val, 0, 97) . '...';
1715
            }
1716
1717
            return $val;
1718
        }
1719
1720
        if (is_array($value)) {
1721
            return '<ARRAY>';
1722
        }
1723
1724
        if (is_object($value)) {
1725
            return get_class($value);
1726
        }
1727
1728
        if (is_resource($value)) {
1729
            return '<RESOURCE>';
1730
        }
1731
1732
        if ($value === NULL) {
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
1733
            return '<NULL>';
1734
        }
1735
1736
        return 'unknown';
1737
    }
1738
}
1739
1740