Passed
Pull Request — main (#3532)
by Markus
44:05
created

Queue::updateOrAddItemForAllRelatedRootPages()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 6.0045

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 31
ccs 19
cts 20
cp 0.95
rs 9.0111
c 0
b 0
f 0
cc 6
nc 6
nop 3
crap 6.0045
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the TYPO3 CMS project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17
18
namespace ApacheSolrForTypo3\Solr\IndexQueue;
19
20
use ApacheSolrForTypo3\Solr\Domain\Index\Queue\QueueInitializationService;
21
use ApacheSolrForTypo3\Solr\Domain\Index\Queue\QueueItemRepository;
22
use ApacheSolrForTypo3\Solr\Domain\Index\Queue\RecordMonitor\Helper\ConfigurationAwareRecordService;
23
use ApacheSolrForTypo3\Solr\Domain\Index\Queue\RecordMonitor\Helper\RootPageResolver;
24
use ApacheSolrForTypo3\Solr\Domain\Index\Queue\Statistic\QueueStatistic;
25
use ApacheSolrForTypo3\Solr\Domain\Index\Queue\Statistic\QueueStatisticsRepository;
26
use ApacheSolrForTypo3\Solr\Domain\Site\Site;
27
use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository;
28
use ApacheSolrForTypo3\Solr\FrontendEnvironment;
29
use ApacheSolrForTypo3\Solr\System\Cache\TwoLevelCache;
30
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
31
use Doctrine\DBAL\ConnectionException;
32
use Doctrine\DBAL\Driver\Exception as DBALDriverException;
33
use Doctrine\DBAL\Exception as DBALException;
34
use Throwable;
35
use TYPO3\CMS\Backend\Utility\BackendUtility;
36
use TYPO3\CMS\Core\Utility\GeneralUtility;
37
38
/**
39
 * The Indexing Queue. It allows us to decouple from frontend indexing and
40
 * reacting to the changes faster.
41
 *
42
 * @author Ingo Renner <[email protected]>
43
 */
44
class Queue
45
{
46
    /**
47
     * @var RootPageResolver
48
     */
49
    protected RootPageResolver $rootPageResolver;
50
51
    /**
52
     * @var ConfigurationAwareRecordService
53
     */
54
    protected ConfigurationAwareRecordService $recordService;
55
56
    /**
57
     * @var SolrLogManager
58
     */
59
    protected SolrLogManager $logger;
60
61
    /**
62
     * @var QueueItemRepository
63
     */
64
    protected QueueItemRepository $queueItemRepository;
65
66
    /**
67
     * @var QueueStatisticsRepository
68
     */
69
    protected QueueStatisticsRepository $queueStatisticsRepository;
70
71
    /**
72
     * @var QueueInitializationService
73
     */
74
    protected QueueInitializationService $queueInitializationService;
75
76
    /**
77
     * @var FrontendEnvironment
78
     */
79
    protected FrontendEnvironment $frontendEnvironment;
80
81
    /**
82
     * Queue constructor.
83
     * @param RootPageResolver|null $rootPageResolver
84
     * @param ConfigurationAwareRecordService|null $recordService
85
     * @param QueueItemRepository|null $queueItemRepository
86
     * @param QueueStatisticsRepository|null $queueStatisticsRepository
87
     * @param QueueInitializationService|null $queueInitializationService
88
     */
89
    public function __construct(
90 156
        RootPageResolver $rootPageResolver = null,
91
        ConfigurationAwareRecordService $recordService = null,
92
        QueueItemRepository $queueItemRepository = null,
93
        QueueStatisticsRepository $queueStatisticsRepository = null,
94
        QueueInitializationService $queueInitializationService = null,
95
        FrontendEnvironment $frontendEnvironment = null
96
    ) {
97
        $this->logger = GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__);
98 156
        $this->rootPageResolver = $rootPageResolver ?? GeneralUtility::makeInstance(RootPageResolver::class);
99 156
        $this->recordService = $recordService ?? GeneralUtility::makeInstance(ConfigurationAwareRecordService::class);
100 156
        $this->queueItemRepository = $queueItemRepository ?? GeneralUtility::makeInstance(QueueItemRepository::class);
101 156
        $this->queueStatisticsRepository = $queueStatisticsRepository ??  GeneralUtility::makeInstance(QueueStatisticsRepository::class);
102 156
        $this->queueInitializationService = $queueInitializationService ?? GeneralUtility::makeInstance(QueueInitializationService::class, /** @scrutinizer ignore-type */ $this);
103 156
        $this->frontendEnvironment = $frontendEnvironment ?? GeneralUtility::makeInstance(FrontendEnvironment::class);
104 156
    }
105
106
    // FIXME some of the methods should be renamed to plural forms
107
    // FIXME singular form methods should deal with exactly one item only
108
109
    /**
110
     * Returns the timestamp of the last indexing run.
111
     *
112
     * @param int $rootPageId The root page uid for which to get
113
     *      the last indexed item id
114
     * @return int Timestamp of last index run.
115
     * @throws DBALDriverException
116
     * @throws DBALException|\Doctrine\DBAL\DBALException
117
     */
118
    public function getLastIndexTime(int $rootPageId): int
119 2
    {
120
        $lastIndexTime = 0;
121 2
122
        $lastIndexedRow = $this->queueItemRepository->findLastIndexedRow($rootPageId);
123 2
124
        if ($lastIndexedRow[0]['indexed']) {
125 2
            $lastIndexTime = $lastIndexedRow[0]['indexed'];
126 1
        }
127
128
        return $lastIndexTime;
129 2
    }
130
131
    /**
132
     * Returns the uid of the last indexed item in the queue
133
     *
134
     * @param int $rootPageId The root page uid for which to get
135
     *      the last indexed item id
136
     * @return int The last indexed item's ID.
137
     * @throws DBALDriverException
138
     * @throws DBALException|\Doctrine\DBAL\DBALException
139
     */
140
    public function getLastIndexedItemId(int $rootPageId): int
141 3
    {
142
        $lastIndexedItemId = 0;
143 3
144
        $lastIndexedItemRow = $this->queueItemRepository->findLastIndexedRow($rootPageId);
145 3
        if ($lastIndexedItemRow[0]['uid']) {
146 3
            $lastIndexedItemId = $lastIndexedItemRow[0]['uid'];
147 2
        }
148
149
        return $lastIndexedItemId;
150 3
    }
151
152
    /**
153
     * @return QueueInitializationService
154
     */
155
    public function getInitializationService(): QueueInitializationService
156 6
    {
157
        return $this->queueInitializationService;
158 6
    }
159
160
    /**
161
     * Marks an item as needing (re)indexing.
162
     *
163
     * Like with Solr itself, there's no add method, just a simple update method
164
     * that handles the adds, too.
165
     *
166
     * The method creates or updates the index queue items for all related rootPageIds.
167
     *
168
     * @param string $itemType The item's type, usually a table name.
169
     * @param int|string $itemUid The item's uid, usually an integer uid, could be a different value for non-database-record types.
170
     * @param int $forcedChangeTime The change time for the item if set, otherwise value from getItemChangedTime() is used.
171
     * @return int Number of updated/created items
172
     * @throws DBALDriverException
173
     * @throws DBALException|\Doctrine\DBAL\DBALException
174
     * @throws Throwable
175
     */
176
    public function updateItem(string $itemType, $itemUid, int $forcedChangeTime = 0): int
177 94
    {
178
        $updateCount = $this->updateOrAddItemForAllRelatedRootPages($itemType, $itemUid, $forcedChangeTime);
179 94
        return $this->postProcessIndexQueueUpdateItem($itemType, $itemUid, $updateCount, $forcedChangeTime);
180 94
    }
181
182
    /**
183
     * Updates or adds the item for all relevant root pages.
184
     *
185
     * @param string $itemType The item's type, usually a table name.
186
     * @param int|string $itemUid The item's uid, usually an integer uid, could be a different value for non-database-record types.
187
     * @param int $forcedChangeTime The change time for the item if set, otherwise value from getItemChangedTime() is used.
188
     * @return int
189
     * @throws DBALDriverException
190
     * @throws DBALException|\Doctrine\DBAL\DBALException
191
     * @throws Throwable
192
     */
193
    protected function updateOrAddItemForAllRelatedRootPages(string $itemType, $itemUid, int $forcedChangeTime): int
194 92
    {
195
        $updateCount = 0;
196 92
        $rootPageIds = $this->rootPageResolver->getResponsibleRootPageIds($itemType, $itemUid);
0 ignored issues
show
Bug introduced by
It seems like $itemUid can also be of type string; however, parameter $uid of ApacheSolrForTypo3\Solr\...esponsibleRootPageIds() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

196
        $rootPageIds = $this->rootPageResolver->getResponsibleRootPageIds($itemType, /** @scrutinizer ignore-type */ $itemUid);
Loading history...
197
        foreach ($rootPageIds as $rootPageId) {
198 92
            $skipInvalidRootPage = $rootPageId === 0;
199 4
            if ($skipInvalidRootPage) {
200 4
                continue;
201 4
            }
202
203
            /* @var SiteRepository $siteRepository */
204 88
            $siteRepository = GeneralUtility::makeInstance(SiteRepository::class);
205 88
            $solrConfiguration = $siteRepository->getSiteByRootPageId($rootPageId)->getSolrConfiguration();
206 88
            $indexingConfiguration = $this->recordService->getIndexingConfigurationName($itemType, $itemUid, $solrConfiguration);
0 ignored issues
show
Bug introduced by
It seems like $itemUid can also be of type string; however, parameter $recordUid of ApacheSolrForTypo3\Solr\...xingConfigurationName() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

206
            $indexingConfiguration = $this->recordService->getIndexingConfigurationName($itemType, /** @scrutinizer ignore-type */ $itemUid, $solrConfiguration);
Loading history...
207
            if ($indexingConfiguration === null) {
208
                continue;
209
            }
210
            $itemInQueueForRootPage = $this->containsItemWithRootPageId($itemType, $itemUid, $rootPageId);
211 88
            if ($itemInQueueForRootPage) {
212 88
                // update changed time if that item is in the queue already
213 88
                $changedTime = ($forcedChangeTime > 0) ? $forcedChangeTime : $this->getItemChangedTime($itemType, $itemUid);
214 88
                $updatedRows = $this->queueItemRepository->updateExistingItemByItemTypeAndItemUidAndRootPageId($itemType, $itemUid, $rootPageId, $changedTime, $indexingConfiguration);
0 ignored issues
show
Bug introduced by
It seems like $itemUid can also be of type string; however, parameter $itemUid of ApacheSolrForTypo3\Solr\...dItemUidAndRootPageId() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

214
                $updatedRows = $this->queueItemRepository->updateExistingItemByItemTypeAndItemUidAndRootPageId($itemType, /** @scrutinizer ignore-type */ $itemUid, $rootPageId, $changedTime, $indexingConfiguration);
Loading history...
215 3
            } else {
216
                // add the item since it's not in the queue yet
217 87
                $updatedRows = $this->addNewItem($itemType, $itemUid, $indexingConfiguration, $rootPageId);
218 87
            }
219 87
220
            $updateCount += $updatedRows;
221 19
        }
222 19
223
        return $updateCount;
224
    }
225 80
226
    /**
227
     * Executes the updateItem post-processing hook.
228 87
     *
229
     * @param string $itemType
230
     * @param int|string $itemUid The item's uid, usually an integer uid, could be a different value for non-database-record types.
231 88
     * @param int $updateCount
232
     * @param int $forcedChangeTime
233
     * @return int
234
     */
235
    protected function postProcessIndexQueueUpdateItem(
236
        string $itemType,
237
        $itemUid,
238
        int $updateCount,
239
        int $forcedChangeTime = 0
240
    ): int {
241
        if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessIndexQueueUpdateItem'] ?? null)) {
242
            return $updateCount;
243 94
        }
244
245
        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessIndexQueueUpdateItem'] as $classReference) {
246
            $updateHandler = $this->getHookImplementation($classReference);
247
            $updateCount = $updateHandler->postProcessIndexQueueUpdateItem($itemType, $itemUid, $updateCount, $forcedChangeTime);
248
        }
