Passed
Push — master ( 3cd8c6...9e747f )
by Timo
38:54 queued 16:17
created

Item   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 447
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 2

Test Coverage

Coverage 68.48%

Importance

Changes 0
Metric Value
wmc 45
lcom 2
cbo 2
dl 0
loc 447
ccs 100
cts 146
cp 0.6848
rs 8.3673
c 0
b 0
f 0

28 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 19 4
A getIndexQueueUid() 0 4 1
A getRootPageUid() 0 4 1
A getMountPointIdentifier() 0 4 1
A setRootPageUid() 0 4 1
A getErrors() 0 4 1
A getSite() 0 5 1
A getType() 0 4 1
A setType() 0 4 1
A getIndexingConfigurationName() 0 4 1
A setIndexingConfigurationName() 0 4 1
A getChanged() 0 4 1
A setChanged() 0 4 1
A getRecordUid() 0 6 1
A setRecord() 0 4 1
A getRecordPageId() 0 6 1
A storeIndexingProperties() 0 10 2
A removeIndexingProperties() 0 15 2
A hasIndexingProperties() 0 4 1
A updateHasIndexingPropertiesFlag() 0 20 3
A hasIndexingProperty() 0 6 1
A loadIndexingProperties() 0 18 4
A setIndexingProperty() 0 20 4
A getIndexingProperty() 0 13 2
A getIndexingProperties() 0 6 1
A getIndexingPropertyKeys() 0 6 1
B writeIndexingProperties() 0 25 3
A getRecord() 0 14 2

How to fix   Complexity   

Complex Class

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
2
namespace ApacheSolrForTypo3\Solr\IndexQueue;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2009-2015 Ingo Renner <[email protected]>
8
 *  All rights reserved
9
 *
10
 *  This script is part of the TYPO3 project. The TYPO3 project is
11
 *  free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; either version 2 of the License, or
14
 *  (at your option) any later version.
15
 *
16
 *  The GNU General Public License can be found at
17
 *  http://www.gnu.org/copyleft/gpl.html.
18
 *
19
 *  This script is distributed in the hope that it will be useful,
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 *  GNU General Public License for more details.
23
 *
24
 *  This copyright notice MUST APPEAR in all copies of the script!
25
 ***************************************************************/
26
27
use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository;
28
use ApacheSolrForTypo3\Solr\Site;
29
use TYPO3\CMS\Backend\Utility\BackendUtility;
30
use TYPO3\CMS\Core\Utility\GeneralUtility;
31
32
/**
33
 * Representation of an index queue item, carrying meta data and the record to be
34
 * indexed.
35
 *
36
 * @author Ingo Renner <[email protected]>
37
 */
