Complex classes like Item 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 Item, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
37 | class Item |
||
38 | { |
||
39 | |||
40 | /** |
||
41 | * The item's uid in the index queue (tx_solr_indexqueue_item.uid) |
||
42 | * |
||
43 | * @var int |
||
44 | */ |
||
45 | protected $indexQueueUid; |
||
46 | |||
47 | /** |
||
48 | * The root page uid of the tree the item is located in (tx_solr_indexqueue_item.root) |
||
49 | * |
||
50 | * @var int |
||
51 | */ |
||
52 | protected $rootPageUid; |
||
53 | |||
54 | /** |
||
55 | * The record's type, usually a table name, but could also be a file type (tx_solr_indexqueue_item.item_type) |
||
56 | * |
||
57 | * @var string |
||
58 | */ |
||
59 | protected $type; |
||
60 | |||
61 | /** |
||
62 | * The name of the indexing configuration that should be used when indexing (tx_solr_indexqueue_item.indexing_configuration) |
||
63 | * the item. |
||
64 | * |
||
65 | * @var string |
||
66 | */ |
||
67 | protected $indexingConfigurationName; |
||
68 | |||
69 | /** |
||
70 | * The unix timestamp when the record was last changed (tx_solr_indexqueue_item.changed) |
||
71 | * |
||
72 | * @var int |
||
73 | */ |
||
74 | protected $changed; |
||
75 | |||
76 | /** |
||
77 | * Indexing properties to provide additional information for the item's |
||
78 | * indexer / how to index the item. |
||
79 | * |
||
80 | * @var array |
||
81 | */ |
||
82 | protected $indexingProperties = array(); |
||
83 | |||
84 | /** |
||
85 | * Flag for lazy loading indexing properties. |
||
86 | * |
||
87 | * @var bool |
||
88 | */ |
||
89 | protected $indexingPropertiesLoaded = false; |
||
90 | |||
91 | /** |
||
92 | * Flag, whether indexing properties exits for this item. |
||
93 | * |
||
94 | * @var bool |
||
95 | */ |
||
96 | protected $hasIndexingProperties = false; |
||
97 | |||
98 | /** |
||
99 | * The record's uid. |
||
100 | * |
||
101 | * @var int |
||
102 | */ |
||
103 | protected $recordUid = 0; |
||
104 | |||
105 | /** |
||
106 | * The record itself |
||
107 | * |
||
108 | * @var array |
||
109 | */ |
||
110 | protected $record; |
||
111 | |||
112 | /** |
||
113 | * Constructor, takes item meta data information and resolves that to the full record. |
||
114 | * |
||
115 | * @param array $itemMetaData Metadata describing the item to index using the index queue. Is expected to contain a record from table tx_solr_indexqueue_item |
||
116 | * @param array $fullRecord Optional full record for the item. If provided, can save some SQL queries. |
||
117 | */ |
||
118 | 19 | public function __construct( |
|
119 | array $itemMetaData, |
||
120 | array $fullRecord = array() |
||
121 | ) { |
||
122 | 19 | $this->indexQueueUid = $itemMetaData['uid']; |
|
123 | 19 | $this->rootPageUid = $itemMetaData['root']; |
|
124 | 19 | $this->type = $itemMetaData['item_type']; |
|
125 | 19 | $this->recordUid = $itemMetaData['item_uid']; |
|
126 | 19 | $this->changed = $itemMetaData['changed']; |
|
127 | |||
128 | 19 | $this->indexingConfigurationName = $itemMetaData['indexing_configuration']; |
|
129 | 19 | $this->hasIndexingProperties = (boolean)$itemMetaData['has_indexing_properties']; |
|
130 | |||
131 | 19 | if (!empty($fullRecord)) { |
|
132 | 15 | $this->record = $fullRecord; |
|
133 | } |
||
134 | 19 | } |
|
135 | |||
136 | 1 | public function getIndexQueueUid() |
|
140 | |||
141 | /** |
||
142 | * Gets the item's root page ID (uid) |
||
143 | * |
||
144 | * @return int root page ID |
||
145 | */ |
||
146 | 13 | public function getRootPageUid() |
|
150 | |||
151 | public function setRootPageUid($uid) |
||
155 | |||
156 | /** |
||
157 | * Gets the site the item belongs to. |
||
158 | * |
||
159 | * @return Site Site instance the item belongs to. |
||
160 | */ |
||
161 | 14 | public function getSite() |
|
166 | |||
167 | 11 | public function getType() |
|
171 | |||
172 | public function setType($type) |
||
176 | |||
177 | 12 | public function getIndexingConfigurationName() |
|
181 | |||
182 | public function setIndexingConfigurationName($indexingConfigurationName) |
||
186 | |||
187 | public function getChanged() |
||
191 | |||
192 | public function setChanged($changed) |
||
196 | |||
197 | /** |
||
198 | * Sets the timestamp of when an item has been indexed. |
||
199 | * |
||
200 | * @return void |
||
201 | */ |
||
202 | 5 | public function updateIndexedTime() |
|
203 | { |
||
204 | 5 | $GLOBALS['TYPO3_DB']->exec_UPDATEquery( |
|
205 | 5 | 'tx_solr_indexqueue_item', |
|
206 | 5 | 'uid = ' . (int)$this->indexQueueUid, |
|
207 | 5 | array('indexed' => time()) |
|
208 | ); |
||
209 | 5 | } |
|
210 | |||
211 | 2 | public function getRecordUid() |
|
217 | |||
218 | /** |
||
219 | * Gets the item's full record. |
||
220 | * |
||
221 | * Uses lazy loading. |
||
222 | * |
||
223 | * @return array The item's DB record. |
||
224 | */ |
||
225 | 11 | public function getRecord() |
|
226 | { |
||
227 | 11 | if (empty($this->record)) { |
|
228 | $this->record = BackendUtility::getRecord( |
||
|
|||
229 | $this->type, |
||
230 | $this->recordUid, |
||
231 | '*', |
||
232 | '', |
||
233 | false |
||
234 | ); |
||
235 | } |
||
236 | |||
237 | 11 | return $this->record; |
|
238 | } |
||
239 | |||
240 | public function setRecord(array $record) |
||
244 | |||
245 | 1 | public function getRecordPageId() |
|
251 | |||
252 | /** |
||
253 | * Stores the indexing properties. |
||
254 | * |
||
255 | */ |
||
256 | 2 | public function storeIndexingProperties() |
|
257 | { |
||
258 | 2 | $this->removeIndexingProperties(); |
|
259 | |||
260 | 2 | if ($this->hasIndexingProperties()) { |
|
261 | 2 | $this->writeIndexingProperties(); |
|
262 | } |
||
263 | |||
264 | 2 | $this->updateHasIndexingPropertiesFlag(); |
|
265 | 2 | } |
|
266 | |||
267 | /** |
||
268 | * Removes existing indexing properties. |
||
269 | * |
||
270 | * @throws \RuntimeException when an SQL error occurs |
||
271 | */ |
||
272 | 2 | protected function removeIndexingProperties() |
|
273 | { |
||
274 | 2 | $GLOBALS['TYPO3_DB']->exec_DELETEquery( |
|
275 | 2 | 'tx_solr_indexqueue_indexing_property', |
|
276 | 2 | 'root = ' . intval($this->rootPageUid) |
|
277 | 2 | . ' AND item_id = ' . intval($this->indexQueueUid) |
|
278 | ); |
||
279 | |||
280 | 2 | if ($GLOBALS['TYPO3_DB']->sql_error()) { |
|
281 | throw new \RuntimeException( |
||
282 | 'Could not remove indexing properties for item ' . $this->indexQueueUid, |
||
283 | 1323802532 |
||
284 | ); |
||
285 | } |
||
286 | 2 | } |
|
287 | |||
288 | 2 | public function hasIndexingProperties() |
|
292 | |||
293 | /** |
||
294 | * Writes all indexing properties. |
||
295 | * |
||
296 | * @throws \RuntimeException when an SQL error occurs |
||
297 | */ |
||
298 | 2 | protected function writeIndexingProperties() |
|
299 | { |
||
300 | 2 | $properties = array(); |
|
301 | 2 | foreach ($this->indexingProperties as $propertyKey => $propertyValue) { |
|
302 | 2 | $properties[] = array( |
|
303 | 2 | $this->rootPageUid, |
|
304 | 2 | $this->indexQueueUid, |
|
305 | 2 | $propertyKey, |
|
306 | 2 | $propertyValue |
|
307 | ); |
||
308 | } |
||
309 | |||
310 | 2 | $GLOBALS['TYPO3_DB']->exec_INSERTmultipleRows( |
|
311 | 2 | 'tx_solr_indexqueue_indexing_property', |
|
312 | 2 | array('root', 'item_id', 'property_key', 'property_value'), |
|
313 | $properties |
||
314 | ); |
||
315 | |||
316 | 2 | if ($GLOBALS['TYPO3_DB']->sql_error()) { |
|
317 | throw new \RuntimeException( |
||
318 | 'Could not insert indexing properties for item ' . $this->indexQueueUid, |
||
319 | 1323802570 |
||
320 | ); |
||
321 | } |
||
322 | 2 | } |
|
323 | |||
324 | /** |
||
325 | * Updates the "has_indexing_properties" flag in the Index Queue. |
||
326 | * |
||
327 | * @throws \RuntimeException when an SQL error occurs |
||
328 | */ |
||
329 | 2 | protected function updateHasIndexingPropertiesFlag() |
|
330 | { |
||
331 | 2 | $hasIndexingProperties = '0'; |
|
332 | 2 | if ($this->hasIndexingProperties()) { |
|
333 | 2 | $hasIndexingProperties = '1'; |
|
334 | } |
||
335 | |||
336 | 2 | $GLOBALS['TYPO3_DB']->exec_UPDATEquery( |
|
337 | 2 | 'tx_solr_indexqueue_item', |
|
338 | 2 | 'uid = ' . intval($this->indexQueueUid), |
|
339 | 2 | array('has_indexing_properties' => $hasIndexingProperties) |
|
340 | ); |
||
341 | |||
342 | 2 | if ($GLOBALS['TYPO3_DB']->sql_error()) { |
|
343 | throw new \RuntimeException( |
||
344 | 'Could not update has_indexing_properties flag in Index Queue for item ' . $this->indexQueueUid, |
||
345 | 1323802610 |
||
346 | ); |
||
347 | } |
||
348 | 2 | } |
|
349 | |||
350 | /** |
||
351 | * @param string $key |
||
352 | * @return bool |
||
353 | */ |
||
354 | 1 | public function hasIndexingProperty($key) |
|
360 | |||
361 | /** |
||
362 | * Loads the indexing properties for the item - if not already loaded. |
||
363 | * |
||
364 | */ |
||
365 | 3 | public function loadIndexingProperties() |
|
366 | { |
||
367 | 3 | if (!$this->indexingPropertiesLoaded) { |
|
368 | 3 | $indexingProperties = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( |
|
369 | 3 | 'property_key, property_value', |
|
370 | 3 | 'tx_solr_indexqueue_indexing_property', |
|
371 | 3 | 'item_id = ' . intval($this->indexQueueUid) |
|
372 | ); |
||
373 | |||
374 | 3 | if (!empty($indexingProperties)) { |
|
375 | foreach ($indexingProperties as $indexingProperty) { |
||
376 | $this->indexingProperties[$indexingProperty['property_key']] = $indexingProperty['property_value']; |
||
377 | } |
||
378 | } |
||
379 | |||
380 | 3 | $this->indexingPropertiesLoaded = true; |
|
381 | } |
||
382 | 3 | } |
|
383 | |||
384 | /** |
||
385 | * Sets an indexing property for the item. |
||
386 | * |
||
387 | * @param string $key Indexing property name |
||
388 | * @param string|int|float $value Indexing property value |
||
389 | * @throws \InvalidArgumentException when $value is not string, integer or float |
||
390 | */ |
||
391 | 2 | public function setIndexingProperty($key, $value) |
|
392 | { |
||
393 | |||
394 | // make sure to not interfere with existing indexing properties |
||
395 | 2 | $this->loadIndexingProperties(); |
|
396 | |||
397 | 2 | $key = (string)$key; // Scalar typehints now! |
|
398 | |||
399 | 2 | if (!is_string($value) && !is_int($value) && !is_float($value)) { |
|
400 | throw new \InvalidArgumentException( |
||
401 | 'Cannot set indexing property "' . $key |
||
402 | . '", its value must be string, integer or float, ' |
||
403 | . 'type given was "' . gettype($value) . '"', |
||
404 | 1323173209 |
||
405 | ); |
||
406 | } |
||
407 | |||
408 | 2 | $this->indexingProperties[$key] = $value; |
|
409 | 2 | $this->hasIndexingProperties = true; |
|
410 | 2 | } |
|
411 | |||
412 | /** |
||
413 | * Gets a specific indexing property by its name/key. |
||
414 | * |
||
415 | * @param string $key Indexing property name/key. |
||
416 | * @throws \InvalidArgumentException when the given $key does not exist. |
||
417 | * @return string |
||
418 | */ |
||
419 | public function getIndexingProperty($key) |
||
432 | |||
433 | /** |
||
434 | * Gets all indexing properties set for this item. |
||
435 | * |
||
436 | * @return array Array of indexing properties. |
||
437 | */ |
||
438 | public function getIndexingProperties() |
||
444 | |||
445 | /** |
||
446 | * Gets the names/keys of the item's indexing properties. |
||
447 | * |
||
448 | * @return array Array of indexing property names/keys |
||
449 | */ |
||
450 | public function getIndexingPropertyKeys() |
||
456 | } |
||
457 |
Our type inference engine has found an assignment of a scalar value (like a string, an integer or null) to a property which is an array.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.
To type hint that a parameter can be either an array or null, you can set a type hint of array and a default value of null. The PHP interpreter will then accept both an array or null for that parameter.
The function can be called with either null or an array for the parameter
$needle
but will only accept an array as$haystack
.