249 94
250 93
        return $updateCount;
251
    }
252
253 1
    /**
254 1
     * @param string $classReference
255 1
     * @return object
256
     */
257
    protected function getHookImplementation(string $classReference): object
258 1
    {
259
        return GeneralUtility::makeInstance($classReference);
260
    }
261
262
    /**
263
     * Finds indexing errors for the current site
264
     *
265
     * @param Site $site
266
     * @return array Error items for the current site's Index Queue
267
     * @throws DBALDriverException
268
     * @throws DBALException|\Doctrine\DBAL\DBALException
269
     */
270
    public function getErrorsBySite(Site $site): array
271
    {
272
        return $this->queueItemRepository->findErrorsBySite($site);
273
    }
274
275
    /**
276
     * Resets all the errors for all index queue items.
277
     *
278 3
     * @return mixed
279
     * @throws DBALException|\Doctrine\DBAL\DBALException
280 3
     */
281
    public function resetAllErrors()
282
    {
283
        return $this->queueItemRepository->flushAllErrors();
284
    }
285
286
    /**
287
     * Resets the errors in the index queue for a specific site
288
     *
289 1
     * @param Site $site
290
     * @return mixed
291 1
     * @throws DBALException|\Doctrine\DBAL\DBALException
292
     */
293
    public function resetErrorsBySite(Site $site)
