Passed
Pull Request — main (#3548)
by Rafael
33:40 queued 29:56
created

QueueItemRepository   F

Complexity

Total Complexity 70

Size/Duplication

Total Lines 1100
Duplicated Lines 0 %

Test Coverage

Coverage 96.28%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 70
eloc 362
c 2
b 0
f 0
dl 0
loc 1100
ccs 414
cts 430
cp 0.9628
rs 2.8

40 Methods

Rating   Name   Duplication   Size   Complexity  
A flushAllErrors() 0 5 1
A flushErrorByItem() 0 9 1
A flushErrorsBySite() 0 9 1
A findLastIndexedRow() 0 18 1
A getPreparedFlushErrorQuery() 0 8 1
A findErrorsBySite() 0 13 1
A __construct() 0 6 1
A containsItem() 0 5 1
A updateIndexTimeByItem() 0 8 1
A updateChangedTimeByItem() 0 8 1
A getItemsByCompositeExpression() 0 17 3
A deleteItemsBySite() 0 4 2
A containsItemWithRootPageId() 0 7 1
A deleteItemsByType() 0 3 1
A deleteItem() 0 4 2
A getIndexQueueItemObjectsFromRecords() 0 4 1
A findItemByUid() 0 15 2
A findAll() 0 9 1
A initializeByNativeSQLStatement() 0 5 1
A deleteItems() 0 28 2
A hookPostProcessFetchRecordsForIndexQueueItem() 0 8 3
A findItems() 0 21 1
A deleteAllItems() 0 3 1
A getAllQueueItemRecordsByUidsGroupedByTable() 0 30 4
A containsIndexedItem() 0 7 1
A add() 0 21 1
A getLocalizableItemChangedTime() 0 23 2
A updateExistingItemByItemTypeAndItemUidAndRootPageId() 0 27 2
A findAllIndexQueueItemsByRootPidAndMountIdentifierAndMountedPids() 0 18 1
A markItemAsFailed() 0 11 3
A findPageIdsOfExistingMountPagesByMountIdentifier() 0 22 3
A getPageItemChangedTimeByPageUid() 0 16 1
A countItems() 0 27 1
A getQueryBuilderForContainsMethods() 0 9 1
A findItemsByItemTypeAndItemUid() 0 9 1
B addItemWhereClauses() 0 50 6
B buildQueryForPropertyDeletion() 0 47 7
A findItemsToIndex() 0 25 1
A updateHasIndexingPropertiesFlagByItemUid() 0 14 1
A getQueueItemObjectsByRecords() 0 28 3

How to fix   Complexity   

Complex Class

Complex classes like QueueItemRepository 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.

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 QueueItemRepository, and based on these observations, apply Extract Interface, too.

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\Domain\Index\Queue;
19
20
use ApacheSolrForTypo3\Solr\Domain\Site\Site;
21
use ApacheSolrForTypo3\Solr\IndexQueue\Item;
22
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
23
use ApacheSolrForTypo3\Solr\System\Records\AbstractRepository;
24
use Doctrine\DBAL\ConnectionException;
25
use Doctrine\DBAL\Driver\Exception as DBALDriverException;
26
use Doctrine\DBAL\Exception as DBALException;
27
use PDO;
28
use Throwable;
29
use TYPO3\CMS\Core\Database\ConnectionPool;
30
use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
31
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
32
use TYPO3\CMS\Core\Utility\GeneralUtility;
33
34
/**
35
 * Class QueueItemRepository
36
 * Handles all CRUD operations to tx_solr_indexqueue_item table
37
 */
38
class QueueItemRepository extends AbstractRepository
39
{
40
    /**
41
     * @var string
42
     */
43
    protected string $table = 'tx_solr_indexqueue_item';
44
45
    /**
46
     * @var SolrLogManager
47
     */
48
    protected SolrLogManager $logger;
49
50
    /**
51
     * QueueItemRepository constructor.
52
     *
53
     * @param SolrLogManager|null $logManager
54
     */
55 170
    public function __construct(SolrLogManager $logManager = null)
56
    {
57 170
        $this->logger = $logManager ?? GeneralUtility::makeInstance(
58 170
            SolrLogManager::class,
59
            /** @scrutinizer ignore-type */
60 170
            __CLASS__
61 170
        );
62
    }
63
64
    /**
65
     * Fetches the last indexed row
66
     *
67
     * @param int $rootPageId The root page uid for which to get the last indexed row
68
     * @return array
69
     *
70
     * @throws DBALDriverException
71
     * @throws DBALException|\Doctrine\DBAL\DBALException
72
     */
73 5
    public function findLastIndexedRow(int $rootPageId): array
74
    {
75 5
        $queryBuilder = $this->getQueryBuilder();
76 5
        return $queryBuilder
77 5
            ->select('uid', 'indexed')
78 5
            ->from($this->table)
79 5
            ->where(
80
                /** @scrutinizer ignore-type */
81 5
                $queryBuilder->expr()->eq('root', $rootPageId)
82 5
            )
83 5
            ->andWhere(
84
                /** @scrutinizer ignore-type */
85 5
                $queryBuilder->expr()->neq('indexed', 0)
86 5
            )
87 5
            ->orderBy('indexed', 'DESC')
88 5
            ->setMaxResults(1)
89 5
            ->execute()
90 5
            ->fetchAllAssociative();
91
    }
92
93
    /**
94
     * Finds indexing errors for the current site
95
     *
96
     * @param Site $site
97
     * @return array Error items for the current site's Index Queue
98
     *
99
     * @throws DBALDriverException
100
     * @throws DBALException|\Doctrine\DBAL\DBALException
101
     */
102 3
    public function findErrorsBySite(Site $site): array
103
    {
104 3
        $queryBuilder = $this->getQueryBuilder();
105 3
        return $queryBuilder
106 3
            ->select('uid', 'item_type', 'item_uid', 'errors')
107 3
            ->from($this->table)
108 3
            ->andWhere(
109
                /** @scrutinizer ignore-type */
110 3
                $queryBuilder->expr()->notLike('errors', $queryBuilder->createNamedParameter('')),
111 3
                $queryBuilder->expr()->eq('root', $site->getRootPageId())
112 3
            )
113 3
            ->execute()
114 3
            ->fetchAllAssociative();
115
    }
116
117
    /**
118
     * Resets all the errors for all index queue items.
119
     *
120
     * @return int affected rows
121
     *
122
     * @throws DBALException|\Doctrine\DBAL\DBALException
123
     */
124 1
    public function flushAllErrors(): int
125
    {
126 1
        $queryBuilder = $this->getQueryBuilder();
127 1
        return (int)$this->getPreparedFlushErrorQuery($queryBuilder)
128 1
            ->execute();
129
    }
130
131
    /**
132
     * Flushes the errors for a single site.
133
     *
134
     * @param Site $site
135
     * @return int
136
     *
137
     * @throws DBALException|\Doctrine\DBAL\DBALException
138
     */
139 1
    public function flushErrorsBySite(Site $site): int
140
    {
141 1
        $queryBuilder = $this->getQueryBuilder();
142 1
        return (int)$this->getPreparedFlushErrorQuery($queryBuilder)
143 1
            ->andWhere(
144
                /** @scrutinizer ignore-type */
145 1
                $queryBuilder->expr()->eq('root', $site->getRootPageId())
146 1
            )
147 1
            ->execute();
148
    }
149
150
    /**
151
     * Flushes the error for a single item.
152
     *
153
     * @param Item $item
154
     * @return int affected rows
155
     *
156
     * @throws DBALException|\Doctrine\DBAL\DBALException
157
     */
158 2
    public function flushErrorByItem(Item $item): int
159
    {
160 2
        $queryBuilder = $this->getQueryBuilder();
161 2
        return (int)$this->getPreparedFlushErrorQuery($queryBuilder)
162 2
            ->andWhere(
163
                /** @scrutinizer ignore-type */
164 2
                $queryBuilder->expr()->eq('uid', $item->getIndexQueueUid())
165 2
            )
166 2
            ->execute();
167
    }
168
169
    /**
170
     * Initializes the QueryBuilder with a query the resets the error field for items that have an error.
171
     *
172
     * @param QueryBuilder $queryBuilder
173
     * @return QueryBuilder
174
     */
175 4
    private function getPreparedFlushErrorQuery(QueryBuilder $queryBuilder): QueryBuilder
176
    {
177 4
        return $queryBuilder
178 4
            ->update($this->table)
179 4
            ->set('errors', '')
180 4
            ->where(
181
                /** @scrutinizer ignore-type */
182 4
                $queryBuilder->expr()->notLike('errors', $queryBuilder->createNamedParameter(''))
183 4
            );
184
    }
185
186
    /**
187
     * Updates an existing queue entry by $itemType $itemUid and $rootPageId.
188
     *
189
     * @param string $itemType The item's type, usually a table name.
190
     * @param int $itemUid The item's uid, usually an integer uid, could be a
191
     *      different value for non-database-record types.
192
     * @param int $rootPageId The uid of the rootPage
193
     * @param int $changedTime The forced change time that should be used for updating
194
     * @param string $indexingConfiguration The name of the related indexConfiguration
195
     * @param int $indexingPriority
196
     * @return int affected rows
197
     *
198
     * @throws DBALException|\Doctrine\DBAL\DBALException
199 19
     */
200
    public function updateExistingItemByItemTypeAndItemUidAndRootPageId(
201
        string $itemType,
202
        int $itemUid,
203
        int $rootPageId,
204
        int $changedTime,
205
        string $indexingConfiguration = '',
206 19
        int $indexingPriority = 0
207 19
    ): int {
208 19
        $queryBuilder = $this->getQueryBuilder();
209 19
        $queryBuilder
210 19
            ->update($this->table)
211
            ->set('changed', $changedTime)
212 19
            ->set('indexing_priority', $indexingPriority)
213
            ->andWhere(
214 19
                /** @scrutinizer ignore-type */
215
                $queryBuilder->expr()->eq('item_type', $queryBuilder->createNamedParameter($itemType)),
216 19
                /** @scrutinizer ignore-type */
217 19
                $queryBuilder->expr()->eq('item_uid', $itemUid),
218
                /** @scrutinizer ignore-type */
219 19
                $queryBuilder->expr()->eq('root', $rootPageId)
220 19
            );
221
222
        if (!empty($indexingConfiguration)) {
223 19
            $queryBuilder->set('indexing_configuration', $indexingConfiguration);
224
        }
225
226
        return (int)$queryBuilder->execute();
227
    }
228
229
    /**
230
     * Adds an item to the index queue.
231
     *
232
     * Not meant for public use.
233
     *
234
     * @param string $itemType The item's type, usually a table name.
235
     * @param int $itemUid The item's uid, usually an integer uid, could be a different value for non-database-record types.
236
     * @param int $rootPageId
237
     * @param int $changedTime
238
     * @param string $indexingConfiguration The item's indexing configuration to use. Optional, overwrites existing / determined configuration.
239
     * @param int $indexingPriority
240 81
     * @return int the number of inserted rows, which is typically 1
241
     *
242
     * @throws DBALException|\Doctrine\DBAL\DBALException
243
     */
244
    public function add(
245
        string $itemType,
246
        int $itemUid,
247 81
        int $rootPageId,
248 81
        int $changedTime,
249 81
        string $indexingConfiguration,
250 81
        int $indexingPriority = 0
251 81
    ): int {
252 81
        $queryBuilder = $this->getQueryBuilder();
253 81
        return (int)$queryBuilder
254 81
            ->insert($this->table)
255 81
            ->values([
256 81
                'root' => $rootPageId,
257 81
                'item_type' => $itemType,
258 81
                'item_uid' => $itemUid,
259
                'changed' => $changedTime,
260
                'errors' => '',
261
                'indexing_configuration' => $indexingConfiguration,
262
                'indexing_priority' => $indexingPriority,
263
            ])
264
            ->execute();
265
    }
266
267
    /**
268
     * Retrieves the count of items that match certain filters. Each filter is passed as parts of the where claus combined with AND.
269
     *
270
     * @param array $sites
271
     * @param array $indexQueueConfigurationNames
272
     * @param array $itemTypes
273
     * @param array $itemUids
274 1
     * @param array $uids
275
     * @return int
276
     *
277
     * @throws DBALDriverException
278
     * @throws DBALException|\Doctrine\DBAL\DBALException
279
     */
280
    public function countItems(
281 1
        array $sites = [],
282 1
        array $indexQueueConfigurationNames = [],
283 1
        array $itemTypes = [],
284 1
        array $itemUids = [],
285 1
        array $uids = []
286
    ): int {
287 1
        $rootPageIds = Site::getRootPageIdsFromSites($sites);
288 1
        $indexQueueConfigurationList = implode(',', $indexQueueConfigurationNames);
289 1
        $itemTypeList = implode(',', $itemTypes);
290 1
        $itemUids = array_map('intval', $itemUids);
291 1
        $uids = array_map('intval', $uids);
292 1
293 1
        $queryBuilderForCountingItems = $this->getQueryBuilder();
294 1
        $queryBuilderForCountingItems->count('uid')->from($this->table);
295 1
        $queryBuilderForCountingItems = $this->addItemWhereClauses(
296 1
            $queryBuilderForCountingItems,
297
            $rootPageIds,
298 1
            $indexQueueConfigurationList,
299 1
            $itemTypeList,
300 1
            $itemUids,
301
            $uids
302
        );
303
304
        return (int)$queryBuilderForCountingItems
305
            ->execute()
306
            ->fetchOne();
307
    }
308
309
    /**
310
     * Gets the most recent changed time of a page's content elements
311
     *
312 59
     * @param int $pageUid
313
     * @return int|null Timestamp of the most recent content element change or null if nothing is found.
314 59
     *
315 59
     * @throws DBALDriverException
316 59
     * @throws DBALException|\Doctrine\DBAL\DBALException
317 59
     */
318 59
    public function getPageItemChangedTimeByPageUid(int $pageUid): ?int
319 59
    {
320 59
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
321
            ->getQueryBuilderForTable('tt_content');
322 59
        $queryBuilder->getRestrictions()->removeAll();
323 59
        $pageContentLastChangedTime = $queryBuilder
324 59
            ->add('select', $queryBuilder->expr()->max('tstamp', 'changed_time'))
325 59
            ->from('tt_content')
326
            ->where(
327 59
                /** @scrutinizer ignore-type */
328
                $queryBuilder->expr()->eq('pid', $pageUid)
329
            )
330
            ->execute()
331
            ->fetchAssociative();
332
333
        return $pageContentLastChangedTime['changed_time'];
334
    }
335
336
    /**
337
     * Gets the most recent changed time for an item taking into account
338
     * localized records.
339
     *
340
     * @param string $itemType The item's type, usually a table name.
341 87
     * @param int $itemUid The item's uid
342
     * @return int Timestamp of the most recent content element change
343 87
     *
344
     * @throws DBALDriverException
345 87
     * @throws DBALException|\Doctrine\DBAL\DBALException
346
     */
347 87
    public function getLocalizableItemChangedTime(string $itemType, int $itemUid): int
348 87
    {
349
        $localizedChangedTime = 0;
350 87
351 87
        if (isset($GLOBALS['TCA'][$itemType]['ctrl']['transOrigPointerField'])) {
352 87
            // table is localizable
353 87
            $translationOriginalPointerField = $GLOBALS['TCA'][$itemType]['ctrl']['transOrigPointerField'];
354 87
            $timeStampField = $GLOBALS['TCA'][$itemType]['ctrl']['tstamp'];
355 87
356
            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($itemType);
357 87
            $queryBuilder->getRestrictions()->removeAll();
358 87
            $localizedChangedTime = $queryBuilder
359 87
                ->add('select', $queryBuilder->expr()->max($timeStampField, 'changed_time'))
360 87
                ->from($itemType)
361 87
                ->orWhere(
362
                    /** @scrutinizer ignore-type */
363 87
                    $queryBuilder->expr()->eq('uid', $itemUid),
364
                    $queryBuilder->expr()->eq($translationOriginalPointerField, $itemUid)
365
                )
366
                ->execute()
367
                ->fetchOne();
368
        }
369
        return (int)$localizedChangedTime;
370
    }
371
372
    /**
373 94
     * Returns prepared QueryBuilder for contains* methods in this repository
374
     *
375 94
     * @param string $itemType
376 94
     * @param int $itemUid
377 94
     * @return QueryBuilder
378
     */
379 94
    protected function getQueryBuilderForContainsMethods(string $itemType, int $itemUid): QueryBuilder
380
    {
381 94
        $queryBuilder = $this->getQueryBuilder();
382 94
        return $queryBuilder->count('uid')->from($this->table)
383
            ->andWhere(
384
                /** @scrutinizer ignore-type */
385
                $queryBuilder->expr()->eq('item_type', $queryBuilder->createNamedParameter($itemType)),
386
                /** @scrutinizer ignore-type */
387
                $queryBuilder->expr()->eq('item_uid', $itemUid)
388
            );
389
    }
390
391
    /**
392
     * Checks whether the Index Queue contains a specific item.
393
     *
394
     * @param string $itemType The item's type, usually a table name.
395 10
     * @param int $itemUid The item's uid
396
     * @return bool TRUE if the item is found in the queue, FALSE otherwise
397 10
     *
398 10
     * @throws DBALDriverException
399 10
     * @throws DBALException|\Doctrine\DBAL\DBALException
400
     */
401
    public function containsItem(string $itemType, int $itemUid): bool
402
    {
403
        return (bool)$this->getQueryBuilderForContainsMethods($itemType, $itemUid)
404
            ->execute()
405
            ->fetchOne();
406
    }
407
408
    /**
409
     * Checks whether the Index Queue contains a specific item.
410
     *
411
     * @param string $itemType The item's type, usually a table name.
412
     * @param int $itemUid The item's uid
413 87
     * @param int $rootPageId
414
     * @return bool TRUE if the item is found in the queue, FALSE otherwise
415 87
     *
416 87
     * @throws DBALDriverException
417 87
     * @throws DBALException|\Doctrine\DBAL\DBALException
418 87
     */
419 87
    public function containsItemWithRootPageId(string $itemType, int $itemUid, int $rootPageId): bool
420
    {
421
        $queryBuilder = $this->getQueryBuilderForContainsMethods($itemType, $itemUid);
422
        return (bool)$queryBuilder
423
            ->andWhere(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('root', $rootPageId))
424
            ->execute()
425
            ->fetchOne();
426
    }
427
428
    /**
429
     * Checks whether the Index Queue contains a specific item that has been
430
     * marked as indexed.
431
     *
432
     * @param string $itemType The item's type, usually a table name.
433 4
     * @param int $itemUid The item's uid
434
     * @return bool TRUE if the item is found in the queue and marked as indexed, FALSE otherwise
435 4
     *
436 4
     * @throws DBALDriverException
437 4
     * @throws DBALException|\Doctrine\DBAL\DBALException
438 4
     */
439 4
    public function containsIndexedItem(string $itemType, int $itemUid): bool
440
    {
441
        $queryBuilder = $this->getQueryBuilderForContainsMethods($itemType, $itemUid);
442
        return (bool)$queryBuilder
443
            ->andWhere(/** @scrutinizer ignore-type */ $queryBuilder->expr()->gt('indexed', 0))
444
            ->execute()
445
            ->fetchOne();
446
    }
447
448
    /**
449
     * Removes an item from the Index Queue.
450
     *
451
     * @param string $itemType The type of the item to remove, usually a table name.
452 64
     * @param int|null $itemUid The uid of the item to remove
453
     *
454 64
     * @throws ConnectionException
455 64
     * @throws Throwable
456
     * @throws DBALException
457
     */
458
    public function deleteItem(string $itemType, int $itemUid = null)
459
    {
460
        $itemUids = empty($itemUid) ? [] : [$itemUid];
461
        $this->deleteItems([], [], [$itemType], $itemUids);
462
    }
463
464
    /**
465
     * Removes all items of a certain type from the Index Queue.
466
     *
467 1
     * @param string $itemType The type of items to remove, usually a table name.
468
     *
469 1
     * @throws ConnectionException
470
     * @throws Throwable
471
     * @throws DBALException
472
     */
473
    public function deleteItemsByType(string $itemType)
474
    {
475
        $this->deleteItem($itemType);
476
    }
477
478
    /**
479
     * Removes all items of a certain site from the Index Queue. Accepts an
480
     * optional parameter to limit the deleted items by indexing configuration.
481
     *
482
     * @param Site $site The site to remove items for.
483 7
     * @param string $indexingConfigurationName Name of a specific indexing configuration
484
     *
485 7
     * @throws ConnectionException
486 7
     * @throws Throwable
487
     * @throws DBALException
488
     */
489
    public function deleteItemsBySite(Site $site, string $indexingConfigurationName = '')
490
    {
491
        $indexingConfigurationNames = empty($indexingConfigurationName) ? [] : [$indexingConfigurationName];
492
        $this->deleteItems([$site], $indexingConfigurationNames);
493
    }
494
495
    /**
496
     * Removes items in the index queue filtered by the passed arguments.
497
     *
498
     * @param array $sites
499
     * @param array $indexQueueConfigurationNames
500
     * @param array $itemTypes
501
     * @param array $itemUids
502 71
     * @param array $uids
503
     *
504
     * @throws ConnectionException
505
     * @throws DBALException
506
     * @throws Throwable
507
     */
508
    public function deleteItems(
509 71
        array $sites = [],
510 71
        array $indexQueueConfigurationNames = [],
511 71
        array $itemTypes = [],
512 71
        array $itemUids = [],
513 71
        array $uids = []
514
    ): void {
515 71
        $rootPageIds = Site::getRootPageIdsFromSites($sites);
516 71
        $indexQueueConfigurationList = implode(',', $indexQueueConfigurationNames);
517 71
        $itemTypeList = implode(',', $itemTypes);
518
        $itemUids = array_map('intval', $itemUids);
519 71
        $uids = array_map('intval', $uids);
520
521 71
        $queryBuilderForDeletingItems = $this->getQueryBuilder();
522
        $queryBuilderForDeletingItems->delete($this->table);
523 71
        $queryBuilderForDeletingItems = $this->addItemWhereClauses($queryBuilderForDeletingItems, $rootPageIds, $indexQueueConfigurationList, $itemTypeList, $itemUids, $uids);
524 71
525
        $queryBuilderForDeletingProperties = $this->buildQueryForPropertyDeletion($queryBuilderForDeletingItems, $rootPageIds, $indexQueueConfigurationList, $itemTypeList, $itemUids, $uids);
526 71
527
        $queryBuilderForDeletingItems->getConnection()->beginTransaction();
528
        try {
529
            $queryBuilderForDeletingItems->execute();
530
            $queryBuilderForDeletingProperties->execute();
531
532
            $queryBuilderForDeletingItems->getConnection()->commit();
533
        } catch (Throwable $e) {
534
            $queryBuilderForDeletingItems->getConnection()->rollback();
535
            throw $e;
536
        }
537
    }
538
539
    /**
540
     * Initializes the query builder to delete items in the index queue filtered by the passed arguments.
541
     *
542
     * @param QueryBuilder $queryBuilderForDeletingItems
543
     * @param array $rootPageIds filter on a set of rootPageUids.
544 73
     * @param string $indexQueueConfigurationList
545
     * @param string $itemTypeList
546
     * @param array $itemUids filter on a set of item uids
547
     * @param array $uids filter on a set of queue item uids
548
     * @return QueryBuilder
549
     */
550
    private function addItemWhereClauses(
551
        QueryBuilder $queryBuilderForDeletingItems,
552 73
        array $rootPageIds,
553 7
        string $indexQueueConfigurationList,
554
        string $itemTypeList,
555 7
        array $itemUids,
556 7
        array $uids
557
    ): QueryBuilder {
558
        if (!empty($rootPageIds)) {
559 73
            $queryBuilderForDeletingItems->andWhere(
560 9
                /** @scrutinizer ignore-type */
561
                $queryBuilderForDeletingItems->expr()->in('root', $rootPageIds)
562 9
            );
563 9
        }
564 9
565 9
        if (!empty($indexQueueConfigurationList)) {
566 9
            $queryBuilderForDeletingItems->andWhere(
567
                /** @scrutinizer ignore-type */
568
                $queryBuilderForDeletingItems->expr()->in(
569 73
                    'indexing_configuration',
570 64
                    $queryBuilderForDeletingItems->createNamedParameter($indexQueueConfigurationList)
571
                )
572 64
            );
573 64
        }
574 64
575 64
        if (!empty($itemTypeList)) {
576 64
            $queryBuilderForDeletingItems->andWhere(
577
                /** @scrutinizer ignore-type */
578
                $queryBuilderForDeletingItems->expr()->in(
579 73
                    'item_type',
580 63
                    $queryBuilderForDeletingItems->createNamedParameter($itemTypeList)
581
                )
582 63
            );
583 63
        }
584
585
        if (!empty($itemUids)) {
586 73
            $queryBuilderForDeletingItems->andWhere(
587 1
                /** @scrutinizer ignore-type */
588
                $queryBuilderForDeletingItems->expr()->in('item_uid', $itemUids)
589 1
            );
590 1
        }
591
592
        if (!empty($uids)) {
593 73
            $queryBuilderForDeletingItems->andWhere(
594
                /** @scrutinizer ignore-type */
595
                $queryBuilderForDeletingItems->expr()->in('uid', $uids)
596
            );
597
        }
598
599
        return $queryBuilderForDeletingItems;
600
    }
601
602
    /**
603
     * Initializes a query builder to delete the indexing properties of an item by the passed conditions.
604
     *
605
     * @param QueryBuilder $queryBuilderForDeletingItems
606
     * @param array $rootPageIds
607
     * @param string $indexQueueConfigurationList
608
     * @param string $itemTypeList
609
     * @param array $itemUids
610 71
     * @param array $uids
611
     * @return QueryBuilder
612
     *
613
     * @throws DBALDriverException
614
     * @throws DBALException|\Doctrine\DBAL\DBALException
615
     */
616
    private function buildQueryForPropertyDeletion(
617
        QueryBuilder $queryBuilderForDeletingItems,
618 71
        array $rootPageIds,
619 71
        string $indexQueueConfigurationList,
620 71
        string $itemTypeList,
621 71
        array $itemUids,
622 71
        array $uids
623 71
    ): QueryBuilder {
624 71
        $queryBuilderForSelectingProperties = $queryBuilderForDeletingItems->getConnection()->createQueryBuilder();
625 71
        $queryBuilderForSelectingProperties
626 71
            ->select('items.uid')
627 71
            ->from('tx_solr_indexqueue_indexing_property', 'properties')
628 71
            ->innerJoin(
629 71
                'properties',
630 71
                $this->table,
631 71
                'items',
632 71
                (string)$queryBuilderForSelectingProperties->expr()->andX(
633 71
                    $queryBuilderForSelectingProperties->expr()->eq('items.uid', $queryBuilderForSelectingProperties->quoteIdentifier('properties.item_id')),
634 71
                    empty($rootPageIds) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.root', $rootPageIds),
635 71
                    empty($indexQueueConfigurationList) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.indexing_configuration', $queryBuilderForSelectingProperties->createNamedParameter($indexQueueConfigurationList)),
636 71
                    empty($itemTypeList) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.item_type', $queryBuilderForSelectingProperties->createNamedParameter($itemTypeList)),
637 71
                    empty($itemUids) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.item_uid', $itemUids),
638 71
                    empty($uids) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.uid', $uids)
639 71
                )
640 71
            );
641 71
        $propertyEntriesToDelete = implode(
642 71
            ',',
643 71
            array_column(
644
                $queryBuilderForSelectingProperties
645 71
                    ->execute()
646
                    ->fetchAllAssociative(),
647
                'uid'
648 71
            )
649 70
        );
650
651
        $queryBuilderForDeletingProperties = $queryBuilderForDeletingItems->getConnection()->createQueryBuilder();
652 71
653 71
        // make sure executing the property deletion query doesn't fail if there are no properties to delete
654 71
        if (empty($propertyEntriesToDelete)) {
655
            $propertyEntriesToDelete = '0';
656 71
        }
657
658
        $queryBuilderForDeletingProperties->delete('tx_solr_indexqueue_indexing_property')->where(
659
            $queryBuilderForDeletingProperties->expr()->in('item_id', $propertyEntriesToDelete)
660
        );
661
662
        return $queryBuilderForDeletingProperties;
663
    }
664 1
665
    /**
666 1
     * Removes all items from the Index Queue.
667
     *
668
     * @return int The number of affected rows. For a truncate this is unreliable as there is no meaningful information.
669
     */
670
    public function deleteAllItems(): int
671
    {
672
        return $this->getQueryBuilder()->getConnection()->truncate($this->table);
673
    }
674
675
    /**
676
     * Gets a single Index Queue item by its uid.
677
     *
678 36
     * @param int $uid Index Queue item uid
679
     * @return Item|null The request Index Queue item or NULL if no item with $itemId was found
680 36
     *
681 36
     * @throws DBALDriverException
682 36
     * @throws DBALException|\Doctrine\DBAL\DBALException
683 36
     */
684 36
    public function findItemByUid(int $uid): ?Item
685 36
    {
686 36
        $queryBuilder = $this->getQueryBuilder();
687
        $indexQueueItemRecord = $queryBuilder
688 36
            ->select('*')
689 7
            ->from($this->table)
690
            ->where(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('uid', $uid))
691
            ->execute()
692 29
            ->fetchAssociative();
693
694
        if (!isset($indexQueueItemRecord['uid'])) {
695
            return null;
696
        }
697
698
        return GeneralUtility::makeInstance(Item::class, /** @scrutinizer ignore-type */ $indexQueueItemRecord);
699
    }
700
701
    /**
702
     * Gets Index Queue items by type and uid.
703
     *
704
     * @param string $itemType item type, usually  the table name
705
     * @param int $itemUid item uid
706
     * @return Item[] An array of items matching $itemType and $itemUid
707 53
     *
708
     * @throws ConnectionException
709 53
     * @throws DBALDriverException
710 53
     * @throws Throwable
711
     * @throws DBALException
712 53
     */
713 53
    public function findItemsByItemTypeAndItemUid(string $itemType, int $itemUid): array
714 53
    {
715 53
        $queryBuilder = $this->getQueryBuilder();
716
        $compositeExpression = $queryBuilder->expr()->andX(
717
            /** @scrutinizer ignore-type */
718
            $queryBuilder->expr()->eq('item_type', $queryBuilder->getConnection()->quote($itemType, PDO::PARAM_STR)),
719
            $queryBuilder->expr()->eq('item_uid', $itemUid)
720
        );
721
        return $this->getItemsByCompositeExpression($compositeExpression, $queryBuilder);
722
    }
723
724
    /**
725
     * Returns a collection of items by CompositeExpression.
726
     *
727
     * @param CompositeExpression|null $expression Optional expression to filter records.
728
     * @param QueryBuilder|null $queryBuilder QueryBuilder to use
729
     * @return array
730 53
     *
731
     * @throws ConnectionException
732
     * @throws DBALDriverException
733
     * @throws Throwable
734 53
     * @throws DBALException
735
     */
736
    protected function getItemsByCompositeExpression(
737
        CompositeExpression $expression = null,
738 53
        QueryBuilder $queryBuilder = null
739 53
    ): array {
740 53
        if (!$queryBuilder instanceof QueryBuilder) {
741
            $queryBuilder = $this->getQueryBuilder();
742
        }
743 53
744 53
        $queryBuilder->select('*')->from($this->table);
745 53
        if (isset($expression)) {
746 53
            $queryBuilder->where($expression);
747
        }
748
749
        $indexQueueItemRecords = $queryBuilder
750
            ->execute()
751
            ->fetchAllAssociative();
752
        return $this->getIndexQueueItemObjectsFromRecords($indexQueueItemRecords);
753
    }
754
755
    /**
756
     * Returns all items in the queue.
757
     *
758
     * @return Item[] all Items from Queue without restrictions
759 5
     *
760
     * @throws ConnectionException
761 5
     * @throws DBALDriverException
762 5
     * @throws Throwable
763 5
     * @throws DBALException
764 5
     */
765 5
    public function findAll(): array
766 5
    {
767 5
        $queryBuilder = $this->getQueryBuilder();
768
        $allRecords = $queryBuilder
769
            ->select('*')
770
            ->from($this->table)
771
            ->execute()
772
            ->fetchAllAssociative();
773
        return $this->getIndexQueueItemObjectsFromRecords($allRecords);
774
    }
775
776
    /**
777
     * Gets $limit number of items to index for a particular $site.
778
     *
779
     * @param Site $site TYPO3 site
780
     * @param int $limit Number of items to get from the queue
781
     * @return Item[] Items to index to the given solr server
782 3
     *
783
     * @throws ConnectionException
784 3
     * @throws DBALDriverException
785
     * @throws Throwable
786 3
     * @throws DBALException
787 3
     */
788 3
    public function findItemsToIndex(Site $site, int $limit = 50): array
789 3
    {
790
        $queryBuilder = $this->getQueryBuilder();
791 3
        // determine which items to index with this run
792
        $indexQueueItemRecords = $queryBuilder
793 3
            ->select('*')
794
            ->from($this->table)
795 3
            ->andWhere(
796
                /** @scrutinizer ignore-type */
797 3
                $queryBuilder->expr()->eq('root', $site->getRootPageId()),
798 3
                /** @scrutinizer ignore-type */
799 3
                $queryBuilder->expr()->gt('changed', 'indexed'),
800 3
                /** @scrutinizer ignore-type */
801 3
                $queryBuilder->expr()->lte('changed', time()),
802 3
                /** @scrutinizer ignore-type */
803 3
                $queryBuilder->expr()->eq('errors', $queryBuilder->createNamedParameter(''))
804 3
            )
805
            ->orderBy('indexing_priority', 'DESC')
806 3
            ->addOrderBy('changed', 'DESC')
807
            ->addOrderBy('uid', 'DESC')
808
            ->setMaxResults($limit)
809
            ->execute()
810
            ->fetchAllAssociative();
811
812
        return $this->getIndexQueueItemObjectsFromRecords($indexQueueItemRecords);
813
    }
814
815
    /**
816
     * Retrieves the count of items that match certain filters. Each filter is passed as parts of the where claus combined with AND.
817
     *
818
     * @param array $sites
819
     * @param array $indexQueueConfigurationNames
820
     * @param array $itemTypes
821
     * @param array $itemUids
822
     * @param array $uids
823
     * @param int $start
824
     * @param int $limit
825
     * @return array
826 1
     *
827
     * @throws ConnectionException
828
     * @throws DBALDriverException
829
     * @throws Throwable
830
     * @throws DBALException
831
     */
832
    public function findItems(
833
        array $sites = [],
834
        array $indexQueueConfigurationNames = [],
835 1
        array $itemTypes = [],
836 1
        array $itemUids = [],
837 1
        array $uids = [],
838 1
        int $start = 0,
839 1
        int $limit = 50
840 1
    ): array {
841 1
        $rootPageIds = Site::getRootPageIdsFromSites($sites);
842 1
        $indexQueueConfigurationList = implode(',', $indexQueueConfigurationNames);
843 1
        $itemTypeList = implode(',', $itemTypes);
844 1
        $itemUids = array_map('intval', $itemUids);
845 1
        $uids = array_map('intval', $uids);
846 1
        $itemQueryBuilder = $this->getQueryBuilder()->select('*')->from($this->table);
847
        $itemQueryBuilder = $this->addItemWhereClauses($itemQueryBuilder, $rootPageIds, $indexQueueConfigurationList, $itemTypeList, $itemUids, $uids);
848
        $itemRecords = $itemQueryBuilder->setFirstResult($start)
849
            ->setMaxResults($limit)
850
            ->execute()
851
            ->fetchAllAssociative();
852
        return $this->getIndexQueueItemObjectsFromRecords($itemRecords);
853
    }
854
855
    /**
856
     * Creates an array of ApacheSolrForTypo3\Solr\IndexQueue\Item objects from an array of
857
     * index queue records.
858
     *
859
     * @param array $indexQueueItemRecords Array of plain index queue records
860
     * @return array Array of ApacheSolrForTypo3\Solr\IndexQueue\Item objects
861 56
     *
862
     * @throws ConnectionException
863 56
     * @throws DBALDriverException
864 56
     * @throws Throwable
865
     * @throws DBALException
866
     */
867
    protected function getIndexQueueItemObjectsFromRecords(array $indexQueueItemRecords): array
868
    {
869
        $tableRecords = $this->getAllQueueItemRecordsByUidsGroupedByTable($indexQueueItemRecords);
870
        return $this->getQueueItemObjectsByRecords($indexQueueItemRecords, $tableRecords);
871
    }
872
873
    /**
874
     * Returns the records for suitable item type.
875
     *
876 56
     * @param array $indexQueueItemRecords
877
     * @return array
878 56
     *
879 56
     * @throws DBALDriverException
880
     * @throws DBALException|\Doctrine\DBAL\DBALException
881 56
     */
882 55
    protected function getAllQueueItemRecordsByUidsGroupedByTable(array $indexQueueItemRecords): array
883
    {
884
        $tableUids = [];
885
        $tableRecords = [];
886 56
        // grouping records by table
887 55
        foreach ($indexQueueItemRecords as $indexQueueItemRecord) {
888
            $tableUids[$indexQueueItemRecord['item_type']][] = $indexQueueItemRecord['item_uid'];
889 55
        }
890 55
891 55
        // fetching records by table, saves us a lot of single queries
892 55
        foreach ($tableUids as $table => $uids) {
893 55
            $uidList = implode(',', $uids);
894 55
895 55
            $queryBuilderForRecordTable = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
896 55
            $queryBuilderForRecordTable->getRestrictions()->removeAll();
897 55
            $resultsFromRecordTable = $queryBuilderForRecordTable
898 52
                ->select('*')
899
                ->from($table)
900
                ->where(/** @scrutinizer ignore-type */ $queryBuilderForRecordTable->expr()->in('uid', $uidList))
901 55
                ->execute();
902 55
            $records = [];
903
            while ($record = $resultsFromRecordTable->fetchAssociative()) {
904
                $records[$record['uid']] = $record;
905 56
            }
906
907
            $tableRecords[$table] = $records;
908
            $this->hookPostProcessFetchRecordsForIndexQueueItem($table, $uids, $tableRecords);
909
        }
910
911
        return $tableRecords;
912
    }
913
914
    /**
915 55
     * Calls defined in postProcessFetchRecordsForIndexQueueItem hook method.
916
     *
917 55
     * @param string $table
918 55
     * @param array $uids
919
     * @param array $tableRecords
920
     */
921
    protected function hookPostProcessFetchRecordsForIndexQueueItem(string $table, array $uids, array &$tableRecords)
922
    {
923
        if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessFetchRecordsForIndexQueueItem'] ?? null)) {
924
            return;
925
        }
926
        $params = ['table' => $table, 'uids' => $uids, 'tableRecords' => &$tableRecords];
927
        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessFetchRecordsForIndexQueueItem'] as $reference) {
928
            GeneralUtility::callUserFunction($reference, $params, $this);
929
        }
930
    }