38
class Item
39
{
40
41
    /**
42
     * The item's uid in the index queue (tx_solr_indexqueue_item.uid)
43
     *
44
     * @var int
45
     */
46
    protected $indexQueueUid;
47
48
    /**
49
     * The root page uid of the tree the item is located in (tx_solr_indexqueue_item.root)
50
     *
51
     * @var int
52
     */
53
    protected $rootPageUid;
54
55
    /**
56
     * The record's type, usually a table name, but could also be a file type (tx_solr_indexqueue_item.item_type)
57
     *
58
     * @var string
59
     */
60
    protected $type;
61
62
    /**
63
     * The name of the indexing configuration that should be used when indexing (tx_solr_indexqueue_item.indexing_configuration)
64
     * the item.
65
     *
66
     * @var string
67
     */
68
    protected $indexingConfigurationName;
69
70
    /**
71
     * The unix timestamp when the record was last changed (tx_solr_indexqueue_item.changed)
72
     *
73
     * @var int
74
     */
75
    protected $changed;
76
77
    /**
78
     * Indexing properties to provide additional information for the item's
79
     * indexer / how to index the item.
80
     *
81
     * @var array
82
     */
83
    protected $indexingProperties = [];
84
85
    /**
86
     * Flag for lazy loading indexing properties.
87
     *
88
     * @var bool
89
     */
90
    protected $indexingPropertiesLoaded = false;
91
92
    /**
93
     * Flag, whether indexing properties exits for this item.
94
     *
95
     * @var bool
96
     */
97
    protected $hasIndexingProperties = false;
98
99
    /**
100
     * The record's uid.
101
     *
102
     * @var int
103
     */
104
    protected $recordUid = 0;
105
106
    /**
107
     * The record itself
108
     *
109
     * @var array
110
     */
111
    protected $record;
112
113
    /**
114
     * Moint point identifier.
115
     *
116
     * @var string
117
     */
118
    protected $mountPointIdentifier;
119
120
    /**
121
     * @var string
122
     */
123
    protected $errors = '';
124
125
    /**
126
     * Constructor, takes item meta data information and resolves that to the full record.
127
     *
128
     * @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
129
     * @param array $fullRecord Optional full record for the item. If provided, can save some SQL queries.
130
     */
131 64
    public function __construct(
132
        array $itemMetaData,
133
        array $fullRecord = []
134
    ) {
135 64
        $this->indexQueueUid = $itemMetaData['uid'];
136 64
        $this->rootPageUid = $itemMetaData['root'];
137 64
        $this->type = $itemMetaData['item_type'];
138 64
        $this->recordUid = $itemMetaData['item_uid'];
139 64
        $this->mountPointIdentifier = (string) empty($itemMetaData['pages_mountidentifier']) ? '' : $itemMetaData['pages_mountidentifier'];
140 64
        $this->changed = $itemMetaData['changed'];
141 64
        $this->errors = (string) empty($itemMetaData['errors']) ? '' : $itemMetaData['errors'];
142
143 64
        $this->indexingConfigurationName = $itemMetaData['indexing_configuration'];
144 64
        $this->hasIndexingProperties = (boolean)$itemMetaData['has_indexing_properties'];
145
146 64
        if (!empty($fullRecord)) {
147 34
            $this->record = $fullRecord;
148
        }
149 64
    }
150
151
    /**
152
     * @return int|mixed
153
     */
154 8
    public function getIndexQueueUid()
155
    {
156 8
        return $this->indexQueueUid;
157
    }
158
159
    /**
160
     * Gets the item's root page ID (uid)
161
     *
162
     * @return int root page ID
163
     */
164 27
    public function getRootPageUid()
165
    {
166 27
        return $this->rootPageUid;
167
    }
168
169
    /**
170
     * Returns mount point identifier
171
     *
172
     * @return string
173
     */
174 21
    public function getMountPointIdentifier()
175
    {
176 21
        return $this->mountPointIdentifier;
177
    }
178
179
    /**
180
     * @param integer $uid
181
     */
182
    public function setRootPageUid($uid)
183
    {
184
        $this->rootPageUid = intval($uid);
185
    }
186
187
    /**
188
     * @return string
189
     */
190 5
    public function getErrors()
191
    {
192 5
        return $this->errors;
193
    }
194
195
    /**
196
     * Gets the site the item belongs to.
197
     *
198
     * @return Site Site instance the item belongs to.
199
     */
200 27
    public function getSite()
201
    {
202 27
        $siteRepository = GeneralUtility::makeInstance(SiteRepository::class);
203 27
        return $siteRepository->getSiteByRootPageId($this->rootPageUid);
204
    }
205
206 23
    public function getType()
207
    {
208 23
        return $this->type;
209
    }
210
211
    public function setType($type)
212
    {
213
        $this->type = $type;
214
    }
215
216 32
    public function getIndexingConfigurationName()
217
    {
218 32
        return $this->indexingConfigurationName;
219
    }
220
221
    public function setIndexingConfigurationName($indexingConfigurationName)
222
    {
223
        $this->indexingConfigurationName = $indexingConfigurationName;
224
    }
225
226
    public function getChanged()
227
    {
228
        return $this->changed;
229
    }
230
231
    public function setChanged($changed)
232
    {
233
        $this->changed = intval($changed);
234
    }
235
236 5
    public function getRecordUid()
237
    {
238 5
        $this->getRecord();
239
240 5
        return $this->record['uid'];
241
    }
242
243
    /**
244
     * Gets the item's full record.
245
     *
246
     * Uses lazy loading.
247
     *
248
     * @return array The item's DB record.
249
     */
250 20
    public function getRecord()
251
    {
252 20
        if (empty($this->record)) {
253 1
            $this->record = (array)BackendUtility::getRecord(
254 1
                $this->type,
255 1
                $this->recordUid,
256 1
                '*',
257 1
                '',
258 1
                false
259
            );
260
        }
261
262 20
        return $this->record;
263
    }
264
265
    public function setRecord(array $record)
266
    {
267
        $this->record = $record;
268
    }
269
270
    /**
271
     * @return int
272
     */
273 17
    public function getRecordPageId()
274
    {
275 17
        $this->getRecord();
276
277 17
        return $this->record['pid'];
278
    }
279
280
    /**
281
     * Stores the indexing properties.
282
     *
283
     */
284 7
    public function storeIndexingProperties()
285
    {
286 7
        $this->removeIndexingProperties();
287
288 7
        if ($this->hasIndexingProperties()) {
289 7
            $this->writeIndexingProperties();
290
        }
291
292 7
        $this->updateHasIndexingPropertiesFlag();
293 7
    }
294
295
    /**
296
     * Removes existing indexing properties.
297
     *
298
     * @throws \RuntimeException when an SQL error occurs
299
     */
300 7
    protected function removeIndexingProperties()
301
    {
302 7
        $GLOBALS['TYPO3_DB']->exec_DELETEquery(
303 7
            'tx_solr_indexqueue_indexing_property',
304 7
            'root = ' . intval($this->rootPageUid)
305 7
            . ' AND item_id = ' . intval($this->indexQueueUid)
306
        );
307
308 7
        if ($GLOBALS['TYPO3_DB']->sql_error()) {
309
            throw new \RuntimeException(
310
                'Could not remove indexing properties for item ' . $this->indexQueueUid,
311
                1323802532
312
            );
313
        }
314 7
    }
315
316 7
    public function hasIndexingProperties()
317
    {
318 7
        return $this->hasIndexingProperties;
319
    }
320
321
    /**
322
     * Writes all indexing properties.
323
     *
324
     * @throws \RuntimeException when an SQL error occurs
325
     */
326 7
    protected function writeIndexingProperties()
327
    {
328 7
        $properties = [];
329 7
        foreach ($this->indexingProperties as $propertyKey => $propertyValue) {
330 7
            $properties[] = [
331 7
                $this->rootPageUid,
332 7
                $this->indexQueueUid,
333 7
                $propertyKey,
334 7
                $propertyValue
335
            ];
336
        }
337
338 7
        $GLOBALS['TYPO3_DB']->exec_INSERTmultipleRows(
339 7
            'tx_solr_indexqueue_indexing_property',
340 7
            ['root', 'item_id', 'property_key', 'property_value'],
341
            $properties
342
        );
343
344 7
        if ($GLOBALS['TYPO3_DB']->sql_error()) {
345
            throw new \RuntimeException(
346
                'Could not insert indexing properties for item ' . $this->indexQueueUid,
347
                1323802570
348
            );
349
        }
350 7
    }
351
352
    /**
353
     * Updates the "has_indexing_properties" flag in the Index Queue.
354
     *
355
     * @throws \RuntimeException when an SQL error occurs
356
     */
357 7
    protected function updateHasIndexingPropertiesFlag()
358
    {
359 7
        $hasIndexingProperties = '0';
360 7
        if ($this->hasIndexingProperties()) {
361 7
            $hasIndexingProperties = '1';
362
        }
363
364 7
        $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
365 7
            'tx_solr_indexqueue_item',
366 7
            'uid = ' . intval($this->indexQueueUid),
367 7
            ['has_indexing_properties' => $hasIndexingProperties]
368
        );
369
370 7
        if ($GLOBALS['TYPO3_DB']->sql_error()) {
371
            throw new \RuntimeException(
372
                'Could not update has_indexing_properties flag in Index Queue for item ' . $this->indexQueueUid,
373
                1323802610
374
            );
375
        }
376 7
    }