294
    {
295
        return $this->queueItemRepository->flushErrorsBySite($site);
296
    }
297
298
    /**
299
     * Resets the error in the index queue for a specific item
300
     *
301 1
     * @param Item $item
302
     * @return mixed
303 1
     * @throws DBALException|\Doctrine\DBAL\DBALException
304
     */
305
    public function resetErrorByItem(Item $item)
306
    {
307
        return $this->queueItemRepository->flushErrorByItem($item);
308
    }
309
310
    /**
311
     * Adds an item to the index queue.
312
     *
313 1
     * Not meant for public use.
314
     *
315 1
     * @param string $itemType The item's type, usually a table name.
316
     * @param int|string $itemUid The item's uid, usually an integer uid, could be a
317
     *      different value for non-database-record types.
318
     * @param string $indexingConfiguration The item's indexing configuration to use.
319
     *      Optional, overwrites existing / determined configuration.
320
     * @param int $rootPageId
321
     * @return int
322
     * @throws DBALDriverException
323
     * @throws DBALException|\Doctrine\DBAL\DBALException
324
     */
325
    private function addNewItem(
326
        string $itemType,
327
        $itemUid,
328
        string $indexingConfiguration,
329
        int $rootPageId
330
    ): int {
331
        $additionalRecordFields = '';
332
        if ($itemType === 'pages') {
333
            $additionalRecordFields = ', doktype, uid';
334 80
        }
335
336
        $record = $this->getRecordCached($itemType, $itemUid, $additionalRecordFields);
337
338
        if (empty($record) || ($itemType === 'pages' && !$this->frontendEnvironment->isAllowedPageType($record, $indexingConfiguration))) {
339
            return 0;
340
        }
341 80
342 80
        $changedTime = $this->getItemChangedTime($itemType, $itemUid);
343 52
344
        return $this->queueItemRepository->add($itemType, $itemUid, $rootPageId, $changedTime, $indexingConfiguration);
0 ignored issues
show
Bug introduced by
It seems like $itemUid can also be of type string; however, parameter $itemUid of ApacheSolrForTypo3\Solr\...ueItemRepository::add() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

344
        return $this->queueItemRepository->add($itemType, /** @scrutinizer ignore-type */ $itemUid, $rootPageId, $changedTime, $indexingConfiguration);
Loading history...
345
    }
