Passed
Push — master ( 14b490...3d7c7d )
by Timo
23:43
created

processDatamap_afterDatabaseOperations()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 29
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 8.304

Importance

Changes 0
Metric Value
eloc 14
dl 0
loc 29
ccs 12
cts 20
cp 0.6
rs 9.2222
c 0
b 0
f 0
cc 6
nc 6
nop 5
crap 8.304
1
<?php
2
namespace ApacheSolrForTypo3\Solr;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2010-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 3 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\IndexQueue\Queue;
28
use ApacheSolrForTypo3\Solr\System\TCA\TCAService;
29
use TYPO3\CMS\Backend\Utility\BackendUtility;
30
use TYPO3\CMS\Core\DataHandling\DataHandler;
31
use TYPO3\CMS\Core\SingletonInterface;
32
use TYPO3\CMS\Core\Utility\GeneralUtility;
33
34
/**
35
 * Garbage Collector, removes related documents from the index when a record is
36
 * set to hidden, is deleted or is otherwise made invisible to website visitors.
37
 *
38
 * Garbage collection will happen for online/LIVE workspaces only.
39
 *
40
 * @author Ingo Renner <[email protected]>
41
 * @author Timo Schmidt <[email protected]>
42
 */
43
class GarbageCollector extends AbstractDataHandlerListener implements SingletonInterface
44
{
45
    /**
46
     * @var array
47
     */
48
    protected $trackedRecords = [];
49
50
    /**
51
     * @var TCAService
52
     */
53
    protected $tcaService;
54
55
    /**
56
     * GarbageCollector constructor.
57
     * @param TCAService|null $TCAService
58
     */
59 12
    public function __construct(TCAService $TCAService = null)
60
    {
61 12
        parent::__construct();
62 12
        $this->tcaService = $TCAService ?? GeneralUtility::makeInstance(TCAService::class);
63 12
    }
64
65
    /**
66
     * Hooks into TCE main and tracks record deletion commands.
67
     *
68
     * @param string $command The command.
69
     * @param string $table The table the record belongs to
70
     * @param int $uid The record's uid
71
     * @param string $value Not used
72
     * @param DataHandler $tceMain TYPO3 Core Engine parent object, not used
73
     * @return void
74
     */
75 3
    public function processCmdmap_preProcess($command, $table, $uid, $value, DataHandler $tceMain)
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

75
    public function processCmdmap_preProcess($command, $table, $uid, /** @scrutinizer ignore-unused */ $value, DataHandler $tceMain)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $tceMain is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

75
    public function processCmdmap_preProcess($command, $table, $uid, $value, /** @scrutinizer ignore-unused */ DataHandler $tceMain)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
76
    {
77
        // workspaces: collect garbage only for LIVE workspace
78 3
        if ($command === 'delete' && $GLOBALS['BE_USER']->workspace == 0) {
79 3
            $this->collectGarbage($table, $uid);
80
81 3
            if ($table === 'pages') {
82 1
                $this->getIndexQueue()->deleteItem($table, $uid);
83
            }
84
        }
85 3
    }
86
87
    /**
88
     * Holds the configuration when a recursive page queing should be triggered.
89
     *
90
     * @var array
91
     * @return array
92
     */
93 3
    protected function getUpdateSubPagesRecursiveTriggerConfiguration()
94
    {
95
        return [
96
            // the current page has the field "extendToSubpages" enabled and the field "hidden" was set to 1
97 3
            'extendToSubpageEnabledAndHiddenFlagWasAdded' => [
98
                'currentState' =>  ['extendToSubpages' => '1'],
99
                'changeSet' => ['hidden' => '1']
100
            ],
101
            // the current page has the field "hidden" enabled and the field "extendToSubpages" was set to 1
102
            'hiddenIsEnabledAndExtendToSubPagesWasAdded' => [
103
                'currentState' =>  ['hidden' => '1'],
104
                'changeSet' => ['extendToSubpages' => '1']
105
            ]
106
        ];
107
    }
108
109
    /**
110
     * Tracks down index documents belonging to a particular record or page and
111
     * removes them from the index and the Index Queue.
112
     *
113
     * @param string $table The record's table name.
114
     * @param int $uid The record's uid.
115
     * @throws \UnexpectedValueException if a hook object does not implement interface \ApacheSolrForTypo3\Solr\GarbageCollectorPostProcessor
116
     */
117 11
    public function collectGarbage($table, $uid)
118
    {
119 11
        $isPageRelatedTable = in_array($table, ['tt_content','pages','pages_language_overlay']);
120 11
        if ($isPageRelatedTable) {
121 10
            $this->collectPageGarbage($table, $uid);
122
        } else {
123 1
            $this->collectRecordGarbage($table, $uid);
124
        }
125
126 11
        $this->callPostProcessGarbageCollectorHook($table, $uid);
127 11
    }
128
129
    /**
130
     * Calls the registered post processing hooks after the garbageCollection.
131
     *
132
     * @param string $table
133
     * @param int $uid
134
     */
135 11
    protected function callPostProcessGarbageCollectorHook($table, $uid)
136
    {
137 11
        if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessGarbageCollector'])) {
138 10
            return;
139
        }
140
141 1
        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessGarbageCollector'] as $classReference) {
142 1
            $garbageCollectorPostProcessor = GeneralUtility::makeInstance($classReference);
143
144 1
            if ($garbageCollectorPostProcessor instanceof GarbageCollectorPostProcessor) {
145 1
                $garbageCollectorPostProcessor->postProcessGarbageCollector($table, $uid);
146
            } else {
147
                $message = get_class($garbageCollectorPostProcessor) . ' must implement interface ' .
148
                    GarbageCollectorPostProcessor::class;
149 1
                throw new \UnexpectedValueException($message, 1345807460);
150
            }
151
        }
