Complex classes like Relation 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 Relation, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
48 | class Relation |
||
49 | { |
||
50 | const CONTENT_OBJECT_NAME = 'SOLR_RELATION'; |
||
51 | |||
52 | /** |
||
53 | * Content object configuration |
||
54 | * |
||
55 | * @var array |
||
56 | */ |
||
57 | protected $configuration = []; |
||
58 | |||
59 | /** |
||
60 | * Constructor. |
||
61 | * |
||
62 | */ |
||
63 | 5 | public function __construct() |
|
68 | |||
69 | /** |
||
70 | * Executes the SOLR_RELATION content object. |
||
71 | * |
||
72 | * Resolves relations between records. Currently supported relations are |
||
73 | * TYPO3-style m:n relations. |
||
74 | * May resolve single value and multi value relations. |
||
75 | * |
||
76 | * @param string $name content object name 'SOLR_RELATION' |
||
77 | * @param array $configuration for the content object |
||
78 | * @param string $TyposcriptKey not used |
||
79 | * @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $parentContentObject parent content object |
||
80 | * @return string serialized array representation of the given list |
||
81 | */ |
||
82 | 5 | public function cObjGetSingleExt( |
|
112 | |||
113 | /** |
||
114 | * Gets the related items of the current record's configured field. |
||
115 | * |
||
116 | * @param ContentObjectRenderer $parentContentObject parent content object |
||
117 | * @return array Array of related items, values already resolved from related records |
||
118 | */ |
||
119 | 5 | protected function getRelatedItems( |
|
120 | ContentObjectRenderer $parentContentObject |
||
121 | ) { |
||
122 | 5 | $relatedItems = []; |
|
123 | |||
124 | 5 | list($localTableName, $localRecordUid) = explode(':', |
|
125 | 5 | $parentContentObject->currentRecord); |
|
126 | |||
127 | 5 | $localTableTca = $GLOBALS['TCA'][$localTableName]; |
|
128 | 5 | $localFieldName = $this->configuration['localField']; |
|
129 | |||
130 | 5 | if (isset($localTableTca['columns'][$localFieldName])) { |
|
131 | 5 | $localFieldTca = $localTableTca['columns'][$localFieldName]; |
|
132 | 5 | $localRecordUid = $this->getUidOfRecordOverlay($localTableName, $localRecordUid); |
|
133 | 5 | if (isset($localFieldTca['config']['MM']) && trim($localFieldTca['config']['MM']) !== '') { |
|
134 | 3 | $relatedItems = $this->getRelatedItemsFromMMTable($localTableName, |
|
135 | 3 | $localRecordUid, $localFieldTca); |
|
136 | 3 | } else { |
|
137 | 2 | $relatedItems = $this->getRelatedItemsFromForeignTable($localTableName, |
|
138 | 2 | $localRecordUid, $localFieldTca, $parentContentObject); |
|
139 | } |
||
140 | 5 | } |
|
141 | |||
142 | 5 | return $relatedItems; |
|
143 | } |
||
144 | |||
145 | /** |
||
146 | * Gets the related items from a table using a n:m relation. |
||
147 | * |
||
148 | * @param string $localTableName Local table name |
||
149 | * @param int $localRecordUid Local record uid |
||
150 | * @param array $localFieldTca The local table's TCA |
||
151 | * @return array Array of related items, values already resolved from related records |
||
152 | */ |
||
153 | 3 | protected function getRelatedItemsFromMMTable( |
|
154 | $localTableName, |
||
155 | $localRecordUid, |
||
156 | array $localFieldTca |
||
157 | ) { |
||
158 | 3 | $relatedItems = []; |
|
159 | 3 | $foreignTableName = $localFieldTca['config']['foreign_table']; |
|
160 | 3 | $foreignTableTca = $GLOBALS['TCA'][$foreignTableName]; |
|
161 | 3 | $foreignTableLabelField = $this->resolveForeignTableLabelField($foreignTableTca); |
|
162 | 3 | $mmTableName = $localFieldTca['config']['MM']; |
|
163 | |||
164 | // Remove the first option of foreignLabelField for recursion |
||
165 | 3 | if (strpos($this->configuration['foreignLabelField'], '.') !== false) { |
|
166 | $foreignTableLabelFieldArr = explode('.', $this->configuration['foreignLabelField']); |
||
167 | unset($foreignTableLabelFieldArr[0]); |
||
168 | $this->configuration['foreignLabelField'] = implode('.', $foreignTableLabelFieldArr); |
||
169 | } |
||
170 | |||
171 | 3 | $relationHandler = GeneralUtility::makeInstance(RelationHandler::class); |
|
172 | 3 | $relationHandler->start('', $foreignTableName, $mmTableName, $localRecordUid, $localTableName, $localFieldTca['config']); |
|
173 | 3 | $selectUids = $relationHandler->tableArray[$foreignTableName]; |
|
174 | 3 | if (!is_array($selectUids) || count($selectUids) <= 0) { |
|
175 | return $relatedItems; |
||
176 | } |
||
177 | |||
178 | 3 | $pageSelector = GeneralUtility::makeInstance(PageRepository::class); |
|
179 | 3 | $whereClause = $pageSelector->enableFields($foreignTableName); |
|
180 | 3 | $relatedRecords = $this->getRelatedRecords($foreignTableName, $selectUids, $whereClause); |
|
181 | 3 | foreach ($relatedRecords as $record) { |
|
182 | 3 | if (isset($foreignTableTca['columns'][$foreignTableLabelField]['config']['foreign_table']) |
|
183 | 3 | && $this->configuration['enableRecursiveValueResolution'] |
|
184 | 3 | ) { |
|
185 | if (strpos($this->configuration['foreignLabelField'], '.') !== false) { |
||
186 | $foreignLabelFieldArr = explode('.', $this->configuration['foreignLabelField']); |
||
187 | unset($foreignLabelFieldArr[0]); |
||
188 | $this->configuration['foreignLabelField'] = implode('.', $foreignLabelFieldArr); |
||
189 | } |
||
190 | |||
191 | $this->configuration['localField'] = $foreignTableLabelField; |
||
192 | |||
193 | $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class); |
||
194 | $contentObject->start($record, $foreignTableName); |
||
195 | |||
196 | return $this->getRelatedItems($contentObject); |
||
197 | } else { |
||
198 | 3 | if ($GLOBALS['TSFE']->sys_language_uid > 0) { |
|
199 | 1 | $record = $this->getTranslationOverlay($foreignTableName, $record); |
|
200 | 1 | } |
|
201 | 3 | $relatedItems[] = $record[$foreignTableLabelField]; |
|
202 | } |
||
203 | 3 | } |
|
204 | |||
205 | 3 | return $relatedItems; |
|
206 | } |
||
207 | |||
208 | /** |
||
209 | * Resolves the field to use as the related item's label depending on TCA |
||
210 | * and TypoScript configuration |
||
211 | * |
||
212 | * @param array $foreignTableTca The foreign table's TCA |
||
213 | * @return string The field to use for the related item's label |
||
214 | */ |
||
215 | 5 | protected function resolveForeignTableLabelField(array $foreignTableTca) |
|
216 | { |
||
217 | 5 | $foreignTableLabelField = $foreignTableTca['ctrl']['label']; |
|
218 | |||
219 | // when foreignLabelField is not enabled we can return directly |
||
220 | 5 | if (empty($this->configuration['foreignLabelField'])) { |
|
221 | 4 | return $foreignTableLabelField; |
|
222 | } |
||
223 | |||
224 | 2 | if (strpos($this->configuration['foreignLabelField'], '.') !== false) { |
|
225 | 1 | list($foreignTableLabelField) = explode('.', $this->configuration['foreignLabelField'], 2); |
|
226 | 1 | } else { |
|
227 | 2 | $foreignTableLabelField = $this->configuration['foreignLabelField']; |
|
228 | } |
||
229 | |||
230 | 2 | return $foreignTableLabelField; |
|
231 | } |
||
232 | |||
233 | /** |
||
234 | * Return the translated record |
||
235 | * |
||
236 | * @param string $tableName |
||
237 | * @param array $record |
||
238 | * @return array |
||
239 | */ |
||
240 | 1 | protected function getTranslationOverlay($tableName, $record) |
|
248 | |||
249 | /** |
||
250 | * Gets the related items from a table using a 1:n relation. |
||
251 | * |
||
252 | * @param string $localTableName Local table name |
||
253 | * @param int $localRecordUid Local record uid |
||
254 | * @param array $localFieldTca The local table's TCA |
||
255 | * @param ContentObjectRenderer $parentContentObject parent content object |
||
256 | * @return array Array of related items, values already resolved from related records |
||
257 | */ |
||
258 | 2 | protected function getRelatedItemsFromForeignTable( |
|
301 | |||
302 | /** |
||
303 | * Resolves the value of the related field. If the related field's value is |
||
304 | * a relation itself, this method takes care of resolving it recursively. |
||
305 | * |
||
306 | * @param array $relatedRecord Related record as array |
||
307 | * @param array $foreignTableTca TCA of the related table |
||
308 | * @param string $foreignTableLabelField Field name of the foreign label field |
||
309 | * @param ContentObjectRenderer $parentContentObject cObject |
||
310 | * @param string $foreignTableName Related record table name |
||
311 | * |
||
312 | * @return string |
||
313 | */ |
||
314 | 2 | protected function resolveRelatedValue( |
|
362 | |||
363 | /** |
||
364 | * When the record has an overlay we retrieve the uid of the translated record, |
||
365 | * to resolve the relations from the translation. |
||
366 | * |
||
367 | * @param string $localTableName |
||
368 | * @param int $localRecordUid |
||
369 | * @return int |
||
370 | */ |
||
371 | 5 | protected function getUidOfRecordOverlay($localTableName, $localRecordUid) |
|
395 | |||
396 | /** |
||
397 | * Return records via relation. |
||
398 | * |
||
399 | * @param string $foreignTable The table to fetch records from. |
||
400 | * @param array $uids The uids to fetch from table. |
||
401 | * @param string $whereClause The where clause to append. |
||
402 | * |
||
403 | * @return array |
||
404 | */ |
||
405 | 5 | protected function getRelatedRecords($foreignTable, array $uids, $whereClause) |
|
418 | } |
||
419 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.