Complex classes like DoctrineObject 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 DoctrineObject, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
27 | class DoctrineObject extends AbstractHydrator |
||
28 | { |
||
29 | /** |
||
30 | * @var ObjectManager |
||
31 | */ |
||
32 | protected $objectManager; |
||
33 | |||
34 | /** |
||
35 | * @var ClassMetadata |
||
36 | */ |
||
37 | protected $metadata; |
||
38 | |||
39 | /** |
||
40 | * @var bool |
||
41 | */ |
||
42 | protected $byValue = true; |
||
43 | |||
44 | /** |
||
45 | * @var string |
||
46 | */ |
||
47 | protected $defaultByValueStrategy = __NAMESPACE__ . '\Strategy\AllowRemoveByValue'; |
||
48 | |||
49 | /** |
||
50 | * @var string |
||
51 | */ |
||
52 | protected $defaultByReferenceStrategy = __NAMESPACE__ . '\Strategy\AllowRemoveByReference'; |
||
53 | |||
54 | |||
55 | /** |
||
56 | * Constructor |
||
57 | * |
||
58 | * @param ObjectManager $objectManager The ObjectManager to use |
||
59 | * @param bool $byValue If set to true, hydrator will always use entity's public API |
||
60 | */ |
||
61 | 72 | public function __construct(ObjectManager $objectManager, $byValue = true) |
|
68 | |||
69 | /** |
||
70 | * @return string |
||
71 | */ |
||
72 | 14 | public function getDefaultByValueStrategy() |
|
76 | |||
77 | /** |
||
78 | * @param string $defaultByValueStrategy |
||
79 | * @return DoctrineObject |
||
80 | */ |
||
81 | 1 | public function setDefaultByValueStrategy($defaultByValueStrategy) |
|
86 | |||
87 | /** |
||
88 | * @return string |
||
89 | */ |
||
90 | 9 | public function getDefaultByReferenceStrategy() |
|
94 | |||
95 | /** |
||
96 | * @param string $defaultByReferenceStrategy |
||
97 | * @return DoctrineObject |
||
98 | */ |
||
99 | 1 | public function setDefaultByReferenceStrategy($defaultByReferenceStrategy) |
|
104 | |||
105 | /** |
||
106 | * Extract values from an object |
||
107 | * |
||
108 | * @param object $object |
||
109 | * @return array |
||
110 | */ |
||
111 | 17 | public function extract($object) |
|
121 | |||
122 | /** |
||
123 | * Hydrate $object with the provided $data. |
||
124 | * |
||
125 | * @param array $data |
||
126 | * @param object $object |
||
127 | * @return object |
||
128 | */ |
||
129 | 56 | public function hydrate(array $data, $object) |
|
139 | |||
140 | /** |
||
141 | * Prepare the hydrator by adding strategies to every collection valued associations |
||
142 | * |
||
143 | * @param object $object |
||
144 | * @return void |
||
145 | */ |
||
146 | 72 | protected function prepare($object) |
|
151 | |||
152 | /** |
||
153 | * Prepare strategies before the hydrator is used |
||
154 | * |
||
155 | * @throws \InvalidArgumentException |
||
156 | * @return void |
||
157 | */ |
||
158 | 72 | protected function prepareStrategies() |
|
192 | |||
193 | /** |
||
194 | * Extract values from an object using a by-value logic (this means that it uses the entity |
||
195 | * API, in this case, getters) |
||
196 | * |
||
197 | * @param object $object |
||
198 | * @throws RuntimeException |
||
199 | * @return array |
||
200 | */ |
||
201 | 10 | protected function extractByValue($object) |
|
234 | |||
235 | /** |
||
236 | * Extract values from an object using a by-reference logic (this means that values are |
||
237 | * directly fetched without using the public API of the entity, in this case, getters) |
||
238 | * |
||
239 | * @param object $object |
||
240 | * @return array |
||
241 | */ |
||
242 | 7 | protected function extractByReference($object) |
|
264 | |||
265 | /** |
||
266 | * Converts a value for hydration |
||
267 | * Apply strategies first, then the type conversions |
||
268 | * |
||
269 | * @inheritdoc |
||
270 | */ |
||
271 | 53 | public function hydrateValue($name, $value, $data = null) |
|
281 | |||
282 | /** |
||
283 | * Hydrate the object using a by-value logic (this means that it uses the entity API, in this |
||
284 | * case, setters) |
||
285 | * |
||
286 | * @param array $data |
||
287 | * @param object $object |
||
288 | * @throws RuntimeException |
||
289 | * @return object |
||
290 | */ |
||
291 | 44 | protected function hydrateByValue(array $data, $object) |
|
335 | |||
336 | /** |
||
337 | * Hydrate the object using a by-reference logic (this means that values are modified directly without |
||
338 | * using the public API, in this case setters, and hence override any logic that could be done in those |
||
339 | * setters) |
||
340 | * |
||
341 | * @param array $data |
||
342 | * @param object $object |
||
343 | * @return object |
||
344 | */ |
||
345 | 29 | protected function hydrateByReference(array $data, $object) |
|
382 | |||
383 | /** |
||
384 | * This function tries, given an array of data, to convert it to an object if the given array contains |
||
385 | * an identifier for the object. This is useful in a context of updating existing entities, without ugly |
||
386 | * tricks like setting manually the existing id directly into the entity |
||
387 | * |
||
388 | * @param array $data The data that may contain identifiers keys |
||
389 | * @param object $object |
||
390 | * @return object |
||
391 | */ |
||
392 | 56 | protected function tryConvertArrayToObject($data, $object) |
|
412 | |||
413 | /** |
||
414 | * Handle ToOne associations |
||
415 | * |
||
416 | * When $value is an array but is not the $target's identifiers, $value is |
||
417 | * most likely an array of fieldset data. The identifiers will be determined |
||
418 | * and a target instance will be initialized and then hydrated. The hydrated |
||
419 | * target will be returned. |
||
420 | * |
||
421 | * @param string $target |
||
422 | * @param mixed $value |
||
423 | * @return object |
||
424 | */ |
||
425 | 11 | protected function toOne($target, $value) |
|
441 | |||
442 | /** |
||
443 | * Handle ToMany associations. In proper Doctrine design, Collections should not be swapped, so |
||
444 | * collections are always handled by reference. Internally, every collection is handled using specials |
||
445 | * strategies that inherit from AbstractCollectionStrategy class, and that add or remove elements but without |
||
446 | * changing the collection of the object |
||
447 | * |
||
448 | * @param object $object |
||
449 | * @param mixed $collectionName |
||
450 | * @param string $target |
||
451 | * @param mixed $values |
||
452 | * |
||
453 | * @throws \InvalidArgumentException |
||
454 | * |
||
455 | * @return void |
||
456 | */ |
||
457 | 17 | protected function toMany($object, $collectionName, $target, $values) |
|
530 | |||
531 | /** |
||
532 | * Handle various type conversions that should be supported natively by Doctrine (like DateTime) |
||
533 | * See Documentation of Doctrine Mapping Types for defaults |
||
534 | * |
||
535 | * @link http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/basic-mapping.html#doctrine-mapping-types |
||
536 | * @param mixed $value |
||
537 | * @param string $typeOfField |
||
538 | * @return DateTime |
||
539 | */ |
||
540 | 53 | protected function handleTypeConversions($value, $typeOfField) |
|
592 | |||
593 | /** |
||
594 | * Find an object by a given target class and identifier |
||
595 | * |
||
596 | * @param mixed $identifiers |
||
597 | * @param string $targetClass |
||
598 | * |
||
599 | * @return object|null |
||
600 | */ |
||
601 | 25 | protected function find($identifiers, $targetClass) |
|
613 | |||
614 | /** |
||
615 | * Verifies if a provided identifier is to be considered null |
||
616 | * |
||
617 | * @param mixed $identifier |
||
618 | * |
||
619 | * @return bool |
||
620 | */ |
||
621 | 23 | private function isNullIdentifier($identifier) |
|
640 | |||
641 | /** |
||
642 | * Applies the naming strategy if there is one set |
||
643 | * |
||
644 | * @param string $field |
||
645 | * |
||
646 | * @return string |
||
647 | */ |
||
648 | 54 | protected function computeHydrateFieldName($field) |
|
655 | |||
656 | /** |
||
657 | * Applies the naming strategy if there is one set |
||
658 | * |
||
659 | * @param string $field |
||
660 | * |
||
661 | * @return string |
||
662 | */ |
||
663 | 17 | protected function computeExtractFieldName($field) |
|
670 | } |
||
671 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.