152 1
    }
153
    /**
154
     * Tracks down index documents belonging to a particular page and
155
     * removes them from the index and the Index Queue.
156
     *
157
     * @param string $table The record's table name.
158
     * @param int $uid The record's uid.
159
     */
160 10
    protected function collectPageGarbage($table, $uid)
161
    {
162 10
        if ($table === 'tt_content') {
163 4
            $this->collectPageGarbageByContentChange($uid);
164 4
            return;
165
        }
166
167 6
        if ($table === 'pages_language_overlay') {
168
            $this->collectPageGarbageByPageOverlayChange($uid);
169
            return;
170
        }
171
172 6
        if ($table === 'pages') {
173 6
            $this->collectPageGarbageByPageChange($uid);
174 6
            return;
175
        }
176
    }
177
178
    /**
179
     * Determines the relevant page id for an content element update. Deletes the page from solr and requeues the
180
     * page for a reindex.
181
     *
182
     * @todo This case can be deleted when TYPO3 8 compatibility is dropped
183
     * @param int $ttContentUid
184
     */
185 4
    protected function collectPageGarbageByContentChange($ttContentUid)
186
    {
187 4
        $contentElement = BackendUtility::getRecord('tt_content', $ttContentUid, 'uid, pid', '', false);
188 4
        $this->deleteInSolrAndUpdateIndexQueue('pages', $contentElement['pid']);
189 4
    }
190
191
    /**
192
     * Determines the relavant page id for the pages_language_overlay. Deletes the page from solr and requeues the
193
     * page for a re index.
194
     *
195
     * @param int $pagesLanguageOverlayUid
196
     */
197
    protected function collectPageGarbageByPageOverlayChange($pagesLanguageOverlayUid)
198
    {
199
        $pageOverlayRecord = BackendUtility::getRecord('pages_language_overlay', $pagesLanguageOverlayUid, 'uid, pid', '', false);
200
        $this->deleteInSolrAndUpdateIndexQueue('pages', $pageOverlayRecord['pid']);
201
    }
202
203
    /**
204
     * When a page was changed it is removed from the index and index queue.
205
     *
206
     * @param int $uid
207
     */
208 6
    protected function collectPageGarbageByPageChange($uid)
209
    {
210
        // @todo The content of this if statement can allways be executed when TYPO3 8 support is dropped
211 6
        if (!Util::getIsTYPO3VersionBelow9()) {
212
            $pageOverlay = BackendUtility::getRecord('pages', $uid, 'l10n_parent', '', false);
213
            $uid = empty($pageOverlay['l10n_parent']) ? $uid : $pageOverlay['l10n_parent'];
214
        }
215
216 6
        $this->deleteInSolrAndRemoveFromIndexQueue('pages', $uid);
217 6
    }
218
219
    /**
220
     * Deletes a document from solr and from the index queue.
221
     *
222
     * @param string $table
223
     * @param integer $uid
224
     */
225 7
    protected function deleteInSolrAndRemoveFromIndexQueue($table, $uid)
226
    {
227 7
        $this->deleteIndexDocuments($table, $uid);
228 7
        $this->getIndexQueue()->deleteItem($table, $uid);
229 7
    }