346 80
347
    /**
348 80
     * Get record to be added in addNewItem
349
     *
350
     * @param string $itemType The item's type, usually a table name.
351
     * @param int|string $itemUid The item's uid, usually an integer uid, could be a
352 80
     *      different value for non-database-record types.
353
     * @param string $additionalRecordFields for sql-query
354 80
     *
355
     * @return array|null
356
     */
357
    protected function getRecordCached(string $itemType, $itemUid, string $additionalRecordFields): ?array
358
    {
359
        $cache = GeneralUtility::makeInstance(TwoLevelCache::class, /** @scrutinizer ignore-type */ 'runtime');
360
        $cacheId = md5('Queue' . ':' . 'getRecordCached' . ':' . $itemType . ':' . $itemUid . ':' . 'pid' . $additionalRecordFields);
361
362
        $record = $cache->get($cacheId);
363
        if (empty($record)) {
364
            $record = BackendUtility::getRecord($itemType, $itemUid, 'pid' . $additionalRecordFields);
365
            $cache->set($cacheId, $record);
366
        }
367 80
368
        return $record;
369 80
    }
370 80
371
    /**
372 80
     * Determines the time for when an item should be indexed. This timestamp
373 80
     * is then stored in the changed column in the Index Queue.
374 80
     *
375 80
     * The changed timestamp usually is now - time(). For records which are set
376
     * to published at a later time, this timestamp is the start time. So if a
377
     * future start time has been set, that will be used to delay indexing
378 80
     * of an item.
379
     *
380
     * @param string $itemType The item's table name.
381
     * @param int|string $itemUid The item's uid, usually an integer uid, could be a
382
     *      different value for non-database-record types.
383
     * @return int Timestamp of the item's changed time or future start time
384
     * @throws DBALDriverException
385
     * @throws DBALException|\Doctrine\DBAL\DBALException
386
     */