931
932
    /**
933
     * Instantiates a list of Item objects from database records.
934
     *
935
     * @param array $indexQueueItemRecords records from database
936
     * @param array $tableRecords
937 56
     * @return array
938
     *
939 56
     * @throws ConnectionException
940 56
     * @throws Throwable
941 55
     * @throws DBALException
942 52
     */
943 52
    protected function getQueueItemObjectsByRecords(array $indexQueueItemRecords, array $tableRecords): array
944
    {
945 52
        $indexQueueItems = [];
946
        foreach ($indexQueueItemRecords as $indexQueueItemRecord) {
947 52
            if (isset($tableRecords[$indexQueueItemRecord['item_type']][$indexQueueItemRecord['item_uid']])) {
948 52
                $indexQueueItems[] = GeneralUtility::makeInstance(
949
                    Item::class,
950 3
                    /** @scrutinizer ignore-type */
951 3
                    $indexQueueItemRecord,
952 3
                    /** @scrutinizer ignore-type */
953 3
                    $tableRecords[$indexQueueItemRecord['item_type']][$indexQueueItemRecord['item_uid']]
954 3
                );
955 3
            } else {
956 3
                $this->logger->log(
957 3
                    SolrLogManager::ERROR,
958 3
                    'Record missing for Index Queue item. Item removed.',
959 3
                    [
960 3
                        $indexQueueItemRecord,
961
                    ]
962
                );
963
                $this->deleteItem(
964 56
                    $indexQueueItemRecord['item_type'],
965
                    $indexQueueItemRecord['item_uid']
966
                );
967
            }
968
        }
969
970
        return $indexQueueItems;
971
    }