230
231
    /**
232
     * Deletes a document from solr and updates the item in the index queue (e.g. on page content updates).
233
     *
234
     * @param string $table
235
     * @param integer $uid
236
     */
237 4
    protected function deleteInSolrAndUpdateIndexQueue($table, $uid)
238
    {
239 4
        $this->deleteIndexDocuments($table, $uid);
240 4
        $this->getIndexQueue()->updateItem($table, $uid);
241 4
    }
242
243
    /**
244
     * @param string $table
245
     * @param int $uid
246
     * @param array $changedFields
247
     */
248 3
    protected function deleteSubpagesWhenExtendToSubpagesIsSet($table, $uid, $changedFields)
249
    {
250 3
        if (!$this->isRecursivePageUpdateRequired($uid, $changedFields)) {
251 1
            return;
252
        }
253
254 2
        $indexQueue = $this->getIndexQueue();
255
        // get affected subpages when "extendToSubpages" flag was set
256 2
        $pagesToDelete = $this->getSubPageIds($uid);
257
        // we need to at least remove this page
258 2
        foreach ($pagesToDelete as $pageToDelete) {
259 2
            $this->deleteIndexDocuments($table, $pageToDelete);
260 2
            $indexQueue->deleteItem($table, $pageToDelete);
261
        }
262 2
    }
263
264
    /**
265
     * Deletes index documents for a given record identification.
266
     *
267
     * @param string $table The record's table name.
268
     * @param int $uid The record's uid.
269
     */
270 11
    protected function deleteIndexDocuments($table, $uid)
271
    {
272
        /** @var $connectionManager ConnectionManager */
273 11
        $connectionManager = GeneralUtility::makeInstance(ConnectionManager::class);
274
275
        // record can be indexed for multiple sites
276 11
        $indexQueueItems = $this->getIndexQueue()->getItems($table, $uid);
277 11
        foreach ($indexQueueItems as $indexQueueItem) {
278 10
            $site = $indexQueueItem->getSite();
279 10
            $solrConfiguration = $site->getSolrConfiguration();
280 10
            $enableCommitsSetting = $solrConfiguration->getEnableCommits();
281
282
            // a site can have multiple connections (cores / languages)
283 10
            $solrConnections = $connectionManager->getConnectionsBySite($site);
284 10
            foreach ($solrConnections as $solr) {
285 10
                $solr->getWriteService()->deleteByQuery('type:' . $table . ' AND uid:' . intval($uid));
286 10
                if ($enableCommitsSetting) {
287 10
                    $solr->getWriteService()->commit(false, false, false);
0 ignored issues
show
Unused Code introduced by
The call to ApacheSolrForTypo3\Solr\...rWriteService::commit() has too many arguments starting with false. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

287
                    $solr->getWriteService()->/** @scrutinizer ignore-call */ commit(false, false, false);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
288
                }
289
            }
290
        }
291 11
    }
292
293
    /**
294
     * Tracks down index documents belonging to a particular record and
295
     * removes them from the index and the Index Queue.
296
     *
297
     * @param string $table The record's table name.
298
     * @param int $uid The record's uid.
299
     */
300 1
    protected function collectRecordGarbage($table, $uid)
301
    {
302 1
        $this->deleteInSolrAndRemoveFromIndexQUeue($table, $uid);
303 1
    }
304
305
    // methods checking whether to trigger garbage collection
306
307
    /**
308
     * Hooks into TCE main and tracks page move commands.
309
     *
310
     * @param string $command The command.
311
     * @param string $table The table the record belongs to
312
     * @param int $uid The record's uid
313
     * @param string $value Not used
314
     * @param DataHandler $tceMain TYPO3 Core Engine parent object, not used
315
     */
316 3
    public function processCmdmap_postProcess($command, $table, $uid, $value, DataHandler $tceMain) {
0 ignored issues
show
Unused Code introduced by
The parameter $tceMain is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

316
    public function processCmdmap_postProcess($command, $table, $uid, $value, /** @scrutinizer ignore-unused */ DataHandler $tceMain) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $value is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

316
    public function processCmdmap_postProcess($command, $table, $uid, /** @scrutinizer ignore-unused */ $value, DataHandler $tceMain) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
317
        // workspaces: collect garbage only for LIVE workspace
318 3
        if ($command === 'move' && $table === 'pages' && $GLOBALS['BE_USER']->workspace == 0) {
319
            // TODO the below comment is not valid anymore, pid has been removed from doc ID
320
            // ...still needed?
321
322
            // must be removed from index since the pid changes and
323
            // is part of the Solr document ID
324
            $this->collectGarbage($table, $uid);
325
326
            // now re-index with new properties
327
            $this->getIndexQueue()->updateItem($table, $uid);
328
        }
329 3
    }