377
378
    /**
379
     * @param string $key
380
     * @return bool
381
     */
382 1
    public function hasIndexingProperty($key)
383
    {
384 1
        $this->loadIndexingProperties();
385
386 1
        return array_key_exists($key, $this->indexingProperties);
387
    }
388
389
    /**
390
     * Loads the indexing properties for the item - if not already loaded.
391
     *
392
     */
393 8
    public function loadIndexingProperties()
394
    {
395 8
        if (!$this->indexingPropertiesLoaded) {
396 8
            $indexingProperties = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
397 8
                'property_key, property_value',
398 8
                'tx_solr_indexqueue_indexing_property',
399 8
                'item_id = ' . intval($this->indexQueueUid)
400
            );
401
402 8
            if (!empty($indexingProperties)) {
403
                foreach ($indexingProperties as $indexingProperty) {
404
                    $this->indexingProperties[$indexingProperty['property_key']] = $indexingProperty['property_value'];
405
                }
406
            }
407
408 8
            $this->indexingPropertiesLoaded = true;
409
        }
410 8
    }
411
412
    /**
413
     * Sets an indexing property for the item.
414
     *
415
     * @param string $key Indexing property name
416
     * @param string|int|float $value Indexing property value
417
     * @throws \InvalidArgumentException when $value is not string, integer or float
418
     */
