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
arrayas a return type and suggests a more specific type. This type is inferred from the actual code.