330
331
    /**
332
     * Hooks into TCE main and tracks changed records. In this case the current
333
     * record's values are stored to do a change comparison later on for fields
334
     * like fe_group.
335
     *
336
     * @param array $incomingFields An array of incoming fields, new or changed, not used
337
     * @param string $table The table the record belongs to
338
     * @param mixed $uid The record's uid, [integer] or [string] (like 'NEW...')
339
     * @param DataHandler $tceMain TYPO3 Core Engine parent object, not used
340
     */
341 5
    public function processDatamap_preProcessFieldArray($incomingFields, $table, $uid, DataHandler $tceMain)
0 ignored issues
show
Unused Code introduced by
The parameter $tceMain is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

341
    public function processDatamap_preProcessFieldArray($incomingFields, $table, $uid, /** @scrutinizer ignore-unused */ DataHandler $tceMain)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $incomingFields is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

341
    public function processDatamap_preProcessFieldArray(/** @scrutinizer ignore-unused */ $incomingFields, $table, $uid, DataHandler $tceMain)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
342
    {
343 5
        if (!is_int($uid)) {
344
            // a newly created record, skip
345
            return;
346
        }
347
348 5
        if (Util::isDraftRecord($table, $uid)) {
349
            // skip workspaces: collect garbage only for LIVE workspace
350
            return;
351
        }
352
353 5
        $hasConfiguredEnableColumnForFeGroup = $this->tcaService->isEnableColumn($table, 'fe_group');
354 5
        if (!$hasConfiguredEnableColumnForFeGroup) {
355
            return;
356
        }
357
358 5
        $visibilityAffectingFields = $this->tcaService->getVisibilityAffectingFieldsByTable($table);
359 5
        $record = (array)BackendUtility::getRecord($table, $uid, $visibilityAffectingFields, '', false);
360
        // If no record could be found skip further processing
361 5
        if (empty($record)) {
362
            return;
363
        }
364
365 5
        $record = $this->tcaService->normalizeFrontendGroupField($table, $record);
366
367
        // keep previous state of important fields for later comparison
368 5
        $this->trackedRecords[$table][$uid] = $record;
369 5
    }
370
371
    /**
372
     * Hooks into TCE Main and watches all record updates. If a change is
373
     * detected that would remove the record from the website, we try to find
374
     * related documents and remove them from the index.
375
     *
376
     * @param string $status Status of the current operation, 'new' or 'update'
377
     * @param string $table The table the record belongs to
378
     * @param mixed $uid The record's uid, [integer] or [string] (like 'NEW...')
379
     * @param array $fields The record's data, not used
380
     * @param DataHandler $tceMain TYPO3 Core Engine parent object, not used
381
     */
382 7
    public function processDatamap_afterDatabaseOperations($status, $table, $uid, array $fields, DataHandler $tceMain)
0 ignored issues
show
Unused Code introduced by
The parameter $tceMain is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

382
    public function processDatamap_afterDatabaseOperations($status, $table, $uid, array $fields, /** @scrutinizer ignore-unused */ DataHandler $tceMain)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
383
    {
384 7
        if ($status === 'new') {
385
            // a newly created record, skip
386
            return;
387
        }
388
389 7
        if (Util::isDraftRecord($table, $uid)) {
390
            // skip workspaces: collect garbage only for LIVE workspace
391
            return;
392
        }
393
394 7
        $record = $this->getRecordWithFieldRelevantForGarbageCollection($table, $uid);
395
396
        // If no record could be found skip further processing
397 7
        if (empty($record)) {
398
            return;
399
        }
400
401 7
        $record = $this->tcaService->normalizeFrontendGroupField($table, $record);
402 7
        $isGarbage = $this->getIsGarbageRecord($table, $record);
403 7
        if (!$isGarbage) {
404 1
            return;
405
        }
406
407 6
        $this->collectGarbage($table, $uid);
408
409 6
        if ($table === 'pages') {
410 3
            $this->deleteSubpagesWhenExtendToSubpagesIsSet($table, $uid, $fields);
411
        }
412 6
    }
413
414
    /**
415
     * Check if a record is getting invisible due to changes in start or endtime. In addition it is checked that the related
416
     * queue item was marked as indexed.
417
     *
418
     * @param string $table
419
     * @param array $record
420
     * @return bool
421
     */
