Complex classes like ResultBuilder 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 ResultBuilder, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
41 | class ResultBuilder { |
||
42 | |||
43 | /** |
||
44 | * @var ApiResult |
||
45 | */ |
||
46 | private $result; |
||
47 | |||
48 | /** |
||
49 | * @var EntityTitleLookup |
||
50 | */ |
||
51 | private $entityTitleLookup; |
||
52 | |||
53 | /** |
||
54 | * @var SerializerFactory |
||
55 | */ |
||
56 | private $serializerFactory; |
||
57 | |||
58 | /** |
||
59 | * @var Serializer |
||
60 | */ |
||
61 | private $entitySerializer; |
||
62 | |||
63 | /** |
||
64 | * @var SiteLookup |
||
65 | */ |
||
66 | private $siteLookup; |
||
67 | |||
68 | /** |
||
69 | * @var PropertyDataTypeLookup |
||
70 | */ |
||
71 | private $dataTypeLookup; |
||
72 | |||
73 | /** |
||
74 | * @var bool|null when special elements such as '_element' are needed by the formatter. |
||
75 | */ |
||
76 | private $addMetaData; |
||
77 | |||
78 | /** |
||
79 | * @var SerializationModifier |
||
80 | */ |
||
81 | private $modifier; |
||
82 | |||
83 | /** |
||
84 | * @var CallbackFactory |
||
85 | */ |
||
86 | private $callbackFactory; |
||
87 | |||
88 | /** |
||
89 | * @var int |
||
90 | */ |
||
91 | private $missingEntityCounter = -1; |
||
92 | |||
93 | /** |
||
94 | * @var JsonDataTypeInjector |
||
95 | */ |
||
96 | private $dataTypeInjector; |
||
97 | |||
98 | /** |
||
99 | * @param ApiResult $result |
||
100 | * @param EntityTitleLookup $entityTitleLookup |
||
101 | * @param SerializerFactory $serializerFactory |
||
102 | * @param Serializer $entitySerializer |
||
103 | * @param SiteLookup $siteLookup |
||
104 | * @param PropertyDataTypeLookup $dataTypeLookup |
||
105 | * @param bool|null $addMetaData when special elements such as '_element' are needed |
||
106 | */ |
||
107 | public function __construct( |
||
133 | |||
134 | /** |
||
135 | * Mark the ApiResult as successful. |
||
136 | * |
||
137 | * { "success": 1 } |
||
138 | * |
||
139 | * @param bool|int|null $success |
||
140 | */ |
||
141 | public function markSuccess( $success = true ) { |
||
152 | |||
153 | /** |
||
154 | * Adds a list of values for the given path and name. |
||
155 | * This automatically sets the indexed tag name, if appropriate. |
||
156 | * |
||
157 | * To set atomic values or records, use setValue() or appendValue(). |
||
158 | * |
||
159 | * @see ApiResult::addValue |
||
160 | * @see ApiResult::setIndexedTagName |
||
161 | * @see ResultBuilder::setValue() |
||
162 | * @see ResultBuilder::appendValue() |
||
163 | * |
||
164 | * @param array|string|null $path |
||
165 | * @param string $name |
||
166 | * @param array $values |
||
167 | * @param string $tag tag name to use for elements of $values if not already present |
||
168 | */ |
||
169 | public function setList( $path, $name, array $values, $tag ) { |
||
185 | |||
186 | /** |
||
187 | * Set an atomic value (or record) for the given path and name. |
||
188 | * If the value is an array, it should be a record (associative), not a list. |
||
189 | * For adding lists, use setList(). |
||
190 | * |
||
191 | * @see ResultBuilder::setList() |
||
192 | * @see ResultBuilder::appendValue() |
||
193 | * @see ApiResult::addValue |
||
194 | * |
||
195 | * @param array|string|null $path |
||
196 | * @param string $name |
||
197 | * @param mixed $value |
||
198 | */ |
||
199 | public function setValue( $path, $name, $value ) { |
||
206 | |||
207 | /** |
||
208 | * Appends a value to the list at the given path. |
||
209 | * This automatically sets the indexed tag name, if appropriate. |
||
210 | * |
||
211 | * If the value is an array, it should be associative, not a list. |
||
212 | * For adding lists, use setList(). |
||
213 | * |
||
214 | * @see ResultBuilder::setList() |
||
215 | * @see ResultBuilder::setValue() |
||
216 | * @see ApiResult::addValue |
||
217 | * @see ApiResult::setIndexedTagName_internal |
||
218 | * |
||
219 | * @param array|string|null $path |
||
220 | * @param int|string|null $key the key to use when appending, or null for automatic. |
||
221 | * May be ignored even if given, based on $this->addMetaData. |
||
222 | * @param mixed $value |
||
223 | * @param string $tag tag name to use for $value in indexed mode |
||
224 | */ |
||
225 | public function appendValue( $path, $key, $value, $tag ) { |
||
236 | |||
237 | /** |
||
238 | * @param array|string|null $path |
||
239 | */ |
||
240 | private function checkPathType( $path ) { |
||
247 | |||
248 | /** |
||
249 | * @param int|string|null $key the key to use when appending, or null for automatic. |
||
250 | */ |
||
251 | private function checkKeyType( $key ) { |
||
258 | |||
259 | /** |
||
260 | * @param mixed $value |
||
261 | */ |
||
262 | private function checkValueIsNotList( $value ) { |
||
269 | |||
270 | /** |
||
271 | * Get serialized entity for the EntityRevision and add it to the result alongside other needed properties. |
||
272 | * |
||
273 | * |
||
274 | * @param string|null $sourceEntityIdSerialization EntityId used to retrieve $entityRevision |
||
275 | * Used as the key for the entity in the 'entities' structure and for adding redirect |
||
276 | * info Will default to the entity's serialized ID if null. If given this must be the |
||
277 | * entity id before any redirects were resolved. |
||
278 | * @param EntityRevision $entityRevision |
||
279 | * @param string[]|string $props a list of fields to include, or "all" |
||
280 | * @param string[]|null $filterSiteIds A list of site IDs to filter by |
||
281 | * @param string[] $filterLangCodes A list of language codes to filter by |
||
282 | * @param TermLanguageFallbackChain[] $termFallbackChains with keys of the origional language |
||
283 | */ |
||
284 | public function addEntityRevision( |
||
336 | |||
337 | private function addEntityInfoToRecord( array $record, EntityId $entityId ): array { |
||
342 | |||
343 | private function addPageInfoToRecord( array $record, EntityRevision $entityRevision ): array { |
||
352 | |||
353 | private function addEntityRedirectInfoToRecord( array $record, $sourceEntityIdSerialization, EntityId $entityId ): array { |
||
360 | |||
361 | /** |
||
362 | * Gets the standard serialization of an EntityDocument and modifies it in a standard way. |
||
363 | * |
||
364 | * This code was created for Items and Properties and since new entity types have been introduced |
||
365 | * it may not work in the desired way. |
||
366 | * @see https://phabricator.wikimedia.org/T249206 |
||
367 | * |
||
368 | * @see ResultBuilder::addEntityRevision |
||
369 | * |
||
370 | * @param EntityDocument $entity |
||
371 | * @param array|string $props |
||
372 | * @param string[]|null $filterSiteIds |
||
373 | * @param string[] $filterLangCodes |
||
374 | * @param TermLanguageFallbackChain[] $termFallbackChains |
||
375 | * |
||
376 | * @return array |
||
377 | */ |
||
378 | private function getModifiedEntityArray( |
||
409 | |||
410 | /** |
||
411 | * @param array $serialization |
||
412 | * @param string|array $props |
||
413 | * |
||
414 | * @return array |
||
415 | */ |
||
416 | private function filterEntitySerializationUsingProps( array $serialization, $props ) { |
||
436 | |||
437 | private function injectEntitySerializationWithSiteLinkUrls( array $serialization ) { |
||
443 | |||
444 | private function sortEntitySerializationSiteLinks( array $serialization ) { |
||
450 | |||
451 | private function filterEntitySerializationUsingSiteIds( |
||
464 | |||
465 | /** |
||
466 | * @param array $serialization |
||
467 | * @param TermLanguageFallbackChain[] $termFallbackChains |
||
468 | * |
||
469 | * @return array |
||
470 | */ |
||
471 | private function addEntitySerializationFallbackInfo( |
||
491 | |||
492 | /** |
||
493 | * @param array $serialization |
||
494 | * @param TermLanguageFallbackChain[] $termFallbackChains |
||
495 | * |
||
496 | * @return array |
||
497 | */ |
||
498 | private function getTermsSerializationWithFallbackInfo( |
||
520 | |||
521 | /** |
||
522 | * @param array $serialization |
||
523 | * @param string[] $langCodes |
||
524 | * |
||
525 | * @return array |
||
526 | */ |
||
527 | private function filterEntitySerializationUsingLangCodes( |
||
556 | |||
557 | private function getEntitySerializationWithMetaData( array $serialization ) { |
||
620 | |||
621 | /** |
||
622 | * Get serialized information for the EntityId and add them to result |
||
623 | * |
||
624 | * @param EntityId $entityId |
||
625 | * @param string|array|null $path |
||
626 | */ |
||
627 | public function addBasicEntityInformation( EntityId $entityId, $path ) { |
||
631 | |||
632 | /** |
||
633 | * Get serialized labels and add them to result |
||
634 | * |
||
635 | * @param TermList $labels the labels to insert in the result |
||
636 | * @param array|string $path where the data is located |
||
637 | */ |
||
638 | public function addLabels( TermList $labels, $path ) { |
||
641 | |||
642 | /** |
||
643 | * Adds fake serialization to show a label has been removed |
||
644 | * |
||
645 | * @param string $language |
||
646 | * @param array|string $path where the data is located |
||
647 | */ |
||
648 | public function addRemovedLabel( $language, $path ) { |
||
651 | |||
652 | /** |
||
653 | * Get serialized descriptions and add them to result |
||
654 | * |
||
655 | * @param TermList $descriptions the descriptions to insert in the result |
||
656 | * @param array|string $path where the data is located |
||
657 | */ |
||
658 | public function addDescriptions( TermList $descriptions, $path ) { |
||
661 | |||
662 | /** |
||
663 | * Adds fake serialization to show a label has been removed |
||
664 | * |
||
665 | * @param string $language |
||
666 | * @param array|string $path where the data is located |
||
667 | */ |
||
668 | public function addRemovedDescription( $language, $path ) { |
||
671 | |||
672 | /** |
||
673 | * Get serialized TermList and add it to the result |
||
674 | * |
||
675 | * @param TermList $termList |
||
676 | * @param string $name |
||
677 | * @param string $tag |
||
678 | * @param array|string $path where the data is located |
||
679 | */ |
||
680 | private function addTermList( TermList $termList, $name, $tag, $path ) { |
||
689 | |||
690 | /** |
||
691 | * Adds fake serialization to show a term has been removed |
||
692 | * |
||
693 | * @param string $language |
||
694 | * @param string $name |
||
695 | * @param string $tag |
||
696 | * @param array|string $path where the data is located |
||
697 | */ |
||
698 | private function addRemovedTerm( $language, $name, $tag, $path ) { |
||
711 | |||
712 | /** |
||
713 | * Get serialized AliasGroupList and add it to result |
||
714 | * |
||
715 | * @param AliasGroupList $aliasGroupList the AliasGroupList to set in the result |
||
716 | * @param array|string $path where the data is located |
||
717 | */ |
||
718 | public function addAliasGroupList( AliasGroupList $aliasGroupList, $path ) { |
||
738 | |||
739 | /** |
||
740 | * Get serialized sitelinks and add them to result |
||
741 | * |
||
742 | * @todo use a SiteLinkListSerializer when created in DataModelSerialization here |
||
743 | * |
||
744 | * @param SiteLinkList $siteLinkList the site links to insert in the result |
||
745 | * @param array|string $path where the data is located |
||
746 | * @param bool $addUrl |
||
747 | */ |
||
748 | public function addSiteLinkList( SiteLinkList $siteLinkList, $path, $addUrl = false ) { |
||
766 | |||
767 | private function getSiteLinkListArrayWithUrls( array $array ) { |
||
778 | |||
779 | private function getSiteLinkListArrayWithMetaData( array $array ) { |
||
793 | |||
794 | /** |
||
795 | * Adds fake serialization to show a sitelink has been removed |
||
796 | * |
||
797 | * @param SiteLinkList $siteLinkList |
||
798 | * @param array|string $path where the data is located |
||
799 | */ |
||
800 | public function addRemovedSiteLinks( SiteLinkList $siteLinkList, $path ) { |
||
818 | |||
819 | /** |
||
820 | * Get serialized claims and add them to result |
||
821 | * |
||
822 | * @param StatementList $statements the labels to set in the result |
||
823 | * @param array|string $path where the data is located |
||
824 | * @param array|string $props a list of fields to include, or "all" |
||
825 | */ |
||
826 | public function addStatements( StatementList $statements, $path, $props = 'all' ) { |
||
869 | |||
870 | /** |
||
871 | * Get serialized claim and add it to result |
||
872 | * |
||
873 | * @param Statement $statement |
||
874 | */ |
||
875 | public function addStatement( Statement $statement ) { |
||
897 | |||
898 | /** |
||
899 | * @param array $array |
||
900 | * @param string $claimPath to the claim array/arrays with trailing / |
||
901 | * |
||
902 | * @return array |
||
903 | */ |
||
904 | private function getArrayWithAlteredClaims( |
||
924 | |||
925 | /** |
||
926 | * @param array $array |
||
927 | * @param string $claimPath to the claim array/arrays with trailing / |
||
928 | * |
||
929 | * @return array |
||
930 | */ |
||
931 | private function getClaimsArrayWithMetaData( array $array, $claimPath = '' ) { |
||
969 | |||
970 | /** |
||
971 | * Get serialized reference and add it to result |
||
972 | * |
||
973 | * @param Reference $reference |
||
974 | */ |
||
975 | public function addReference( Reference $reference ) { |
||
992 | |||
993 | private function getReferenceArrayWithMetaData( array $array ) { |
||
1011 | |||
1012 | /** |
||
1013 | * Add an entry for a missing entity... |
||
1014 | * |
||
1015 | * @param string|null $key The key under which to place the missing entity in the 'entities' |
||
1016 | * structure. If null, defaults to the 'id' field in $missingDetails if that is set; |
||
1017 | * otherwise, it defaults to using a unique negative number. |
||
1018 | * @param array $missingDetails array containing key value pair missing details |
||
1019 | */ |
||
1020 | public function addMissingEntity( $key, array $missingDetails ) { |
||
1049 | |||
1050 | /** |
||
1051 | * @param string $from |
||
1052 | * @param string $to |
||
1053 | * @param string $name |
||
1054 | */ |
||
1055 | public function addNormalizedTitle( $from, $to, $name = 'n' ) { |
||
1062 | |||
1063 | /** |
||
1064 | * Adds the ID of the new revision from the Status object to the API result structure. |
||
1065 | * The status value is expected to be structured in the way that EditEntity::attemptSave() |
||
1066 | * resp WikiPage::doEditContent() do it: as an array, with an EntityRevision object in the |
||
1067 | * 'revision' field. If $oldRevId is set and the latest edit was null, a 'nochange' flag |
||
1068 | * is also added. |
||
1069 | * |
||
1070 | * If no revision is found in the Status object, this method does nothing. |
||
1071 | * |
||
1072 | * @see ApiResult::addValue() |
||
1073 | * |
||
1074 | * @param Status $status The status to get the revision ID from. |
||
1075 | * @param string|null|array $path Where in the result to put the revision id |
||
1076 | * @param int|null $oldRevId The id of the latest revision of the entity before |
||
1077 | * the last (possibly null) edit |
||
1078 | */ |
||
1079 | public function addRevisionIdFromStatusToResult( Status $status, $path, $oldRevId = null ) { |
||
1098 | |||
1099 | } |
||
1100 |
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: