Complex classes like ManyToManyRelation 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 ManyToManyRelation, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
32 | class ManyToManyRelation extends MultipleRelation implements \IteratorAggregate, \Countable |
||
33 | { |
||
34 | use LookupTrait; |
||
35 | |||
36 | /** Schema shortcuts */ |
||
37 | const PIVOT_TABLE = Record::PIVOT_TABLE; |
||
38 | const PIVOT_DATABASE = 917; |
||
39 | |||
40 | /** |
||
41 | * @var Table|null |
||
42 | */ |
||
43 | private $pivotTable = null; |
||
44 | |||
45 | /** |
||
46 | * @var \SplObjectStorage |
||
47 | */ |
||
48 | private $pivotData; |
||
49 | |||
50 | /** |
||
51 | * Linked but not saved yet records. |
||
52 | * |
||
53 | * @var array |
||
54 | */ |
||
55 | private $scheduled = []; |
||
56 | |||
57 | /** |
||
58 | * Record which pivot data was updated, record must still present in linked array. |
||
59 | * |
||
60 | * @var array |
||
61 | */ |
||
62 | private $updated = []; |
||
63 | |||
64 | /** |
||
65 | * Records scheduled to be de-associated. |
||
66 | * |
||
67 | * @var RecordInterface[] |
||
68 | */ |
||
69 | private $unlinked = []; |
||
70 | |||
71 | /** |
||
72 | * @param string $class |
||
73 | * @param array $schema |
||
74 | * @param ORMInterface $orm |
||
75 | */ |
||
76 | public function __construct($class, array $schema, ORMInterface $orm) |
||
81 | |||
82 | /** |
||
83 | * {@inheritdoc} |
||
84 | * |
||
85 | * Pivot data must be set separatelly. |
||
86 | */ |
||
87 | public function setRelated($value) |
||
124 | |||
125 | /** |
||
126 | * Get all unlinked records. |
||
127 | * |
||
128 | * @return \ArrayIterator |
||
129 | */ |
||
130 | public function getUnlinked() |
||
134 | |||
135 | /** |
||
136 | * Get pivot data associated with specific instance. |
||
137 | * |
||
138 | * @param RecordInterface $record |
||
139 | * |
||
140 | * @return array |
||
141 | * |
||
142 | * @throws RelationException |
||
143 | */ |
||
144 | public function getPivot(RecordInterface $record): array |
||
154 | |||
155 | /** |
||
156 | * Link record with parent entity. Only record instances is accepted. |
||
157 | * |
||
158 | * @param RecordInterface $record |
||
159 | * @param array $pivotData |
||
160 | * |
||
161 | * @return self |
||
162 | * |
||
163 | * @throws RelationException |
||
164 | */ |
||
165 | public function link(RecordInterface $record, array $pivotData = []): self |
||
191 | |||
192 | /** |
||
193 | * Unlink specific entity from relation. Will load relation data! Record to delete will be |
||
194 | * automatically matched to a give record. |
||
195 | * |
||
196 | * @param RecordInterface $record |
||
197 | * |
||
198 | * @return self |
||
199 | * |
||
200 | * @throws RelationException When entity not linked. |
||
201 | */ |
||
202 | public function unlink(RecordInterface $record): self |
||
223 | |||
224 | /** |
||
225 | * {@inheritdoc} |
||
226 | */ |
||
227 | public function queueCommands(ContextualCommandInterface $parentCommand): CommandInterface |
||
303 | |||
304 | /** |
||
305 | * Insane method used to properly set pivot command context (where or insert statement) based on |
||
306 | * parent and outer records AND/OR based on command promises. |
||
307 | * |
||
308 | * @param ContextualCommandInterface $pivotCommand |
||
309 | * @param RecordInterface $parent |
||
310 | * @param ContextualCommandInterface $parentCommand |
||
311 | * @param RecordInterface $outer |
||
312 | * @param ContextualCommandInterface $outerCommand |
||
313 | * |
||
314 | * @return ContextualCommandInterface |
||
315 | */ |
||
316 | protected function ensureContext( |
||
341 | |||
342 | /** |
||
343 | * Fetch data from database. Lazy load. Method require a bit of love. |
||
344 | * |
||
345 | * @return array |
||
346 | */ |
||
347 | protected function loadRelated(): array |
||
377 | |||
378 | /** |
||
379 | * Create query for lazy loading. |
||
380 | * |
||
381 | * @param mixed $innerKey |
||
382 | * |
||
383 | * @return SelectQuery |
||
384 | */ |
||
385 | protected function createQuery($innerKey): SelectQuery |
||
417 | |||
418 | /** |
||
419 | * Init relations and populate pivot map. |
||
420 | * |
||
421 | * @return ManyToManyRelation |
||
422 | */ |
||
423 | protected function initInstances(): MultipleRelation |
||
445 | |||
446 | /** |
||
447 | * @return Table |
||
448 | */ |
||
449 | private function pivotTable() |
||
461 | |||
462 | /** |
||
463 | * Make sure that pivot data in a valid format. |
||
464 | * |
||
465 | * @param array $pivotData |
||
466 | * |
||
467 | * @throws RelationException |
||
468 | */ |
||
469 | private function assertPivot(array $pivotData) |
||
477 | } |