387
    protected function getItemChangedTime(string $itemType, $itemUid): int
388
    {
389
        $itemTypeHasStartTimeColumn = false;
390
        $changedTimeColumns = $GLOBALS['TCA'][$itemType]['ctrl']['tstamp'];
391
        $startTime = 0;
392
        $pageChangedTime = 0;
393
394
        if (!empty($GLOBALS['TCA'][$itemType]['ctrl']['enablecolumns']['starttime'])) {
395
            $itemTypeHasStartTimeColumn = true;
396
            $changedTimeColumns .= ', ' . $GLOBALS['TCA'][$itemType]['ctrl']['enablecolumns']['starttime'];
397 87
        }
398
        if ($itemType === 'pages') {
399 87
            // does not carry time information directly, but needed to support
400 87
            // canonical pages
401 87
            $changedTimeColumns .= ', content_from_pid';
402 87
        }
403
404 87
        $record = BackendUtility::getRecord($itemType, $itemUid, $changedTimeColumns);
405 87
        $itemChangedTime = $record[$GLOBALS['TCA'][$itemType]['ctrl']['tstamp']];
406 87
407
        if ($itemTypeHasStartTimeColumn) {
408 87
            $startTime = $record[$GLOBALS['TCA'][$itemType]['ctrl']['enablecolumns']['starttime']];
409
        }
410
411 59
        if ($itemType === 'pages') {
412
            $record['uid'] = $itemUid;
413
            // overrule the page's last changed time with the most recent
414 87
            //content element change
415 87
            $pageChangedTime = $this->getPageItemChangedTime($record);
0 ignored issues
show
Bug introduced by
It seems like $record can also be of type null; however, parameter $page of ApacheSolrForTypo3\Solr\...etPageItemChangedTime() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

415
            $pageChangedTime = $this->getPageItemChangedTime(/** @scrutinizer ignore-type */ $record);
Loading history...
416
        }
417 87
418 87
        $localizationsChangedTime = $this->queueItemRepository->getLocalizableItemChangedTime($itemType, (int)$itemUid);
419
420
        // if start time exists and start time is higher than last changed timestamp
421 87
        // then set changed to the future start time to make the item
422 59
        // indexed at a later time
423
        return (int)max(
424
            $itemChangedTime,
425 59
            $pageChangedTime,
426
            $localizationsChangedTime,
427
            $startTime
428 87
        );
429
    }
430
431
    /**
432
     * Gets the most recent changed time of a page's content elements
433 87
     *
434 87
     * @param array $page Partial page record
435 87
     * @return int Timestamp of the most recent content element change
436 87
     * @throws DBALDriverException
437 87
     * @throws DBALException|\Doctrine\DBAL\DBALException
438 87
     */
439
    protected function getPageItemChangedTime(array $page): int
440
    {
441
        if (!empty($page['content_from_pid'])) {
442
            // canonical page, get the original page's last changed time
443
            return $this->queueItemRepository->getPageItemChangedTimeByPageUid((int)$page['content_from_pid']);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->queueItemR...ge['content_from_pid']) could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
444
        }
445
        return $this->queueItemRepository->getPageItemChangedTimeByPageUid((int)$page['uid']) ?? 0;