972
973
    /**
974
     * Marks an item as failed and causes the indexer to skip the item in the
975
     * next run.
976
     *
977 6
     * @param int|Item $item Either the item's Index Queue uid or the complete item
978
     * @param string $errorMessage Error message
979 6
     * @return int affected rows
980 6
     *
981
     * @throws DBALException|\Doctrine\DBAL\DBALException
982 6
     */
983 6
    public function markItemAsFailed($item, string $errorMessage = ''): int
984 6
    {
985 6
        $itemUid = ($item instanceof Item) ? $item->getIndexQueueUid() : (int)$item;
986 6
        $errorMessage = empty($errorMessage) ? '1' : $errorMessage;
987 6
988
        $queryBuilder = $this->getQueryBuilder();
989
        return (int)$queryBuilder
990
            ->update($this->table)
991
            ->set('errors', $errorMessage)
992
            ->where($queryBuilder->expr()->eq('uid', $itemUid))
993
            ->execute();
994
    }
995
996
    /**
997
     * Sets the timestamp of when an item last has been indexed.
998 2
     *
999
     * @param Item $item
1000 2
     * @return int affected rows
1001 2
     *
1002 2
     * @throws DBALException|\Doctrine\DBAL\DBALException
1003 2
     */
1004 2
    public function updateIndexTimeByItem(Item $item): int
