Version 1
[yaffs-website] / vendor / webmozart / assert / src / Assert.php
1 <?php
2
3 /*
4  * This file is part of the webmozart/assert package.
5  *
6  * (c) Bernhard Schussek <bschussek@gmail.com>
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 BadMethodCallException;
15 use InvalidArgumentException;
16 use Traversable;
17 use Exception;
18 use Throwable;
19 use Closure;
20
21 /**
22  * Efficient assertions to validate the input/output of your methods.
23  *
24  * @method static void nullOrString($value, $message = '')
25  * @method static void nullOrStringNotEmpty($value, $message = '')
26  * @method static void nullOrInteger($value, $message = '')
27  * @method static void nullOrIntegerish($value, $message = '')
28  * @method static void nullOrFloat($value, $message = '')
29  * @method static void nullOrNumeric($value, $message = '')
30  * @method static void nullOrBoolean($value, $message = '')
31  * @method static void nullOrScalar($value, $message = '')
32  * @method static void nullOrObject($value, $message = '')
33  * @method static void nullOrResource($value, $type = null, $message = '')
34  * @method static void nullOrIsCallable($value, $message = '')
35  * @method static void nullOrIsArray($value, $message = '')
36  * @method static void nullOrIsTraversable($value, $message = '')
37  * @method static void nullOrIsInstanceOf($value, $class, $message = '')
38  * @method static void nullOrNotInstanceOf($value, $class, $message = '')
39  * @method static void nullOrIsEmpty($value, $message = '')
40  * @method static void nullOrNotEmpty($value, $message = '')
41  * @method static void nullOrTrue($value, $message = '')
42  * @method static void nullOrFalse($value, $message = '')
43  * @method static void nullOrEq($value, $value2, $message = '')
44  * @method static void nullOrNotEq($value,$value2,  $message = '')
45  * @method static void nullOrSame($value, $value2, $message = '')
46  * @method static void nullOrNotSame($value, $value2, $message = '')
47  * @method static void nullOrGreaterThan($value, $value2, $message = '')
48  * @method static void nullOrGreaterThanEq($value, $value2, $message = '')
49  * @method static void nullOrLessThan($value, $value2, $message = '')
50  * @method static void nullOrLessThanEq($value, $value2, $message = '')
51  * @method static void nullOrRange($value, $min, $max, $message = '')
52  * @method static void nullOrOneOf($value, $values, $message = '')
53  * @method static void nullOrContains($value, $subString, $message = '')
54  * @method static void nullOrStartsWith($value, $prefix, $message = '')
55  * @method static void nullOrStartsWithLetter($value, $message = '')
56  * @method static void nullOrEndsWith($value, $suffix, $message = '')
57  * @method static void nullOrRegex($value, $pattern, $message = '')
58  * @method static void nullOrAlpha($value, $message = '')
59  * @method static void nullOrDigits($value, $message = '')
60  * @method static void nullOrAlnum($value, $message = '')
61  * @method static void nullOrLower($value, $message = '')
62  * @method static void nullOrUpper($value, $message = '')
63  * @method static void nullOrLength($value, $length, $message = '')
64  * @method static void nullOrMinLength($value, $min, $message = '')
65  * @method static void nullOrMaxLength($value, $max, $message = '')
66  * @method static void nullOrLengthBetween($value, $min, $max, $message = '')
67  * @method static void nullOrFileExists($value, $message = '')
68  * @method static void nullOrFile($value, $message = '')
69  * @method static void nullOrDirectory($value, $message = '')
70  * @method static void nullOrReadable($value, $message = '')
71  * @method static void nullOrWritable($value, $message = '')
72  * @method static void nullOrClassExists($value, $message = '')
73  * @method static void nullOrSubclassOf($value, $class, $message = '')
74  * @method static void nullOrImplementsInterface($value, $interface, $message = '')
75  * @method static void nullOrPropertyExists($value, $property, $message = '')
76  * @method static void nullOrPropertyNotExists($value, $property, $message = '')
77  * @method static void nullOrMethodExists($value, $method, $message = '')
78  * @method static void nullOrMethodNotExists($value, $method, $message = '')
79  * @method static void nullOrKeyExists($value, $key, $message = '')
80  * @method static void nullOrKeyNotExists($value, $key, $message = '')
81  * @method static void nullOrCount($value, $key, $message = '')
82  * @method static void nullOrUuid($values, $message = '')
83  * @method static void allString($values, $message = '')
84  * @method static void allStringNotEmpty($values, $message = '')
85  * @method static void allInteger($values, $message = '')
86  * @method static void allIntegerish($values, $message = '')
87  * @method static void allFloat($values, $message = '')
88  * @method static void allNumeric($values, $message = '')
89  * @method static void allBoolean($values, $message = '')
90  * @method static void allScalar($values, $message = '')
91  * @method static void allObject($values, $message = '')
92  * @method static void allResource($values, $type = null, $message = '')
93  * @method static void allIsCallable($values, $message = '')
94  * @method static void allIsArray($values, $message = '')
95  * @method static void allIsTraversable($values, $message = '')
96  * @method static void allIsInstanceOf($values, $class, $message = '')
97  * @method static void allNotInstanceOf($values, $class, $message = '')
98  * @method static void allNull($values, $message = '')
99  * @method static void allNotNull($values, $message = '')
100  * @method static void allIsEmpty($values, $message = '')
101  * @method static void allNotEmpty($values, $message = '')
102  * @method static void allTrue($values, $message = '')
103  * @method static void allFalse($values, $message = '')
104  * @method static void allEq($values, $value2, $message = '')
105  * @method static void allNotEq($values,$value2,  $message = '')
106  * @method static void allSame($values, $value2, $message = '')
107  * @method static void allNotSame($values, $value2, $message = '')
108  * @method static void allGreaterThan($values, $value2, $message = '')
109  * @method static void allGreaterThanEq($values, $value2, $message = '')
110  * @method static void allLessThan($values, $value2, $message = '')
111  * @method static void allLessThanEq($values, $value2, $message = '')
112  * @method static void allRange($values, $min, $max, $message = '')
113  * @method static void allOneOf($values, $values, $message = '')
114  * @method static void allContains($values, $subString, $message = '')
115  * @method static void allStartsWith($values, $prefix, $message = '')
116  * @method static void allStartsWithLetter($values, $message = '')
117  * @method static void allEndsWith($values, $suffix, $message = '')
118  * @method static void allRegex($values, $pattern, $message = '')
119  * @method static void allAlpha($values, $message = '')
120  * @method static void allDigits($values, $message = '')
121  * @method static void allAlnum($values, $message = '')
122  * @method static void allLower($values, $message = '')
123  * @method static void allUpper($values, $message = '')
124  * @method static void allLength($values, $length, $message = '')
125  * @method static void allMinLength($values, $min, $message = '')
126  * @method static void allMaxLength($values, $max, $message = '')
127  * @method static void allLengthBetween($values, $min, $max, $message = '')
128  * @method static void allFileExists($values, $message = '')
129  * @method static void allFile($values, $message = '')
130  * @method static void allDirectory($values, $message = '')
131  * @method static void allReadable($values, $message = '')
132  * @method static void allWritable($values, $message = '')
133  * @method static void allClassExists($values, $message = '')
134  * @method static void allSubclassOf($values, $class, $message = '')
135  * @method static void allImplementsInterface($values, $interface, $message = '')
136  * @method static void allPropertyExists($values, $property, $message = '')
137  * @method static void allPropertyNotExists($values, $property, $message = '')
138  * @method static void allMethodExists($values, $method, $message = '')
139  * @method static void allMethodNotExists($values, $method, $message = '')
140  * @method static void allKeyExists($values, $key, $message = '')
141  * @method static void allKeyNotExists($values, $key, $message = '')
142  * @method static void allCount($values, $key, $message = '')
143  * @method static void allUuid($values, $message = '')
144  *
145  * @since  1.0
146  *
147  * @author Bernhard Schussek <bschussek@gmail.com>
148  */
149 class Assert
150 {
151     public static function string($value, $message = '')
152     {
153         if (!is_string($value)) {
154             static::reportInvalidArgument(sprintf(
155                 $message ?: 'Expected a string. Got: %s',
156                 static::typeToString($value)
157             ));
158         }
159     }
160
161     public static function stringNotEmpty($value, $message = '')
162     {
163         static::string($value, $message);
164         static::notEmpty($value, $message);
165     }
166
167     public static function integer($value, $message = '')
168     {
169         if (!is_int($value)) {
170             static::reportInvalidArgument(sprintf(
171                 $message ?: 'Expected an integer. Got: %s',
172                 static::typeToString($value)
173             ));
174         }
175     }
176
177     public static function integerish($value, $message = '')
178     {
179         if (!is_numeric($value) || $value != (int) $value) {
180             static::reportInvalidArgument(sprintf(
181                 $message ?: 'Expected an integerish value. Got: %s',
182                 static::typeToString($value)
183             ));
184         }
185     }
186
187     public static function float($value, $message = '')
188     {
189         if (!is_float($value)) {
190             static::reportInvalidArgument(sprintf(
191                 $message ?: 'Expected a float. Got: %s',
192                 static::typeToString($value)
193             ));
194         }
195     }
196
197     public static function numeric($value, $message = '')
198     {
199         if (!is_numeric($value)) {
200             static::reportInvalidArgument(sprintf(
201                 $message ?: 'Expected a numeric. Got: %s',
202                 static::typeToString($value)
203             ));
204         }
205     }
206
207     public static function boolean($value, $message = '')
208     {
209         if (!is_bool($value)) {
210             static::reportInvalidArgument(sprintf(
211                 $message ?: 'Expected a boolean. Got: %s',
212                 static::typeToString($value)
213             ));
214         }
215     }
216
217     public static function scalar($value, $message = '')
218     {
219         if (!is_scalar($value)) {
220             static::reportInvalidArgument(sprintf(
221                 $message ?: 'Expected a scalar. Got: %s',
222                 static::typeToString($value)
223             ));
224         }
225     }
226
227     public static function object($value, $message = '')
228     {
229         if (!is_object($value)) {
230             static::reportInvalidArgument(sprintf(
231                 $message ?: 'Expected an object. Got: %s',
232                 static::typeToString($value)
233             ));
234         }
235     }
236
237     public static function resource($value, $type = null, $message = '')
238     {
239         if (!is_resource($value)) {
240             static::reportInvalidArgument(sprintf(
241                 $message ?: 'Expected a resource. Got: %s',
242                 static::typeToString($value)
243             ));
244         }
245
246         if ($type && $type !== get_resource_type($value)) {
247             static::reportInvalidArgument(sprintf(
248                 $message ?: 'Expected a resource of type %2$s. Got: %s',
249                 static::typeToString($value),
250                 $type
251             ));
252         }
253     }
254
255     public static function isCallable($value, $message = '')
256     {
257         if (!is_callable($value)) {
258             static::reportInvalidArgument(sprintf(
259                 $message ?: 'Expected a callable. Got: %s',
260                 static::typeToString($value)
261             ));
262         }
263     }
264
265     public static function isArray($value, $message = '')
266     {
267         if (!is_array($value)) {
268             static::reportInvalidArgument(sprintf(
269                 $message ?: 'Expected an array. Got: %s',
270                 static::typeToString($value)
271             ));
272         }
273     }
274
275     public static function isTraversable($value, $message = '')
276     {
277         if (!is_array($value) && !($value instanceof Traversable)) {
278             static::reportInvalidArgument(sprintf(
279                 $message ?: 'Expected a traversable. Got: %s',
280                 static::typeToString($value)
281             ));
282         }
283     }
284
285     public static function isInstanceOf($value, $class, $message = '')
286     {
287         if (!($value instanceof $class)) {
288             static::reportInvalidArgument(sprintf(
289                 $message ?: 'Expected an instance of %2$s. Got: %s',
290                 static::typeToString($value),
291                 $class
292             ));
293         }
294     }
295
296     public static function notInstanceOf($value, $class, $message = '')
297     {
298         if ($value instanceof $class) {
299             static::reportInvalidArgument(sprintf(
300                 $message ?: 'Expected an instance other than %2$s. Got: %s',
301                 static::typeToString($value),
302                 $class
303             ));
304         }
305     }
306
307     public static function isEmpty($value, $message = '')
308     {
309         if (!empty($value)) {
310             static::reportInvalidArgument(sprintf(
311                 $message ?: 'Expected an empty value. Got: %s',
312                 static::valueToString($value)
313             ));
314         }
315     }
316
317     public static function notEmpty($value, $message = '')
318     {
319         if (empty($value)) {
320             static::reportInvalidArgument(sprintf(
321                 $message ?: 'Expected a non-empty value. Got: %s',
322                 static::valueToString($value)
323             ));
324         }
325     }
326
327     public static function null($value, $message = '')
328     {
329         if (null !== $value) {
330             static::reportInvalidArgument(sprintf(
331                 $message ?: 'Expected null. Got: %s',
332                 static::valueToString($value)
333             ));
334         }
335     }
336
337     public static function notNull($value, $message = '')
338     {
339         if (null === $value) {
340             static::reportInvalidArgument(
341                 $message ?: 'Expected a value other than null.'
342             );
343         }
344     }
345
346     public static function true($value, $message = '')
347     {
348         if (true !== $value) {
349             static::reportInvalidArgument(sprintf(
350                 $message ?: 'Expected a value to be true. Got: %s',
351                 static::valueToString($value)
352             ));
353         }
354     }
355
356     public static function false($value, $message = '')
357     {
358         if (false !== $value) {
359             static::reportInvalidArgument(sprintf(
360                 $message ?: 'Expected a value to be false. Got: %s',
361                 static::valueToString($value)
362             ));
363         }
364     }
365
366     public static function eq($value, $value2, $message = '')
367     {
368         if ($value2 != $value) {
369             static::reportInvalidArgument(sprintf(
370                 $message ?: 'Expected a value equal to %2$s. Got: %s',
371                 static::valueToString($value),
372                 static::valueToString($value2)
373             ));
374         }
375     }
376
377     public static function notEq($value, $value2, $message = '')
378     {
379         if ($value2 == $value) {
380             static::reportInvalidArgument(sprintf(
381                 $message ?: 'Expected a different value than %s.',
382                 static::valueToString($value2)
383             ));
384         }
385     }
386
387     public static function same($value, $value2, $message = '')
388     {
389         if ($value2 !== $value) {
390             static::reportInvalidArgument(sprintf(
391                 $message ?: 'Expected a value identical to %2$s. Got: %s',
392                 static::valueToString($value),
393                 static::valueToString($value2)
394             ));
395         }
396     }
397
398     public static function notSame($value, $value2, $message = '')
399     {
400         if ($value2 === $value) {
401             static::reportInvalidArgument(sprintf(
402                 $message ?: 'Expected a value not identical to %s.',
403                 static::valueToString($value2)
404             ));
405         }
406     }
407
408     public static function greaterThan($value, $limit, $message = '')
409     {
410         if ($value <= $limit) {
411             static::reportInvalidArgument(sprintf(
412                 $message ?: 'Expected a value greater than %2$s. Got: %s',
413                 static::valueToString($value),
414                 static::valueToString($limit)
415             ));
416         }
417     }
418
419     public static function greaterThanEq($value, $limit, $message = '')
420     {
421         if ($value < $limit) {
422             static::reportInvalidArgument(sprintf(
423                 $message ?: 'Expected a value greater than or equal to %2$s. Got: %s',
424                 static::valueToString($value),
425                 static::valueToString($limit)
426             ));
427         }
428     }
429
430     public static function lessThan($value, $limit, $message = '')
431     {
432         if ($value >= $limit) {
433             static::reportInvalidArgument(sprintf(
434                 $message ?: 'Expected a value less than %2$s. Got: %s',
435                 static::valueToString($value),
436                 static::valueToString($limit)
437             ));
438         }
439     }
440
441     public static function lessThanEq($value, $limit, $message = '')
442     {
443         if ($value > $limit) {
444             static::reportInvalidArgument(sprintf(
445                 $message ?: 'Expected a value less than or equal to %2$s. Got: %s',
446                 static::valueToString($value),
447                 static::valueToString($limit)
448             ));
449         }
450     }
451
452     public static function range($value, $min, $max, $message = '')
453     {
454         if ($value < $min || $value > $max) {
455             static::reportInvalidArgument(sprintf(
456                 $message ?: 'Expected a value between %2$s and %3$s. Got: %s',
457                 static::valueToString($value),
458                 static::valueToString($min),
459                 static::valueToString($max)
460             ));
461         }
462     }
463
464     public static function oneOf($value, array $values, $message = '')
465     {
466         if (!in_array($value, $values, true)) {
467             static::reportInvalidArgument(sprintf(
468                 $message ?: 'Expected one of: %2$s. Got: %s',
469                 static::valueToString($value),
470                 implode(', ', array_map(array('static', 'valueToString'), $values))
471             ));
472         }
473     }
474
475     public static function contains($value, $subString, $message = '')
476     {
477         if (false === strpos($value, $subString)) {
478             static::reportInvalidArgument(sprintf(
479                 $message ?: 'Expected a value to contain %2$s. Got: %s',
480                 static::valueToString($value),
481                 static::valueToString($subString)
482             ));
483         }
484     }
485
486     public static function startsWith($value, $prefix, $message = '')
487     {
488         if (0 !== strpos($value, $prefix)) {
489             static::reportInvalidArgument(sprintf(
490                 $message ?: 'Expected a value to start with %2$s. Got: %s',
491                 static::valueToString($value),
492                 static::valueToString($prefix)
493             ));
494         }
495     }
496
497     public static function startsWithLetter($value, $message = '')
498     {
499         $valid = isset($value[0]);
500
501         if ($valid) {
502             $locale = setlocale(LC_CTYPE, 0);
503             setlocale(LC_CTYPE, 'C');
504             $valid = ctype_alpha($value[0]);
505             setlocale(LC_CTYPE, $locale);
506         }
507
508         if (!$valid) {
509             static::reportInvalidArgument(sprintf(
510                 $message ?: 'Expected a value to start with a letter. Got: %s',
511                 static::valueToString($value)
512             ));
513         }
514     }
515
516     public static function endsWith($value, $suffix, $message = '')
517     {
518         if ($suffix !== substr($value, -static::strlen($suffix))) {
519             static::reportInvalidArgument(sprintf(
520                 $message ?: 'Expected a value to end with %2$s. Got: %s',
521                 static::valueToString($value),
522                 static::valueToString($suffix)
523             ));
524         }
525     }
526
527     public static function regex($value, $pattern, $message = '')
528     {
529         if (!preg_match($pattern, $value)) {
530             static::reportInvalidArgument(sprintf(
531                 $message ?: 'The value %s does not match the expected pattern.',
532                 static::valueToString($value)
533             ));
534         }
535     }
536
537     public static function alpha($value, $message = '')
538     {
539         $locale = setlocale(LC_CTYPE, 0);
540         setlocale(LC_CTYPE, 'C');
541         $valid = !ctype_alpha($value);
542         setlocale(LC_CTYPE, $locale);
543
544         if ($valid) {
545             static::reportInvalidArgument(sprintf(
546                 $message ?: 'Expected a value to contain only letters. Got: %s',
547                 static::valueToString($value)
548             ));
549         }
550     }
551
552     public static function digits($value, $message = '')
553     {
554         $locale = setlocale(LC_CTYPE, 0);
555         setlocale(LC_CTYPE, 'C');
556         $valid = !ctype_digit($value);
557         setlocale(LC_CTYPE, $locale);
558
559         if ($valid) {
560             static::reportInvalidArgument(sprintf(
561                 $message ?: 'Expected a value to contain digits only. Got: %s',
562                 static::valueToString($value)
563             ));
564         }
565     }
566
567     public static function alnum($value, $message = '')
568     {
569         $locale = setlocale(LC_CTYPE, 0);
570         setlocale(LC_CTYPE, 'C');
571         $valid = !ctype_alnum($value);
572         setlocale(LC_CTYPE, $locale);
573
574         if ($valid) {
575             static::reportInvalidArgument(sprintf(
576                 $message ?: 'Expected a value to contain letters and digits only. Got: %s',
577                 static::valueToString($value)
578             ));
579         }
580     }
581
582     public static function lower($value, $message = '')
583     {
584         $locale = setlocale(LC_CTYPE, 0);
585         setlocale(LC_CTYPE, 'C');
586         $valid = !ctype_lower($value);
587         setlocale(LC_CTYPE, $locale);
588
589         if ($valid) {
590             static::reportInvalidArgument(sprintf(
591                 $message ?: 'Expected a value to contain lowercase characters only. Got: %s',
592                 static::valueToString($value)
593             ));
594         }
595     }
596
597     public static function upper($value, $message = '')
598     {
599         $locale = setlocale(LC_CTYPE, 0);
600         setlocale(LC_CTYPE, 'C');
601         $valid = !ctype_upper($value);
602         setlocale(LC_CTYPE, $locale);
603
604         if ($valid) {
605             static::reportInvalidArgument(sprintf(
606                 $message ?: 'Expected a value to contain uppercase characters only. Got: %s',
607                 static::valueToString($value)
608             ));
609         }
610     }
611
612     public static function length($value, $length, $message = '')
613     {
614         if ($length !== static::strlen($value)) {
615             static::reportInvalidArgument(sprintf(
616                 $message ?: 'Expected a value to contain %2$s characters. Got: %s',
617                 static::valueToString($value),
618                 $length
619             ));
620         }
621     }
622
623     public static function minLength($value, $min, $message = '')
624     {
625         if (static::strlen($value) < $min) {
626             static::reportInvalidArgument(sprintf(
627                 $message ?: 'Expected a value to contain at least %2$s characters. Got: %s',
628                 static::valueToString($value),
629                 $min
630             ));
631         }
632     }
633
634     public static function maxLength($value, $max, $message = '')
635     {
636         if (static::strlen($value) > $max) {
637             static::reportInvalidArgument(sprintf(
638                 $message ?: 'Expected a value to contain at most %2$s characters. Got: %s',
639                 static::valueToString($value),
640                 $max
641             ));
642         }
643     }
644
645     public static function lengthBetween($value, $min, $max, $message = '')
646     {
647         $length = static::strlen($value);
648
649         if ($length < $min || $length > $max) {
650             static::reportInvalidArgument(sprintf(
651                 $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s',
652                 static::valueToString($value),
653                 $min,
654                 $max
655             ));
656         }
657     }
658
659     public static function fileExists($value, $message = '')
660     {
661         static::string($value);
662
663         if (!file_exists($value)) {
664             static::reportInvalidArgument(sprintf(
665                 $message ?: 'The file %s does not exist.',
666                 static::valueToString($value)
667             ));
668         }
669     }
670
671     public static function file($value, $message = '')
672     {
673         static::fileExists($value, $message);
674
675         if (!is_file($value)) {
676             static::reportInvalidArgument(sprintf(
677                 $message ?: 'The path %s is not a file.',
678                 static::valueToString($value)
679             ));
680         }
681     }
682
683     public static function directory($value, $message = '')
684     {
685         static::fileExists($value, $message);
686
687         if (!is_dir($value)) {
688             static::reportInvalidArgument(sprintf(
689                 $message ?: 'The path %s is no directory.',
690                 static::valueToString($value)
691             ));
692         }
693     }
694
695     public static function readable($value, $message = '')
696     {
697         if (!is_readable($value)) {
698             static::reportInvalidArgument(sprintf(
699                 $message ?: 'The path %s is not readable.',
700                 static::valueToString($value)
701             ));
702         }
703     }
704
705     public static function writable($value, $message = '')
706     {
707         if (!is_writable($value)) {
708             static::reportInvalidArgument(sprintf(
709                 $message ?: 'The path %s is not writable.',
710                 static::valueToString($value)
711             ));
712         }
713     }
714
715     public static function classExists($value, $message = '')
716     {
717         if (!class_exists($value)) {
718             static::reportInvalidArgument(sprintf(
719                 $message ?: 'Expected an existing class name. Got: %s',
720                 static::valueToString($value)
721             ));
722         }
723     }
724
725     public static function subclassOf($value, $class, $message = '')
726     {
727         if (!is_subclass_of($value, $class)) {
728             static::reportInvalidArgument(sprintf(
729                 $message ?: 'Expected a sub-class of %2$s. Got: %s',
730                 static::valueToString($value),
731                 static::valueToString($class)
732             ));
733         }
734     }
735
736     public static function implementsInterface($value, $interface, $message = '')
737     {
738         if (!in_array($interface, class_implements($value))) {
739             static::reportInvalidArgument(sprintf(
740                 $message ?: 'Expected an implementation of %2$s. Got: %s',
741                 static::valueToString($value),
742                 static::valueToString($interface)
743             ));
744         }
745     }
746
747     public static function propertyExists($classOrObject, $property, $message = '')
748     {
749         if (!property_exists($classOrObject, $property)) {
750             static::reportInvalidArgument(sprintf(
751                 $message ?: 'Expected the property %s to exist.',
752                 static::valueToString($property)
753             ));
754         }
755     }
756
757     public static function propertyNotExists($classOrObject, $property, $message = '')
758     {
759         if (property_exists($classOrObject, $property)) {
760             static::reportInvalidArgument(sprintf(
761                 $message ?: 'Expected the property %s to not exist.',
762                 static::valueToString($property)
763             ));
764         }
765     }
766
767     public static function methodExists($classOrObject, $method, $message = '')
768     {
769         if (!method_exists($classOrObject, $method)) {
770             static::reportInvalidArgument(sprintf(
771                 $message ?: 'Expected the method %s to exist.',
772                 static::valueToString($method)
773             ));
774         }
775     }
776
777     public static function methodNotExists($classOrObject, $method, $message = '')
778     {
779         if (method_exists($classOrObject, $method)) {
780             static::reportInvalidArgument(sprintf(
781                 $message ?: 'Expected the method %s to not exist.',
782                 static::valueToString($method)
783             ));
784         }
785     }
786
787     public static function keyExists($array, $key, $message = '')
788     {
789         if (!array_key_exists($key, $array)) {
790             static::reportInvalidArgument(sprintf(
791                 $message ?: 'Expected the key %s to exist.',
792                 static::valueToString($key)
793             ));
794         }
795     }
796
797     public static function keyNotExists($array, $key, $message = '')
798     {
799         if (array_key_exists($key, $array)) {
800             static::reportInvalidArgument(sprintf(
801                 $message ?: 'Expected the key %s to not exist.',
802                 static::valueToString($key)
803             ));
804         }
805     }
806
807     public static function count($array, $number, $message = '')
808     {
809         static::eq(
810             count($array),
811             $number,
812             $message ?: sprintf('Expected an array to contain %d elements. Got: %d.', $number, count($array))
813         );
814     }
815
816     public static function uuid($value, $message = '')
817     {
818         $value = str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
819
820         // The nil UUID is special form of UUID that is specified to have all
821         // 128 bits set to zero.
822         if ('00000000-0000-0000-0000-000000000000' === $value) {
823             return;
824         }
825
826         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)) {
827             static::reportInvalidArgument(sprintf(
828                 $message ?: 'Value %s is not a valid UUID.',
829                 static::valueToString($value)
830             ));
831         }
832     }
833
834     public static function throws(Closure $expression, $class = 'Exception', $message = '')
835     {
836         static::string($class);
837
838         $actual = 'none';
839         try {
840             $expression();
841         } catch (Exception $e) {
842             $actual = get_class($e);
843             if ($e instanceof $class) {
844                 return;
845             }
846         } catch (Throwable $e) {
847             $actual = get_class($e);
848             if ($e instanceof $class) {
849                 return;
850             }
851         }
852
853         static::reportInvalidArgument($message ?: sprintf(
854             'Expected to throw "%s", got "%s"',
855             $class,
856             $actual
857         ));
858     }
859
860     public static function __callStatic($name, $arguments)
861     {
862         if ('nullOr' === substr($name, 0, 6)) {
863             if (null !== $arguments[0]) {
864                 $method = lcfirst(substr($name, 6));
865                 call_user_func_array(array('static', $method), $arguments);
866             }
867
868             return;
869         }
870
871         if ('all' === substr($name, 0, 3)) {
872             static::isTraversable($arguments[0]);
873
874             $method = lcfirst(substr($name, 3));
875             $args = $arguments;
876
877             foreach ($arguments[0] as $entry) {
878                 $args[0] = $entry;
879
880                 call_user_func_array(array('static', $method), $args);
881             }
882
883             return;
884         }
885
886         throw new BadMethodCallException('No such method: '.$name);
887     }
888
889     protected static function valueToString($value)
890     {
891         if (null === $value) {
892             return 'null';
893         }
894
895         if (true === $value) {
896             return 'true';
897         }
898
899         if (false === $value) {
900             return 'false';
901         }
902
903         if (is_array($value)) {
904             return 'array';
905         }
906
907         if (is_object($value)) {
908             return get_class($value);
909         }
910
911         if (is_resource($value)) {
912             return 'resource';
913         }
914
915         if (is_string($value)) {
916             return '"'.$value.'"';
917         }
918
919         return (string) $value;
920     }
921
922     protected static function typeToString($value)
923     {
924         return is_object($value) ? get_class($value) : gettype($value);
925     }
926
927     protected static function strlen($value)
928     {
929         if (!function_exists('mb_detect_encoding')) {
930             return strlen($value);
931         }
932
933         if (false === $encoding = mb_detect_encoding($value)) {
934             return strlen($value);
935         }
936
937         return mb_strwidth($value, $encoding);
938     }
939
940     protected static function reportInvalidArgument($message)
941     {
942         throw new InvalidArgumentException($message);
943     }
944
945     private function __construct()
946     {
947     }
948 }