446
    }
447
448
    /**
449 59
     * Checks whether the Index Queue contains a specific item.
450
     *
451 59
     * @param string $itemType The item's type, usually a table name.
452
     * @param int|string $itemUid The item's uid, usually an integer uid, could be a
453
     *      different value for non-database-record types.
454
     * @return bool TRUE if the item is found in the queue, FALSE otherwise
455 59
     * @throws DBALDriverException
456
     * @throws DBALException|\Doctrine\DBAL\DBALException
457
     */
458
    public function containsItem(string $itemType, $itemUid): bool
459
    {
460
        return $this->queueItemRepository->containsItem($itemType, (int)$itemUid);
461
    }
462
463
    /**
464
     * Checks whether the Index Queue contains a specific item.
465
     *
466
     * @param string $itemType The item's type, usually a table name.
467
     * @param int|string $itemUid The item's uid, usually an integer uid, could be a
468 10
     *      different value for non-database-record types.
469
     * @param int $rootPageId
470 10
     * @return bool TRUE if the item is found in the queue, FALSE otherwise
471
     * @throws DBALDriverException
472
     * @throws DBALException|\Doctrine\DBAL\DBALException
473
     */
474
    public function containsItemWithRootPageId(string $itemType, $itemUid, int $rootPageId): bool
475
    {
476
        return $this->queueItemRepository->containsItemWithRootPageId($itemType, (int)$itemUid, $rootPageId);
477
    }
478
479
    /**
480
     * Checks whether the Index Queue contains a specific item that has been
481
     * marked as indexed.
482
     *
483
     * @param string $itemType The item's type, usually a table name.
484 87
     * @param int|string $itemUid The item's uid, usually an integer uid, could be a
485
     *      different value for non-database-record types.
486 87
     * @return bool TRUE if the item is found in the queue and marked as
487
     *      indexed, FALSE otherwise
488
     * @throws DBALDriverException
489
     * @throws DBALException|\Doctrine\DBAL\DBALException
490
     */
491
    public function containsIndexedItem(string $itemType, $itemUid): bool
492
    {
493
        return $this->queueItemRepository->containsIndexedItem($itemType, (int)$itemUid);
494
    }
495
496
    /**
497
     * Removes an item from the Index Queue.
498
     *
499
     * @param string $itemType The type of the item to remove, usually a table name.
500
     * @param int|string $itemUid The uid of the item to remove
501 4
     * @throws ConnectionException
502
     * @throws DBALException
503 4
     * @throws Throwable
504
     */
505
    public function deleteItem(string $itemType, $itemUid)
506
    {
507
        $this->queueItemRepository->deleteItem($itemType, (int)$itemUid);
508
    }
509
510
    /**
511
     * Removes all items of a certain type from the Index Queue.
512
     *
513
     * @param string $itemType The type of items to remove, usually a table name.
514
     * @throws ConnectionException
515 61
     * @throws DBALException
516
     * @throws Throwable
517 61
     */
518
    public function deleteItemsByType(string $itemType)
519
    {
520
        $this->queueItemRepository->deleteItemsByType($itemType);
521
    }
522
523
    /**
524
     * Removes all items of a certain site from the Index Queue. Accepts an
525
     * optional parameter to limit the deleted items by indexing configuration.
526
     *
527
     * @param Site $site The site to remove items for.
528 1
     * @param string $indexingConfigurationName Name of a specific indexing
529
     *      configuration
530 1
     * @throws ConnectionException
531
     * @throws \Doctrine\DBAL\DBALException
532
     * @throws Throwable
533
     */
534
    public function deleteItemsBySite(Site $site, string $indexingConfigurationName = '')
535
    {
536
        $this->queueItemRepository->deleteItemsBySite($site, $indexingConfigurationName);
537
    }
538
539
    /**
540
     * Removes all items from the Index Queue.
541
     */
542
    public function deleteAllItems()
543
    {
544 6
        $this->queueItemRepository->deleteAllItems();
545
    }
546 6
547
    /**
548
     * Gets a single Index Queue item by its uid.
549
     *
550
     * @param int $itemId Index Queue item uid
551
     * @return Item|null The request Index Queue item or NULL if no item with $itemId was found
552 1
     * @throws DBALDriverException
553
     * @throws DBALException|\Doctrine\DBAL\DBALException
554 1
     */