419 7
    public function setIndexingProperty($key, $value)
420
    {
421
422
        // make sure to not interfere with existing indexing properties
423 7
        $this->loadIndexingProperties();
424
425 7
        $key = (string)$key; // Scalar typehints now!
426
427 7
        if (!is_string($value) && !is_int($value) && !is_float($value)) {
428
            throw new \InvalidArgumentException(
429
                'Cannot set indexing property "' . $key
430
                . '", its value must be string, integer or float, '
431
                . 'type given was "' . gettype($value) . '"',
432
                1323173209
433
            );
434
        }
435
436 7
        $this->indexingProperties[$key] = $value;
437 7
        $this->hasIndexingProperties = true;
438 7
    }
439
440
    /**
441
     * Gets a specific indexing property by its name/key.
442
     *
443
     * @param string $key Indexing property name/key.
444
     * @throws \InvalidArgumentException when the given $key does not exist.
445
     * @return string
446
     */
447
    public function getIndexingProperty($key)
448
    {
449
        $this->loadIndexingProperties();
450
451
        if (!array_key_exists($key, $this->indexingProperties)) {
452
            throw new \InvalidArgumentException(
453
                'No indexing property "' . $key . '".',
454
                1323174143
455
            );
456
        }
457
458
        return $this->indexingProperties[$key];
459
    }
460
461
    /**
462
     * Gets all indexing properties set for this item.
463
     *
464
     * @return array Array of indexing properties.
465
     */
466
    public function getIndexingProperties()
467
    {
468
        $this->loadIndexingProperties();
469
470
        return $this->indexingProperties;
471
    }
472
473
    /**
474
     * Gets the names/keys of the item's indexing properties.
475
     *
476
     * @return array Array of indexing property names/keys
477
     */
478
    public function getIndexingPropertyKeys()
479
    {
480
        $this->loadIndexingProperties();
481
482
        return array_keys($this->indexingProperties);
483
    }
484
}
485