1005 2
    {
1006
        $queryBuilder = $this->getQueryBuilder();
1007
        return (int)$queryBuilder
1008
            ->update($this->table)
1009
            ->set('indexed', time())
1010
            ->where($queryBuilder->expr()->eq('uid', $item->getIndexQueueUid()))
1011
            ->execute();
1012
    }
1013
1014
    /**
1015
     * Sets the change timestamp of an item.
1016
     *
1017
     * @param Item $item
1018
     * @param int $changedTime
1019
     * @return int affected rows
1020
     *
1021
     * @throws DBALException|\Doctrine\DBAL\DBALException
1022
     */
1023
    public function updateChangedTimeByItem(Item $item, int $changedTime = 0): int
1024
    {
1025
        $queryBuilder = $this->getQueryBuilder();
1026
        return (int)$queryBuilder
1027
            ->update($this->table)
1028
            ->set('changed', $changedTime)
1029
            ->where($queryBuilder->expr()->eq('uid', $item->getIndexQueueUid()))
1030
            ->execute();
1031
    }
1032
1033
    /**
1034
     * Initializes Queue by given sql
1035
     *
1036
     * Note: Do not use platform specific functions!
1037
     *
1038 14
     * @param string $sqlStatement Native SQL statement
1039
     * @return int The number of affected rows.
1040 14
     *
1041 14
     * @throws DBALException
1042 14
     * @internal
1043
     */
