Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Assert often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Assert, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
191 | class Assert |
||
|
|||
192 | { |
||
193 | 94 | public static function string($value, $message = '') |
|
202 | |||
203 | 16 | public static function stringNotEmpty($value, $message = '') |
|
208 | |||
209 | 17 | public static function integer($value, $message = '') |
|
218 | |||
219 | 16 | public static function integerish($value, $message = '') |
|
228 | |||
229 | 16 | public static function float($value, $message = '') |
|
238 | |||
239 | 20 | public static function numeric($value, $message = '') |
|
248 | |||
249 | 24 | public static function natural($value, $message = '') |
|
250 | { |
||
251 | 24 | if (!is_int($value) || $value < 0) { |
|
252 | 16 | static::reportInvalidArgument(sprintf( |
|
253 | 16 | $message ?: 'Expected a non-negative integer. Got %s', |
|
254 | 16 | static::valueToString($value) |
|
255 | )); |
||
256 | } |
||
257 | 8 | } |
|
258 | |||
259 | 16 | public static function boolean($value, $message = '') |
|
268 | |||
269 | 23 | public static function scalar($value, $message = '') |
|
278 | |||
279 | 23 | public static function object($value, $message = '') |
|
288 | |||
289 | 16 | public static function resource($value, $type = null, $message = '') |
|
306 | |||
307 | 20 | public static function isCallable($value, $message = '') |
|
316 | |||
317 | 20 | public static function isArray($value, $message = '') |
|
326 | |||
327 | /** |
||
328 | * @deprecated |
||
329 | */ |
||
330 | 20 | public static function isTraversable($value, $message = '') |
|
331 | { |
||
332 | 20 | @trigger_error( |
|
333 | 20 | sprintf( |
|
334 | 20 | 'The "%s" assertion is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "isIterable" or "isInstanceOf" instead.', |
|
335 | 20 | __METHOD__ |
|
336 | ), |
||
337 | 20 | E_USER_DEPRECATED |
|
338 | ); |
||
339 | |||
340 | 20 | if (!is_array($value) && !($value instanceof Traversable)) { |
|
341 | 8 | static::reportInvalidArgument(sprintf( |
|
342 | 8 | $message ?: 'Expected a traversable. Got: %s', |
|
343 | 8 | static::typeToString($value) |
|
344 | )); |
||
345 | } |
||
346 | 12 | } |
|
347 | |||
348 | 20 | View Code Duplication | public static function isArrayAccessible($value, $message = '') |
357 | |||
358 | 24 | View Code Duplication | public static function isCountable($value, $message = '') |
367 | |||
368 | 864 | View Code Duplication | public static function isIterable($value, $message = '') |
377 | |||
378 | 16 | public static function isInstanceOf($value, $class, $message = '') |
|
388 | |||
389 | 16 | public static function notInstanceOf($value, $class, $message = '') |
|
399 | |||
400 | 20 | public static function isInstanceOfAny($value, array $classes, $message = '') |
|
414 | |||
415 | 23 | public static function isEmpty($value, $message = '') |
|
424 | |||
425 | 23 | public static function notEmpty($value, $message = '') |
|
434 | |||
435 | 11 | public static function null($value, $message = '') |
|
436 | { |
||
437 | 11 | if (null !== $value) { |
|
438 | 8 | static::reportInvalidArgument(sprintf( |
|
439 | 8 | $message ?: 'Expected null. Got: %s', |
|
440 | 8 | static::valueToString($value) |
|
441 | )); |
||
442 | } |
||
443 | 3 | } |
|
444 | |||
445 | 11 | public static function notNull($value, $message = '') |
|
453 | |||
454 | 15 | public static function true($value, $message = '') |
|
455 | { |
||
456 | 15 | if (true !== $value) { |
|
457 | 11 | static::reportInvalidArgument(sprintf( |
|
458 | 11 | $message ?: 'Expected a value to be true. Got: %s', |
|
459 | 11 | static::valueToString($value) |
|
460 | )); |
||
461 | } |
||
462 | 4 | } |
|
463 | |||
464 | 19 | public static function false($value, $message = '') |
|
465 | { |
||
466 | 19 | if (false !== $value) { |
|
467 | 15 | static::reportInvalidArgument(sprintf( |
|
468 | 15 | $message ?: 'Expected a value to be false. Got: %s', |
|
469 | 15 | static::valueToString($value) |
|
470 | )); |
||
471 | } |
||
472 | 4 | } |
|
473 | |||
474 | 47 | View Code Duplication | public static function ip($value, $message = '') |
483 | |||
484 | 47 | View Code Duplication | public static function ipv4($value, $message = '') |
493 | |||
494 | 47 | View Code Duplication | public static function ipv6($value, $message = '') |
503 | |||
504 | 16 | View Code Duplication | public static function email($value, $message = '') |
505 | { |
||
506 | 16 | if (false === filter_var($value, FILTER_VALIDATE_EMAIL)) { |
|
507 | 12 | static::reportInvalidArgument(sprintf( |
|
508 | 12 | $message ?: 'Expected a value to be a valid e-mail address. Got %s', |
|
509 | 12 | static::valueToString($value) |
|
510 | )); |
||
511 | } |
||
512 | 4 | } |
|
513 | |||
514 | 12 | public static function uniqueValues(array $values, $message = '') |
|
515 | { |
||
516 | 12 | $allValues = count($values); |
|
517 | 12 | $uniqueValues = count(array_unique($values)); |
|
518 | |||
519 | 12 | if ($allValues !== $uniqueValues) { |
|
520 | 8 | $difference = $allValues - $uniqueValues; |
|
521 | |||
522 | 8 | static::reportInvalidArgument(sprintf( |
|
523 | 8 | $message ?: 'Expected an array of unique values, but %s of them %s duplicated', |
|
524 | $difference, |
||
525 | 8 | (1 === $difference ? 'is' : 'are') |
|
526 | )); |
||
527 | } |
||
528 | 4 | } |
|
529 | |||
530 | 33 | public static function eq($value, $expect, $message = '') |
|
531 | { |
||
532 | 33 | if ($expect != $value) { |
|
533 | 17 | static::reportInvalidArgument(sprintf( |
|
534 | 17 | $message ?: 'Expected a value equal to %2$s. Got: %s', |
|
535 | 17 | static::valueToString($value), |
|
536 | 17 | static::valueToString($expect) |
|
537 | )); |
||
538 | } |
||
539 | 16 | } |
|
540 | |||
541 | 28 | public static function notEq($value, $expect, $message = '') |
|
542 | { |
||
543 | 28 | if ($expect == $value) { |
|
544 | 16 | static::reportInvalidArgument(sprintf( |
|
545 | 16 | $message ?: 'Expected a different value than %s.', |
|
546 | 16 | static::valueToString($expect) |
|
547 | )); |
||
548 | } |
||
549 | 12 | } |
|
550 | |||
551 | 16 | public static function same($value, $expect, $message = '') |
|
552 | { |
||
553 | 16 | if ($expect !== $value) { |
|
554 | 12 | static::reportInvalidArgument(sprintf( |
|
555 | 12 | $message ?: 'Expected a value identical to %2$s. Got: %s', |
|
556 | 12 | static::valueToString($value), |
|
557 | 12 | static::valueToString($expect) |
|
558 | )); |
||
559 | } |
||
560 | 4 | } |
|
561 | |||
562 | 16 | public static function notSame($value, $expect, $message = '') |
|
563 | { |
||
564 | 16 | if ($expect === $value) { |
|
565 | 4 | static::reportInvalidArgument(sprintf( |
|
566 | 4 | $message ?: 'Expected a value not identical to %s.', |
|
567 | 4 | static::valueToString($expect) |
|
568 | )); |
||
569 | } |
||
570 | 12 | } |
|
571 | |||
572 | 8 | public static function greaterThan($value, $limit, $message = '') |
|
573 | { |
||
574 | 8 | if ($value <= $limit) { |
|
575 | 4 | static::reportInvalidArgument(sprintf( |
|
576 | 4 | $message ?: 'Expected a value greater than %2$s. Got: %s', |
|
577 | 4 | static::valueToString($value), |
|
578 | 4 | static::valueToString($limit) |
|
579 | )); |
||
580 | } |
||
581 | 4 | } |
|
582 | |||
583 | 12 | public static function greaterThanEq($value, $limit, $message = '') |
|
584 | { |
||
585 | 12 | if ($value < $limit) { |
|
586 | 4 | static::reportInvalidArgument(sprintf( |
|
587 | 4 | $message ?: 'Expected a value greater than or equal to %2$s. Got: %s', |
|
588 | 4 | static::valueToString($value), |
|
589 | 4 | static::valueToString($limit) |
|
590 | )); |
||
591 | } |
||
592 | 8 | } |
|
593 | |||
594 | 8 | public static function lessThan($value, $limit, $message = '') |
|
595 | { |
||
596 | 8 | if ($value >= $limit) { |
|
597 | 4 | static::reportInvalidArgument(sprintf( |
|
598 | 4 | $message ?: 'Expected a value less than %2$s. Got: %s', |
|
599 | 4 | static::valueToString($value), |
|
600 | 4 | static::valueToString($limit) |
|
601 | )); |
||
602 | } |
||
603 | 4 | } |
|
604 | |||
605 | 12 | public static function lessThanEq($value, $limit, $message = '') |
|
606 | { |
||
607 | 12 | if ($value > $limit) { |
|
608 | 4 | static::reportInvalidArgument(sprintf( |
|
609 | 4 | $message ?: 'Expected a value less than or equal to %2$s. Got: %s', |
|
610 | 4 | static::valueToString($value), |
|
611 | 4 | static::valueToString($limit) |
|
612 | )); |
||
613 | } |
||
614 | 8 | } |
|
615 | |||
616 | 16 | View Code Duplication | public static function range($value, $min, $max, $message = '') |
617 | { |
||
618 | 16 | if ($value < $min || $value > $max) { |
|
619 | 8 | static::reportInvalidArgument(sprintf( |
|
620 | 8 | $message ?: 'Expected a value between %2$s and %3$s. Got: %s', |
|
621 | 8 | static::valueToString($value), |
|
622 | 8 | static::valueToString($min), |
|
623 | 8 | static::valueToString($max) |
|
624 | )); |
||
625 | } |
||
626 | 8 | } |
|
627 | |||
628 | 8 | public static function oneOf($value, array $values, $message = '') |
|
629 | { |
||
630 | 8 | if (!in_array($value, $values, true)) { |
|
631 | 4 | static::reportInvalidArgument(sprintf( |
|
632 | 4 | $message ?: 'Expected one of: %2$s. Got: %s', |
|
633 | 4 | static::valueToString($value), |
|
634 | 4 | implode(', ', array_map(array('static', 'valueToString'), $values)) |
|
635 | )); |
||
636 | } |
||
637 | 4 | } |
|
638 | |||
639 | 80 | View Code Duplication | public static function contains($value, $subString, $message = '') |
640 | { |
||
641 | 80 | if (false === strpos($value, $subString)) { |
|
642 | 32 | static::reportInvalidArgument(sprintf( |
|
643 | 32 | $message ?: 'Expected a value to contain %2$s. Got: %s', |
|
644 | 32 | static::valueToString($value), |
|
645 | 32 | static::valueToString($subString) |
|
646 | )); |
||
647 | } |
||
648 | 48 | } |
|
649 | |||
650 | 80 | View Code Duplication | public static function notContains($value, $subString, $message = '') |
651 | { |
||
652 | 80 | if (false !== strpos($value, $subString)) { |
|
653 | 48 | static::reportInvalidArgument(sprintf( |
|
654 | 48 | $message ?: '%2$s was not expected to be contained in a value. Got: %s', |
|
655 | 48 | static::valueToString($value), |
|
656 | 48 | static::valueToString($subString) |
|
657 | )); |
||
658 | } |
||
659 | 32 | } |
|
660 | |||
661 | 40 | public static function notWhitespaceOnly($value, $message = '') |
|
662 | { |
||
663 | 40 | if (preg_match('/^\s*$/', $value)) { |
|
664 | 24 | static::reportInvalidArgument(sprintf( |
|
665 | 24 | $message ?: 'Expected a non-whitespace string. Got: %s', |
|
666 | 24 | static::valueToString($value) |
|
667 | )); |
||
668 | } |
||
669 | 16 | } |
|
670 | |||
671 | 48 | View Code Duplication | public static function startsWith($value, $prefix, $message = '') |
672 | { |
||
673 | 48 | if (0 !== strpos($value, $prefix)) { |
|
674 | 32 | static::reportInvalidArgument(sprintf( |
|
675 | 32 | $message ?: 'Expected a value to start with %2$s. Got: %s', |
|
676 | 32 | static::valueToString($value), |
|
677 | 32 | static::valueToString($prefix) |
|
678 | )); |
||
679 | } |
||
680 | 16 | } |
|
681 | |||
682 | 24 | public static function startsWithLetter($value, $message = '') |
|
683 | { |
||
684 | 24 | $valid = isset($value[0]); |
|
685 | |||
686 | 24 | if ($valid) { |
|
687 | 20 | $locale = setlocale(LC_CTYPE, 0); |
|
688 | 20 | setlocale(LC_CTYPE, 'C'); |
|
689 | 20 | $valid = ctype_alpha($value[0]); |
|
690 | 20 | setlocale(LC_CTYPE, $locale); |
|
691 | } |
||
692 | |||
693 | 24 | if (!$valid) { |
|
694 | 12 | static::reportInvalidArgument(sprintf( |
|
695 | 12 | $message ?: 'Expected a value to start with a letter. Got: %s', |
|
696 | 12 | static::valueToString($value) |
|
697 | )); |
||
698 | } |
||
699 | 12 | } |
|
700 | |||
701 | 48 | public static function endsWith($value, $suffix, $message = '') |
|
702 | { |
||
703 | 48 | if ($suffix !== substr($value, -strlen($suffix))) { |
|
704 | 32 | static::reportInvalidArgument(sprintf( |
|
705 | 32 | $message ?: 'Expected a value to end with %2$s. Got: %s', |
|
706 | 32 | static::valueToString($value), |
|
707 | 32 | static::valueToString($suffix) |
|
708 | )); |
||
709 | } |
||
710 | 16 | } |
|
711 | |||
712 | 12 | public static function regex($value, $pattern, $message = '') |
|
713 | { |
||
714 | 12 | if (!preg_match($pattern, $value)) { |
|
715 | 8 | static::reportInvalidArgument(sprintf( |
|
716 | 8 | $message ?: 'The value %s does not match the expected pattern.', |
|
717 | 8 | static::valueToString($value) |
|
718 | )); |
||
719 | } |
||
720 | 4 | } |
|
721 | |||
722 | 12 | public static function notRegex($value, $pattern, $message = '') |
|
723 | { |
||
724 | 12 | if (preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) { |
|
725 | 4 | static::reportInvalidArgument(sprintf( |
|
726 | 4 | $message ?: 'The value %s matches the pattern %s (at offset %d).', |
|
727 | 4 | static::valueToString($value), |
|
728 | 4 | static::valueToString($pattern), |
|
729 | 4 | $matches[0][1] |
|
730 | )); |
||
731 | } |
||
732 | 8 | } |
|
733 | |||
734 | 12 | View Code Duplication | public static function alpha($value, $message = '') |
748 | |||
749 | 12 | View Code Duplication | public static function digits($value, $message = '') |
763 | |||
764 | 12 | View Code Duplication | public static function alnum($value, $message = '') |
778 | |||
779 | 16 | View Code Duplication | public static function lower($value, $message = '') |
793 | |||
794 | 16 | View Code Duplication | public static function upper($value, $message = '') |
808 | |||
809 | 36 | public static function length($value, $length, $message = '') |
|
819 | |||
820 | 36 | public static function minLength($value, $min, $message = '') |
|
821 | { |
||
822 | 36 | if (static::strlen($value) < $min) { |
|
823 | 12 | static::reportInvalidArgument(sprintf( |
|
824 | 12 | $message ?: 'Expected a value to contain at least %2$s characters. Got: %s', |
|
825 | 12 | static::valueToString($value), |
|
826 | $min |
||
827 | )); |
||
828 | } |
||
829 | 24 | } |
|
830 | |||
831 | 36 | public static function maxLength($value, $max, $message = '') |
|
832 | { |
||
833 | 36 | if (static::strlen($value) > $max) { |
|
834 | 12 | static::reportInvalidArgument(sprintf( |
|
835 | 12 | $message ?: 'Expected a value to contain at most %2$s characters. Got: %s', |
|
836 | 12 | static::valueToString($value), |
|
837 | $max |
||
838 | )); |
||
839 | } |
||
840 | 24 | } |
|
841 | |||
842 | 60 | View Code Duplication | public static function lengthBetween($value, $min, $max, $message = '') |
855 | |||
856 | 36 | public static function fileExists($value, $message = '') |
|
867 | |||
868 | 12 | View Code Duplication | public static function file($value, $message = '') |
879 | |||
880 | 12 | View Code Duplication | public static function directory($value, $message = '') |
891 | |||
892 | public static function readable($value, $message = '') |
||
893 | { |
||
894 | if (!is_readable($value)) { |
||
895 | static::reportInvalidArgument(sprintf( |
||
896 | $message ?: 'The path %s is not readable.', |
||
897 | static::valueToString($value) |
||
898 | )); |
||
899 | } |
||
900 | } |
||
901 | |||
902 | public static function writable($value, $message = '') |
||
903 | { |
||
904 | if (!is_writable($value)) { |
||
905 | static::reportInvalidArgument(sprintf( |
||
906 | $message ?: 'The path %s is not writable.', |
||
907 | static::valueToString($value) |
||
908 | )); |
||
909 | } |
||
910 | } |
||
911 | |||
912 | 8 | public static function classExists($value, $message = '') |
|
913 | { |
||
914 | 8 | if (!class_exists($value)) { |
|
915 | 4 | static::reportInvalidArgument(sprintf( |
|
916 | 4 | $message ?: 'Expected an existing class name. Got: %s', |
|
917 | 4 | static::valueToString($value) |
|
918 | )); |
||
919 | } |
||
920 | 4 | } |
|
921 | |||
922 | 8 | public static function subclassOf($value, $class, $message = '') |
|
932 | |||
933 | 8 | public static function interfaceExists($value, $message = '') |
|
934 | { |
||
935 | 8 | if (!interface_exists($value)) { |
|
936 | 4 | static::reportInvalidArgument(sprintf( |
|
937 | 4 | $message ?: 'Expected an existing interface name. got %s', |
|
938 | 4 | static::valueToString($value) |
|
939 | )); |
||
940 | } |
||
941 | 4 | } |
|
942 | |||
943 | 8 | public static function implementsInterface($value, $interface, $message = '') |
|
944 | { |
||
945 | 8 | if (!in_array($interface, class_implements($value))) { |
|
946 | 4 | static::reportInvalidArgument(sprintf( |
|
947 | 4 | $message ?: 'Expected an implementation of %2$s. Got: %s', |
|
948 | 4 | static::valueToString($value), |
|
949 | 4 | static::valueToString($interface) |
|
950 | )); |
||
951 | } |
||
952 | 4 | } |
|
953 | |||
954 | 12 | View Code Duplication | public static function propertyExists($classOrObject, $property, $message = '') |
963 | |||
964 | 12 | View Code Duplication | public static function propertyNotExists($classOrObject, $property, $message = '') |
973 | |||
974 | 27 | View Code Duplication | public static function methodExists($classOrObject, $method, $message = '') |
983 | |||
984 | 27 | View Code Duplication | public static function methodNotExists($classOrObject, $method, $message = '') |
993 | |||
994 | 12 | View Code Duplication | public static function keyExists($array, $key, $message = '') |
1003 | |||
1004 | 12 | View Code Duplication | public static function keyNotExists($array, $key, $message = '') |
1013 | |||
1014 | 8 | public static function count($array, $number, $message = '') |
|
1022 | |||
1023 | 12 | View Code Duplication | public static function minCount($array, $min, $message = '') |
1033 | |||
1034 | 12 | View Code Duplication | public static function maxCount($array, $max, $message = '') |
1044 | |||
1045 | 20 | public static function countBetween($array, $min, $max, $message = '') |
|
1058 | |||
1059 | 24 | public static function isList($array, $message = '') |
|
1067 | |||
1068 | 16 | public static function isMap($array, $message = '') |
|
1069 | { |
||
1070 | if ( |
||
1071 | 16 | !is_array($array) || |
|
1072 | 16 | !$array || |
|
1073 | array_keys($array) !== array_filter(array_keys($array), function ($key) { |
||
1074 | 12 | return is_string($key); |
|
1075 | 16 | }) |
|
1076 | ) { |
||
1077 | 12 | static::reportInvalidArgument( |
|
1078 | 12 | $message ?: 'Expected map - associative array with string keys.' |
|
1079 | ); |
||
1080 | } |
||
1081 | 4 | } |
|
1082 | |||
1083 | 56 | public static function uuid($value, $message = '') |
|
1100 | |||
1101 | 24 | public static function throws(Closure $expression, $class = 'Exception', $message = '') |
|
1127 | |||
1128 | 1361 | public static function __callStatic($name, $arguments) |
|
1156 | |||
1157 | 678 | protected static function valueToString($value) |
|
1193 | |||
1194 | 169 | protected static function typeToString($value) |
|
1198 | |||
1199 | 168 | protected static function strlen($value) |
|
1211 | |||
1212 | 902 | protected static function reportInvalidArgument($message) |
|
1216 | |||
1217 | private function __construct() |
||
1220 | } |
||
1221 |