555
    public function getItem(int $itemId): ?Item
556
    {
557
        return $this->queueItemRepository->findItemByUid($itemId);
558
    }
559
560
    /**
561
     * Gets Index Queue items by type and uid.
562
     *
563
     * @param string $itemType item type, usually  the table name
564
     * @param int|string $itemUid item uid
565 34
     * @return Item[] An array of items matching $itemType and $itemUid
566
     * @throws ConnectionException
567 34
     * @throws DBALDriverException
568
     * @throws DBALException
569
     * @throws Throwable
570
     */
571
    public function getItems(string $itemType, $itemUid): array
572
    {
573
        return $this->queueItemRepository->findItemsByItemTypeAndItemUid($itemType, (int)$itemUid);
574
    }
575
576
    /**
577
     * Returns all items in the queue.
578
     *
579
     * @return Item[] An array of items
580
     * @throws ConnectionException
581 52
     * @throws DBALDriverException
582
     * @throws DBALException
583 52
     * @throws Throwable
584
     */
585
    public function getAllItems(): array
586
    {
587
        return $this->queueItemRepository->findAll();
588
    }
589
590
    /**
591
     * Returns the number of items for all queues.
592
     *
593
     * @return int
594
     * @throws DBALDriverException
595 4
     * @throws DBALException
596
     */
597 4
    public function getAllItemsCount(): int
598
    {
599
        return $this->queueItemRepository->count();
600
    }
601
602
    /**
603
     * Extracts the number of pending, indexed and erroneous items from the
604
     * Index Queue.
605
     *
606
     * @param Site $site
607 112
     * @param string $indexingConfigurationName
608
     *
609 112
     * @return QueueStatistic
610
     * @throws DBALDriverException
611
     * @throws DBALException
612
     */
613
    public function getStatisticsBySite(Site $site, string $indexingConfigurationName = ''): QueueStatistic
614
    {
615
        return $this->queueStatisticsRepository
616
            ->findOneByRootPidAndOptionalIndexingConfigurationName(
617
                $site->getRootPageId(),
618
                $indexingConfigurationName
619
            );
620
    }
621
622
    /**
623 5
     * Gets $limit number of items to index for a particular $site.
624
     *
625 5
     * @param Site $site TYPO3 site
626 5
     * @param int $limit Number of items to get from the queue
627 5
     * @return Item[] Items to index to the given solr server
628 5
     * @throws ConnectionException
629 5
     * @throws DBALDriverException
630
     * @throws DBALException
631
     * @throws Throwable
632
     */
633
    public function getItemsToIndex(Site $site, int $limit = 50): array
634
    {
635
        return $this->queueItemRepository->findItemsToIndex($site, $limit);
636
    }
637
638
    /**
639
     * Marks an item as failed and causes the indexer to skip the item in the
640
     * next run.
641
     *
642
     * @param int|Item $item Either the item's Index Queue uid or the complete item
643 3
     * @param string $errorMessage Error message
644
     * @throws DBALException|\Doctrine\DBAL\DBALException
645 3
     */
646
    public function markItemAsFailed($item, string $errorMessage = '')
647
    {
648
        $this->queueItemRepository->markItemAsFailed($item, $errorMessage);
649
    }
650
651
    /**
652
     * Sets the timestamp of when an item last has been indexed.
653
     *
654
     * @param Item $item
655
     * @throws DBALException|\Doctrine\DBAL\DBALException
656 6
     */
657
    public function updateIndexTimeByItem(Item $item)
658 6
    {
659
        $this->queueItemRepository->updateIndexTimeByItem($item);
660
    }
661
662
    /**
663
     * Sets the change timestamp of an item.
664
     *
665
     * @param Item $item
666
     * @param int $forcedChangeTime The change time for the item
667 2
     * @throws DBALException|\Doctrine\DBAL\DBALException
668
     */
669 2
    public function setForcedChangeTimeByItem(Item $item, int $forcedChangeTime = 0)
670
    {
671
        $this->queueItemRepository->updateChangedTimeByItem($item, $forcedChangeTime);
672
    }
673
}
674