1044
    public function initializeByNativeSQLStatement(string $sqlStatement): int
1045
    {
1046
        return $this->getQueryBuilder()
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getQueryBu...tatement($sqlStatement) could return the type string which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
1047
            ->getConnection()
1048
            ->executeStatement($sqlStatement);
1049
    }
1050
1051
    /**
1052
     * Retrieves an array of pageIds from mountPoints that already have a queue entry.
1053
     *
1054 8
     * @param string $identifier identifier of the mount point
1055
     * @return array pageIds from mountPoints that already have a queue entry
1056 8
     *
1057 8
     * @throws DBALDriverException
1058 8
     * @throws DBALException|\Doctrine\DBAL\DBALException
1059 8
     */
1060 8
    public function findPageIdsOfExistingMountPagesByMountIdentifier(string $identifier): array
1061 8
    {
1062 8
        $queryBuilder = $this->getQueryBuilder();
1063 8
        $resultSet = $queryBuilder
1064 8
            ->select('item_uid')
1065 8
            ->add('select', $queryBuilder->expr()->count('*', 'queueItemCount'), true)
1066 8
            ->from($this->table)
1067
            ->where(
1068 8
                $queryBuilder->expr()->eq('item_type', $queryBuilder->createNamedParameter('pages')),
1069 8
                $queryBuilder->expr()->eq('pages_mountidentifier', $queryBuilder->createNamedParameter($identifier))
1070
            )
1071
            ->groupBy('item_uid')
1072
            ->execute();
1073
1074
        $mountedPagesIdsWithQueueItems = [];
1075 8
        while ($record = $resultSet->fetchAssociative()) {
1076
            if ($record['queueItemCount'] > 0) {
1077
                $mountedPagesIdsWithQueueItems[] = $record['item_uid'];
1078
            }
1079
        }
1080
1081
        return $mountedPagesIdsWithQueueItems;
1082
    }
