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 |
||
43 | class Assert |
||
44 | { |
||
45 | /** @var Assert */ |
||
46 | protected static $validator; |
||
47 | |||
48 | /** @var string */ |
||
49 | protected $name; |
||
50 | |||
51 | /** @var int|float|bool|string|resource|array|null */ |
||
52 | protected $value; |
||
53 | |||
54 | /** |
||
55 | * Creates validator instance for variable, first fail check will throw an exception |
||
56 | * |
||
57 | * @param int|float|string|resource|array|null $value |
||
58 | * @param string $name |
||
59 | * @return static |
||
60 | * @throws InvalidNotObjectException |
||
61 | * @throws InvalidStringException |
||
62 | */ |
||
63 | 118 | public static function assert($value, $name = 'value') |
|
64 | { |
||
65 | 118 | if (is_object($value)) { |
|
66 | 1 | throw new InvalidNotObjectException($name); |
|
67 | } |
||
68 | |||
69 | 117 | if (!is_string($name)) { |
|
70 | 1 | throw new InvalidStringException('name', $name); |
|
71 | } |
||
72 | |||
73 | 116 | if (empty(self::$validator)) { |
|
74 | 1 | self::$validator = new static; |
|
75 | 1 | } |
|
76 | |||
77 | 116 | self::$validator->name = $name; |
|
78 | 116 | self::$validator->value = $value; |
|
79 | |||
80 | 116 | return self::$validator; |
|
81 | } |
||
82 | |||
83 | /** |
||
84 | * Return current validation value |
||
85 | * |
||
86 | * @return int|float|string|resource|array |
||
1 ignored issue
–
show
|
|||
87 | */ |
||
88 | 5 | public function get() |
|
92 | |||
93 | /** |
||
94 | * @param \Closure $callback (Assert $value) |
||
95 | * @return $this |
||
96 | * @throws InvalidArrayException |
||
97 | * @throws InvalidIntException |
||
98 | */ |
||
99 | 4 | public function forList(\Closure $callback) |
|
100 | { |
||
101 | 4 | if (!is_array($this->value)) { |
|
102 | 1 | throw new InvalidArrayException($this->name, $this->value); |
|
103 | } |
||
104 | |||
105 | 3 | if (empty($this->value)) { |
|
106 | 1 | return $this; |
|
107 | } |
||
108 | |||
109 | 2 | $valueAssert = clone self::$validator; |
|
110 | |||
111 | 2 | foreach ($this->value as $key => $value) { |
|
112 | 2 | $valueAssert->value = $value; |
|
113 | 2 | $valueAssert->name = sprintf("%s[%s]", $this->name, $key); |
|
114 | |||
115 | 2 | $callback($valueAssert); |
|
116 | 1 | } |
|
117 | |||
118 | 1 | return $this; |
|
119 | } |
||
120 | |||
121 | /** |
||
122 | * @param \Closure $callback (Assert $key, Assert $value) |
||
123 | * @return $this |
||
124 | * @throws InvalidArrayException |
||
125 | */ |
||
126 | 5 | public function forMap(\Closure $callback) |
|
127 | { |
||
128 | 5 | if (!is_array($this->value)) { |
|
129 | 1 | throw new InvalidArrayException($this->name, $this->value); |
|
130 | } |
||
131 | |||
132 | 4 | if (empty($this->value)) { |
|
133 | 1 | return $this; |
|
134 | } |
||
135 | |||
136 | 3 | $keyAssert = clone self::$validator; |
|
137 | 3 | $valueAssert = clone self::$validator; |
|
138 | |||
139 | 3 | foreach ($this->value as $key => $value) { |
|
140 | 3 | $keyAssert->value = $key; |
|
141 | 3 | $valueAssert->value = $value; |
|
142 | |||
143 | 3 | $keyAssert->name = sprintf("%s: key '%s'", $this->name, $key); |
|
144 | 3 | $valueAssert->name = sprintf("%s['%s']", $this->name, $key); |
|
145 | |||
146 | 3 | $callback($keyAssert, $valueAssert); |
|
147 | 1 | } |
|
148 | |||
149 | 1 | return $this; |
|
150 | } |
||
151 | |||
152 | /** |
||
153 | * @param int $length |
||
154 | * @return $this |
||
155 | * @throws InvalidIntException |
||
156 | * @throws InvalidStringLengthException |
||
157 | * @throws NumberNotPositiveException |
||
158 | * @throws InvalidStringException |
||
159 | */ |
||
160 | 5 | public function length($length) |
|
176 | |||
177 | /** |
||
178 | * Soft check if value has length $from <= $length <= to. Runs only after string validation |
||
179 | * |
||
180 | * @param int $from |
||
181 | * @param int $to |
||
182 | * @return $this |
||
183 | * @throws InvalidIntException |
||
184 | * @throws LengthNotBetweenException |
||
185 | * @throws NumberNotPositiveException |
||
186 | * @throws NumberNotGreaterException |
||
187 | * @throws NumberNotLessException |
||
188 | * @throws InvalidStringException |
||
189 | */ |
||
190 | 7 | public function lengthBetween($from, $to) |
|
214 | |||
215 | /** |
||
216 | * Soft check if value has length less than $length. Runs only after string validation |
||
217 | * |
||
218 | * @param int $length |
||
219 | * @return $this |
||
220 | * @throws InvalidIntException |
||
221 | * @throws LengthNotLessException |
||
222 | * @throws NumberNotPositiveException |
||
223 | * @throws InvalidStringException |
||
224 | */ |
||
225 | 5 | public function lengthLess($length) |
|
241 | |||
242 | /** |
||
243 | * Soft check if value has length less than $length. Runs only after notEmpty and string validations |
||
244 | * |
||
245 | * @param int $length |
||
246 | * @return $this |
||
247 | * @throws InvalidIntException |
||
248 | * @throws LengthNotGreaterException |
||
249 | * @throws NumberNotPositiveException |
||
250 | * @throws InvalidStringException |
||
251 | */ |
||
252 | 5 | public function lengthGreater($length) |
|
268 | |||
269 | /** |
||
270 | * Check if value is in array (in_array strict) |
||
271 | * |
||
272 | * @param array $range |
||
273 | * @return $this |
||
274 | * @throws InvalidArrayException |
||
275 | * @throws InvalidNotEmptyException |
||
276 | * @throws ValueNotInArrayException |
||
277 | */ |
||
278 | 4 | public function inArray($range) |
|
279 | { |
||
280 | 4 | if (!is_array($range)) { |
|
281 | 1 | throw new InvalidArrayException('range', $range); |
|
282 | 3 | } elseif (empty($range)) { |
|
283 | 1 | throw new InvalidNotEmptyException('range'); |
|
284 | } |
||
285 | |||
286 | 2 | if (!in_array($this->value, $range, true)) { |
|
287 | 1 | throw new ValueNotInArrayException($this->name, $this->value, $range); |
|
288 | } |
||
289 | |||
290 | 1 | return $this; |
|
291 | } |
||
292 | |||
293 | /** |
||
294 | * Check if value is array |
||
295 | * |
||
296 | * @return $this |
||
297 | * @throws InvalidArrayException |
||
298 | */ |
||
299 | 2 | public function isArray() |
|
307 | |||
308 | /** |
||
309 | * Soft check that $from <= value <= $to |
||
310 | * |
||
311 | * @param float|int $from |
||
312 | * @param float|int $to |
||
313 | * @return $this |
||
314 | * @throws NumberNotBetweenException |
||
315 | * @throws InvalidIntOrFloatException |
||
316 | * @throws NumberNotLessStrictlyException |
||
317 | */ |
||
318 | 6 | public function between($from, $to) |
|
336 | |||
337 | /** |
||
338 | * Strict check that $from < value < $to |
||
339 | * |
||
340 | * @param float|int $from |
||
341 | * @param float|int $to |
||
342 | * @return $this |
||
343 | * @throws InvalidIntOrFloatException |
||
344 | * @throws NumberNotBetweenStrictlyException |
||
345 | * @throws NumberNotLessStrictlyException |
||
346 | */ |
||
347 | 6 | public function betweenStrict($from, $to) |
|
365 | |||
366 | /** |
||
367 | * Check if value is boolean (is_bool) |
||
368 | * |
||
369 | * @return $this |
||
370 | * @throws InvalidBoolException |
||
371 | */ |
||
372 | 2 | public function bool() |
|
380 | |||
381 | /** |
||
382 | * Check if value is digit (ctype_digit) |
||
383 | * |
||
384 | * @return $this |
||
385 | * @throws InvalidDigitException |
||
386 | * @throws InvalidStringException |
||
387 | */ |
||
388 | 3 | public function digit() |
|
398 | |||
399 | /** |
||
400 | * Check if value is empty (empty) |
||
401 | * |
||
402 | * @return $this |
||
403 | * @throws InvalidEmptyException |
||
404 | */ |
||
405 | 2 | public function isEmpty() |
|
413 | |||
414 | /** |
||
415 | * Check if value is not empty (empty) |
||
416 | * |
||
417 | * @return $this |
||
418 | * @throws InvalidNotEmptyException |
||
419 | */ |
||
420 | 2 | public function notEmpty() |
|
428 | |||
429 | /** |
||
430 | * Check if value is float (is_float) |
||
431 | * |
||
432 | * @return $this |
||
433 | * @throws InvalidFloatException |
||
434 | */ |
||
435 | 2 | public function float() |
|
443 | |||
444 | /** |
||
445 | * Check if value is integer (is_int) |
||
446 | * |
||
447 | * @return $this |
||
448 | * @throws InvalidIntException |
||
449 | */ |
||
450 | 7 | public function int() |
|
458 | |||
459 | /** |
||
460 | * Soft check that value <= $max |
||
461 | * |
||
462 | * @param float|int $number |
||
463 | * @return $this |
||
464 | * @throws InvalidIntOrFloatException |
||
465 | * @throws NumberNotLessException |
||
466 | */ |
||
467 | 4 | public function less($number) |
|
481 | |||
482 | /** |
||
483 | * Soft check that value >= $min |
||
484 | * |
||
485 | * @param float|int $number |
||
486 | * @return $this |
||
487 | * @throws NumberNotGreaterException |
||
488 | * @throws InvalidIntOrFloatException |
||
489 | */ |
||
490 | 4 | public function greater($number) |
|
504 | |||
505 | /** |
||
506 | * Strict check that value < $max |
||
507 | * |
||
508 | * @param float|int $number |
||
509 | * @return $this |
||
510 | * @throws InvalidIntOrFloatException |
||
511 | * @throws NumberNotLessStrictlyException |
||
512 | */ |
||
513 | 4 | public function lessStrict($number) |
|
527 | |||
528 | /** |
||
529 | * Strict check that value > $min |
||
530 | * |
||
531 | * @param float|int $number |
||
532 | * @return $this |
||
533 | * @throws InvalidIntOrFloatException |
||
534 | * @throws NumberNotGreaterStrictlyException |
||
535 | */ |
||
536 | 4 | public function greaterStrict($number) |
|
550 | |||
551 | /** |
||
552 | * Check if value match regexp pattern |
||
553 | * |
||
554 | * @param string $pattern |
||
555 | * @return $this |
||
556 | * @throws InvalidNotEmptyException |
||
557 | * @throws InvalidRegexpPatternException |
||
558 | * @throws InvalidStringException |
||
559 | * @throws StringNotMatchRegExpException |
||
560 | */ |
||
561 | 6 | public function match($pattern) |
|
562 | { |
||
563 | 6 | if (!is_string($pattern)) { |
|
564 | 1 | throw new InvalidStringException('pattern', $pattern); |
|
565 | 5 | } elseif (empty($pattern)) { |
|
566 | 1 | throw new InvalidNotEmptyException('pattern'); |
|
567 | } |
||
568 | |||
569 | 4 | if (!is_string($this->value)) { |
|
570 | 1 | throw new InvalidStringException($this->name, $this->value); |
|
571 | } |
||
572 | |||
573 | // God please sorry for this @ |
||
574 | 3 | $checkResult = @preg_match($pattern, $this->value); |
|
575 | |||
576 | 3 | if ((preg_last_error() !== PREG_NO_ERROR) || ($checkResult === false)) { |
|
577 | 1 | throw new InvalidRegExpPatternException('pattern', $pattern); |
|
578 | } |
||
579 | |||
580 | 2 | if ($checkResult === 0) { |
|
581 | 1 | throw new StringNotMatchRegExpException($this->name, $this->value, $pattern); |
|
582 | } |
||
583 | |||
584 | 1 | return $this; |
|
585 | } |
||
586 | |||
587 | /** |
||
588 | * Check if value match glob pattern |
||
589 | * |
||
590 | * @param string $pattern |
||
591 | * @return $this |
||
592 | * @throws InvalidNotEmptyException |
||
593 | * @throws InvalidStringException |
||
594 | * @throws StringNotMatchGlobException |
||
595 | */ |
||
596 | 5 | public function glob($pattern) |
|
597 | { |
||
598 | 5 | if (!is_string($pattern)) { |
|
599 | 1 | throw new InvalidStringException('pattern', $pattern); |
|
600 | 4 | } elseif (empty($pattern)) { |
|
601 | 1 | throw new InvalidNotEmptyException('pattern'); |
|
602 | } |
||
603 | |||
604 | 3 | if (!is_string($this->value)) { |
|
605 | 1 | throw new InvalidStringException($this->name, $this->value); |
|
606 | 2 | } elseif (!fnmatch($pattern, $this->value)) { |
|
607 | 1 | throw new StringNotMatchGlobException($this->name, $this->value, $pattern); |
|
608 | } |
||
609 | |||
610 | 1 | return $this; |
|
611 | } |
||
612 | |||
613 | /** |
||
614 | * Check if value < 0 |
||
615 | * |
||
616 | * @return $this |
||
617 | * @throws InvalidIntOrFloatException |
||
618 | * @throws NumberNotNegativeException |
||
619 | */ |
||
620 | 3 | public function negative() |
|
630 | |||
631 | /** |
||
632 | * Check if value > 0 |
||
633 | * |
||
634 | * @return $this |
||
635 | * @throws InvalidIntOrFloatException |
||
636 | * @throws NumberNotPositiveException |
||
637 | */ |
||
638 | 3 | public function positive() |
|
648 | |||
649 | /** |
||
650 | * Check if value is null |
||
651 | * |
||
652 | * @return $this |
||
653 | * @throws InvalidNullException |
||
654 | */ |
||
655 | 2 | public function isNull() |
|
663 | |||
664 | /** |
||
665 | * Check if value is not null |
||
666 | * |
||
667 | * @return $this |
||
668 | * @throws InvalidNotNullException |
||
669 | */ |
||
670 | 2 | public function notNull() |
|
678 | |||
679 | /** |
||
680 | * Check if value is numeric (is_numeric) |
||
681 | * |
||
682 | * @return $this |
||
683 | * @throws InvalidIntOrFloatOrStringException |
||
684 | * @throws InvalidNumericException |
||
685 | */ |
||
686 | 3 | public function numeric() |
|
696 | |||
697 | /** |
||
698 | * Check if value is resource (is_resource) |
||
699 | * |
||
700 | * @return $this |
||
701 | * @throws InvalidResourceException |
||
702 | */ |
||
703 | 2 | public function resource() |
|
711 | |||
712 | /** |
||
713 | * Check if value is string (is_string) |
||
714 | * |
||
715 | * @return $this |
||
716 | * @throws InvalidStringException |
||
717 | */ |
||
718 | 3 | public function string() |
|
726 | |||
727 | /** |
||
728 | * Cast value to bool |
||
729 | * |
||
730 | * @return $this |
||
731 | */ |
||
732 | 1 | public function toBool() |
|
738 | |||
739 | /** |
||
740 | * Cast value to float. If it's not numeric - there will be fail cast |
||
741 | * |
||
742 | * @return $this |
||
743 | * @throws InvalidNotArrayException |
||
744 | * @throws InvalidNumericException |
||
745 | */ |
||
746 | 3 | public function toFloat() |
|
758 | |||
759 | /** |
||
760 | * Cast value to int. If it's not numeric - there will be fail cast |
||
761 | * |
||
762 | * @return $this |
||
763 | * @throws InvalidNotArrayException |
||
764 | * @throws InvalidNumericException |
||
765 | */ |
||
766 | 3 | public function toInt() |
|
778 | |||
779 | /** |
||
780 | * Cast value to string. If it's array - there will be fail cast |
||
781 | * |
||
782 | * @return $this |
||
783 | * @throws InvalidNotArrayException |
||
784 | */ |
||
785 | 2 | public function toString() |
|
795 | } |
||
796 |
This check compares the return type specified in the
@return
annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.If the return type contains the type array, this check recommends the use of a more specific type like
String[]
orarray<String>
.