422 3
    protected function isInvisibleByStartOrEndtime($table, $record)
423
    {
424
        return (
425 3
            ($this->tcaService->isStartTimeInFuture($table, $record) || $this->tcaService->isEndTimeInPast($table, $record)) &&
426 3
            $this->isRelatedQueueRecordMarkedAsIndexed($table, $record)
427
        );
428
    }
429
430
    /**
431
     * Checks if the related index queue item is indexed.
432
     *
433
     * * For tt_content and pages_language_overlay the page from the pid is checked
434
     * * For all other records the table it's self is checked
435
     *
436
     * @param string $table The table name.
437
     * @param array $record An array with record fields that may affect visibility.
438
     * @return bool True if the record is marked as being indexed
439
     */
440 2
    protected function isRelatedQueueRecordMarkedAsIndexed($table, $record)
441
    {
442
        //@todo check for pages_language_overlay can be dropped when TYPO3 8 compatibility is dropped.
443 2
        if ($table === 'tt_content' || $table === 'pages_language_overlay') {
444 2
            $table = 'pages';
445 2
            $uid = $record['pid'];
446
        } else {
447
            $uid = $record['uid'];
448
        }
449
450 2
        return $this->getIndexQueue()->containsIndexedItem($table, $uid);
451
    }
452
453
    /**
454
     * @return Queue
455
     */
456 11
    private function getIndexQueue()
457
    {
458 11
        return GeneralUtility::makeInstance(Queue::class);
459
    }
460
461
    /**
462
     * Checks whether the a frontend group field exists for the record and if so
463
     * whether groups have been removed from accessing the record thus making
464
     * the record invisible to at least some people.
465
     *
466
     * @param string $table The table name.
467
     * @param array $record An array with record fields that may affect visibility.
468
     * @return bool TRUE if frontend groups have been removed from access to the record, FALSE otherwise.
469
     */
470 1
    protected function hasFrontendGroupsRemoved($table, $record)
471
    {
472 1
        if (!isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['fe_group'])) {
473
            return false;
474
        }
475
476 1
        $frontendGroupsField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['fe_group'];
477
478 1
        $previousGroups = explode(',', (string)$this->trackedRecords[$table][$record['uid']][$frontendGroupsField]);
479 1
        $currentGroups = explode(',', (string)$record[$frontendGroupsField]);
480 1
        $removedGroups = array_diff($previousGroups, $currentGroups);
481
482 1
        return (boolean)count($removedGroups);
483
    }
484
485
    /**
486
     * Checks whether the page has been excluded from searching.
487
     *
488
     * @param array $record An array with record fields that may affect visibility.
489
     * @return bool True if the page has been excluded from searching, FALSE otherwise
490
     */
491
    protected function isPageExcludedFromSearch($record)
492
    {
493
        return (boolean)$record['no_search'];
494
    }
495
496
    /**
497
     * Checks whether a page has a page type that can be indexed.
498
     * Currently standard pages and mount pages can be indexed.
499
     *
500
     * @param array $record A page record
501
     * @return bool TRUE if the page can be indexed according to its page type, FALSE otherwise
502
     */
503
    protected function isIndexablePageType(array $record)
504
    {
505
        return Util::isAllowedPageType($record);
506
    }
507
508
    /**
509
     * Determines if a record is garbage and can be deleted.
510
     *
511
     * @param string $table
512
     * @param array $record
513
     * @return bool
514
     */
515 7
    protected function getIsGarbageRecord($table, $record):bool
516
    {
517 7
        return $this->tcaService->isHidden($table, $record) ||
518 3
                $this->isInvisibleByStartOrEndtime($table, $record) ||
519 1
                $this->hasFrontendGroupsRemoved($table, $record) ||
520 1
                ($table === 'pages' && $this->isPageExcludedFromSearch($record)) ||
521 7
                ($table === 'pages' && !$this->isIndexablePageType($record));
522
    }
523
524
    /**
525
     * Returns a record with all visibility affecting fields.
526
     *
527
     * @param string $table
528
     * @param int $uid
529
     * @return array
530
     */
531 7
    protected function getRecordWithFieldRelevantForGarbageCollection($table, $uid):array
532
    {
533 7
        $garbageCollectionRelevantFields = $this->tcaService->getVisibilityAffectingFieldsByTable($table);
534 7
        $record = (array)BackendUtility::getRecord($table, $uid, $garbageCollectionRelevantFields, '', false);
535 7
        return $record;
536
    }
537
}
538