Complex classes like DataParser 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 DataParser, and based on these observations, apply Extract Interface, too.
1 | <?php declare (strict_types = 1); |
||
53 | class DataParser implements JsonApiDataParserInterface |
||
54 | { |
||
55 | use RelationshipRulesTrait, ClassIsTrait; |
||
56 | |||
57 | /** Rule description index */ |
||
58 | const RULE_INDEX = 0; |
||
59 | |||
60 | /** Rule description index */ |
||
61 | const RULE_ATTRIBUTES = self::RULE_INDEX + 1; |
||
62 | |||
63 | /** Rule description index */ |
||
64 | const RULE_TO_ONE = self::RULE_ATTRIBUTES + 1; |
||
65 | |||
66 | /** Rule description index */ |
||
67 | const RULE_TO_MANY = self::RULE_TO_ONE + 1; |
||
68 | |||
69 | /** Rule description index */ |
||
70 | const RULE_UNLISTED_ATTRIBUTE = self::RULE_TO_MANY + 1; |
||
71 | |||
72 | /** Rule description index */ |
||
73 | const RULE_UNLISTED_RELATIONSHIP = self::RULE_UNLISTED_ATTRIBUTE + 1; |
||
74 | |||
75 | /** |
||
76 | * NOTE: Despite the type it is just a string so only static methods can be called from the interface. |
||
77 | * |
||
78 | * @var JsonApiDataRulesSerializerInterface|string |
||
79 | */ |
||
80 | private $serializerClass; |
||
81 | |||
82 | /** |
||
83 | * @var int|null |
||
84 | */ |
||
85 | private $errorStatus; |
||
86 | |||
87 | /** |
||
88 | * @var ContextStorageInterface |
||
89 | */ |
||
90 | private $context; |
||
91 | |||
92 | /** |
||
93 | * @var JsonApiErrorCollection |
||
94 | */ |
||
95 | private $jsonApiErrors; |
||
96 | |||
97 | /** |
||
98 | * @var array |
||
99 | */ |
||
100 | private $blocks; |
||
101 | |||
102 | /** |
||
103 | * @var array |
||
104 | */ |
||
105 | private $idRule; |
||
106 | |||
107 | /** |
||
108 | * @var array |
||
109 | */ |
||
110 | private $typeRule; |
||
111 | |||
112 | /** |
||
113 | * @var int[] |
||
114 | */ |
||
115 | private $attributeRules; |
||
116 | |||
117 | /** |
||
118 | * @var int[] |
||
119 | */ |
||
120 | private $toOneRules; |
||
121 | |||
122 | /** |
||
123 | * @var int[] |
||
124 | */ |
||
125 | private $toManyRules; |
||
126 | |||
127 | /** |
||
128 | * @var bool |
||
129 | */ |
||
130 | private $isIgnoreUnknowns; |
||
131 | |||
132 | /** |
||
133 | * @var FormatterInterface|null |
||
134 | */ |
||
135 | private $formatter; |
||
136 | |||
137 | /** |
||
138 | * @var FormatterFactoryInterface |
||
139 | */ |
||
140 | private $formatterFactory; |
||
141 | |||
142 | /** |
||
143 | * @var ErrorAggregatorInterface |
||
144 | */ |
||
145 | private $errorAggregator; |
||
146 | |||
147 | /** |
||
148 | * @var CaptureAggregatorInterface |
||
149 | */ |
||
150 | private $captureAggregator; |
||
151 | |||
152 | /** |
||
153 | * @param string $rulesClass |
||
154 | 30 | * @param string $serializerClass |
|
155 | * @param array $serializedData |
||
156 | * @param ContextStorageInterface $context |
||
157 | * @param JsonApiErrorCollection $jsonErrors |
||
158 | * @param FormatterFactoryInterface $formatterFactory |
||
159 | * |
||
160 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
161 | */ |
||
162 | public function __construct( |
||
191 | |||
192 | /** |
||
193 | 8 | * @inheritdoc |
|
194 | */ |
||
195 | public function assert(array $jsonData): JsonApiDataParserInterface |
||
203 | 17 | ||
204 | /** |
||
205 | * @inheritdoc |
||
206 | 17 | * |
|
207 | 17 | * @SuppressWarnings(PHPMD.ElseExpression) |
|
208 | 17 | */ |
|
209 | 17 | public function parse(array $input): bool |
|
223 | 9 | ||
224 | /** |
||
225 | 9 | * @inheritdoc |
|
226 | 9 | * |
|
227 | 9 | * @SuppressWarnings(PHPMD.ElseExpression) |
|
228 | */ |
||
229 | 9 | public function parseRelationship(string $index, string $name, array $jsonData): bool |
|
272 | |||
273 | 9 | /** |
|
274 | 4 | * @inheritdoc |
|
275 | 4 | */ |
|
276 | public function assertRelationship( |
||
288 | |||
289 | /** |
||
290 | * @inheritdoc |
||
291 | */ |
||
292 | 16 | public function getErrors(): array |
|
296 | |||
297 | /** |
||
298 | * @inheritdoc |
||
299 | */ |
||
300 | 26 | public function getCaptures(): array |
|
304 | 26 | ||
305 | /** |
||
306 | 26 | * @return self |
|
307 | */ |
||
308 | protected function resetAggregators(): self |
||
316 | 30 | ||
317 | 30 | /** |
|
318 | 30 | * @param string $serializerClass |
|
319 | * |
||
320 | * @return self |
||
321 | 30 | */ |
|
322 | protected function setSerializerClass(string $serializerClass): self |
||
330 | |||
331 | 30 | /** |
|
332 | * @return JsonApiDataRulesSerializerInterface|string |
||
333 | */ |
||
334 | protected function getSerializer() |
||
338 | |||
339 | /** |
||
340 | * @param array $jsonData |
||
341 | * |
||
342 | 17 | * @return self |
|
343 | * |
||
344 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
345 | 17 | * @SuppressWarnings(PHPMD.ElseExpression) |
|
346 | */ |
||
347 | 17 | private function validateType(array $jsonData): self |
|
382 | |||
383 | /** |
||
384 | * @param array $jsonData |
||
385 | 17 | * |
|
386 | * @return self |
||
387 | * |
||
388 | 17 | * @SuppressWarnings(PHPMD.StaticAccess) |
|
389 | */ |
||
390 | private function validateId(array $jsonData): self |
||
419 | |||
420 | /** |
||
421 | * @param array $jsonData |
||
422 | * |
||
423 | 17 | * @return self |
|
424 | * |
||
425 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
426 | 17 | * @SuppressWarnings(PHPMD.ElseExpression) |
|
427 | */ |
||
428 | 17 | private function validateAttributes(array $jsonData): self |
|
473 | |||
474 | /** |
||
475 | * @param array $jsonData |
||
476 | * |
||
477 | 17 | * @return self |
|
478 | * |
||
479 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
480 | 17 | * @SuppressWarnings(PHPMD.ElseExpression) |
|
481 | 17 | */ |
|
482 | 17 | private function validateRelationships(array $jsonData): self |
|
541 | |||
542 | /** |
||
543 | * @param int $index |
||
544 | * @param string $name |
||
545 | * @param mixed $mightBeRelationship |
||
546 | 11 | * |
|
547 | * @return void |
||
548 | 11 | * |
|
549 | 11 | * @SuppressWarnings(PHPMD.ElseExpression) |
|
550 | 11 | */ |
|
551 | private function validateAsToOneRelationship(int $index, string $name, $mightBeRelationship): void |
||
567 | |||
568 | /** |
||
569 | * @param int $index |
||
570 | * @param string $name |
||
571 | * @param mixed $mightBeRelationship |
||
572 | 13 | * |
|
573 | * @return void |
||
574 | 13 | * |
|
575 | 13 | * @SuppressWarnings(PHPMD.ElseExpression) |
|
576 | 13 | */ |
|
577 | 13 | private function validateAsToManyRelationship(int $index, string $name, $mightBeRelationship): void |
|
609 | |||
610 | /** |
||
611 | * @param mixed $data |
||
612 | 15 | * |
|
613 | * @return array|null|false Either `array` ($type => $id), or `null`, or `false` on error. |
||
|
|||
614 | 15 | * |
|
615 | 2 | * @SuppressWarnings(PHPMD.ElseExpression) |
|
616 | 13 | */ |
|
617 | 13 | private function parseSingleRelationship($data) |
|
634 | |||
635 | /** |
||
636 | * @param mixed $input |
||
637 | * @param int $index |
||
638 | 24 | * |
|
639 | * @return void |
||
640 | 24 | * |
|
641 | 24 | * @SuppressWarnings(PHPMD.StaticAccess) |
|
642 | 24 | */ |
|
643 | 24 | private function executeBlock($input, int $index): void |
|
654 | |||
655 | /** |
||
656 | * @param array $indexes |
||
657 | 25 | * |
|
658 | * @return void |
||
659 | 25 | * |
|
660 | 1 | * @SuppressWarnings(PHPMD.StaticAccess) |
|
661 | 1 | */ |
|
662 | 1 | private function executeStarts(array $indexes): void |
|
673 | |||
674 | /** |
||
675 | * @param array $indexes |
||
676 | 25 | * |
|
677 | * @return void |
||
678 | 25 | * |
|
679 | 5 | * @SuppressWarnings(PHPMD.StaticAccess) |
|
680 | 5 | */ |
|
681 | 5 | private function executeEnds(array $indexes): void |
|
692 | |||
693 | 3 | /** |
|
694 | * @param ErrorInterface $error |
||
695 | 3 | * |
|
696 | * @return string |
||
697 | 3 | */ |
|
698 | private function getMessage(ErrorInterface $error): string |
||
704 | |||
705 | 17 | /** |
|
706 | * @return array |
||
707 | */ |
||
708 | protected function getIdRule(): array |
||
712 | |||
713 | 17 | /** |
|
714 | * @return array |
||
715 | */ |
||
716 | protected function getTypeRule(): array |
||
720 | |||
721 | 26 | /** |
|
722 | * @return ContextStorageInterface |
||
723 | */ |
||
724 | protected function getContext(): ContextStorageInterface |
||
728 | |||
729 | 30 | /** |
|
730 | * @param ContextStorageInterface $context |
||
731 | 30 | * |
|
732 | * @return self |
||
733 | 30 | */ |
|
734 | protected function setContext(ContextStorageInterface $context): self |
||
740 | |||
741 | 26 | /** |
|
742 | * @return JsonApiErrorCollection |
||
743 | */ |
||
744 | protected function getJsonApiErrorCollection(): JsonApiErrorCollection |
||
748 | |||
749 | 30 | /** |
|
750 | * @param JsonApiErrorCollection $errors |
||
751 | 30 | * |
|
752 | * @return self |
||
753 | 30 | */ |
|
754 | protected function setJsonApiErrors(JsonApiErrorCollection $errors): self |
||
760 | |||
761 | 1 | /** |
|
762 | * @return bool |
||
763 | */ |
||
764 | protected function isIgnoreUnknowns(): bool |
||
768 | |||
769 | 1 | /** |
|
770 | * @return self |
||
771 | 1 | */ |
|
772 | protected function enableIgnoreUnknowns(): self |
||
778 | |||
779 | 30 | /** |
|
780 | * @return self |
||
781 | 30 | */ |
|
782 | protected function disableIgnoreUnknowns(): self |
||
788 | |||
789 | 5 | /** |
|
790 | * @return int |
||
791 | 5 | */ |
|
792 | private function getErrorStatus(): int |
||
798 | |||
799 | /** |
||
800 | * @param int $status |
||
801 | */ |
||
802 | private function addErrorStatus(int $status): void |
||
824 | |||
825 | 30 | /** |
|
826 | * @param array $rules |
||
827 | 30 | * |
|
828 | * @return self |
||
829 | 30 | */ |
|
830 | private function setAttributeRules(array $rules): self |
||
838 | |||
839 | 30 | /** |
|
840 | * @param array $rules |
||
841 | 30 | * |
|
842 | * @return self |
||
843 | 30 | */ |
|
844 | private function setToOneIndexes(array $rules): self |
||
852 | |||
853 | 30 | /** |
|
854 | * @param array $rules |
||
855 | 30 | * |
|
856 | * @return self |
||
857 | 30 | */ |
|
858 | private function setToManyIndexes(array $rules): self |
||
866 | |||
867 | 17 | /** |
|
868 | * @return int[] |
||
869 | */ |
||
870 | protected function getAttributeRules(): array |
||
874 | |||
875 | 26 | /** |
|
876 | * @return int[] |
||
877 | */ |
||
878 | protected function getToOneRules(): array |
||
882 | |||
883 | 23 | /** |
|
884 | * @return int[] |
||
885 | */ |
||
886 | protected function getToManyRules(): array |
||
890 | |||
891 | 28 | /** |
|
892 | * @return array |
||
893 | */ |
||
894 | private function getBlocks(): array |
||
898 | |||
899 | 9 | /** |
|
900 | 9 | * @return FormatterInterface |
|
901 | */ |
||
902 | protected function getFormatter(): FormatterInterface |
||
910 | |||
911 | 30 | /** |
|
912 | * @param FormatterFactoryInterface $formatterFactory |
||
913 | 30 | * |
|
914 | * @return self |
||
915 | 30 | */ |
|
916 | protected function setFormatterFactory(FormatterFactoryInterface $formatterFactory): self |
||
922 | |||
923 | /** |
||
924 | * @param string $name |
||
925 | 10 | * |
|
926 | * @return int|null |
||
927 | 10 | * |
|
928 | 10 | * @SuppressWarnings(PHPMD.StaticAccess) |
|
929 | */ |
||
930 | 10 | private function getAttributeIndex(string $name): ?int |
|
937 | |||
938 | /** |
||
939 | 9 | * @param string $defaultMessage |
|
940 | * @param array $args |
||
941 | 9 | * |
|
942 | * @return string |
||
943 | 9 | */ |
|
944 | private function formatMessage(string $defaultMessage, array $args = []): string |
||
950 | |||
951 | 26 | /** |
|
952 | * @return ErrorAggregatorInterface |
||
953 | */ |
||
954 | private function getErrorAggregator(): ErrorAggregatorInterface |
||
958 | |||
959 | 26 | /** |
|
960 | * @return CaptureAggregatorInterface |
||
961 | */ |
||
962 | private function getCaptureAggregator(): CaptureAggregatorInterface |
||
966 | |||
967 | /** |
||
968 | * @param array $rules |
||
969 | 30 | * |
|
970 | * @return bool |
||
971 | 30 | * |
|
972 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
973 | 30 | */ |
|
974 | 30 | private function debugCheckIndexesExist(array $rules): bool |
|
990 | } |
||
991 |
This check looks for the generic type
array
as a return type and suggests a more specific type. This type is inferred from the actual code.