1083
1084
    /**
1085
     * Retrieves an array of items for mount destinations matched by root page ID, Mount Identifier and a list of mounted page IDs.
1086
     *
1087
     * @param int $rootPid
1088
     * @param string $identifier identifier of the mount point
1089 8
     * @param array $mountedPids An array of mounted page IDs
1090
     * @return array
1091
     *
1092
     * @throws DBALDriverException
1093
     * @throws DBALException|\Doctrine\DBAL\DBALException
1094 8
     */
1095 8
    public function findAllIndexQueueItemsByRootPidAndMountIdentifierAndMountedPids(
1096 8
        int $rootPid,
1097 8
        string $identifier,
1098 8
        array $mountedPids
1099 8
    ): array {
1100 8
        $queryBuilder = $this->getQueryBuilder();
1101 8
        return $queryBuilder
1102 8
            ->select('*')
1103 8
            ->from($this->table)
1104 8
            ->where(
1105 8
                $queryBuilder->expr()->eq('root', $queryBuilder->createNamedParameter($rootPid, PDO::PARAM_INT)),
1106 8
                $queryBuilder->expr()->eq('item_type', $queryBuilder->createNamedParameter('pages')),
1107
                $queryBuilder->expr()->in('item_uid', $mountedPids),
1108
                $queryBuilder->expr()->eq('has_indexing_properties', $queryBuilder->createNamedParameter(1, PDO::PARAM_INT)),
1109
                $queryBuilder->expr()->eq('pages_mountidentifier', $queryBuilder->createNamedParameter($identifier))
1110
            )
1111
            ->execute()
1112
            ->fetchAllAssociative();
1113
    }
1114
1115
    /**
1116
     * Updates has_indexing_properties field for given Item
1117
     *
1118 10
     * @param int $itemUid
1119
     * @param bool $hasIndexingPropertiesFlag
1120 10
     * @return int number of affected rows, 1 on success
1121 10
     *
1122 10
     * @throws DBALException|\Doctrine\DBAL\DBALException
1123 10
     */
1124
    public function updateHasIndexingPropertiesFlagByItemUid(int $itemUid, bool $hasIndexingPropertiesFlag): int
1125 10
    {
1126 10
        $queryBuilder = $this->getQueryBuilder();
1127 10
        return (int)$queryBuilder
1128 10
            ->update($this->table)
1129 10
            ->where(
1130 10
                /** @scrutinizer ignore-type */
1131 10
                $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($itemUid, PDO::PARAM_INT))
1132
            )
1133
            ->set(
1134
                'has_indexing_properties',
1135
                $queryBuilder->createNamedParameter($hasIndexingPropertiesFlag, PDO::PARAM_INT),
1136
                false
1137
            )->execute();
1138
    }
1139
}
1140