Passed
Push — task/2976_TYPO3.11_compatibili... ( fdb8e9...6dca74 )
by Rafael
23:01
created

getItemsByCompositeExpression()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3.009

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 17
ccs 9
cts 10
cp 0.9
rs 9.9666
cc 3
nc 4
nop 2
crap 3.009
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ApacheSolrForTypo3\Solr\Domain\Index\Queue;
6
7
/*
8
 * This file is part of the TYPO3 CMS project.
9
 *
10
 * It is free software; you can redistribute it and/or modify it under
11
 * the terms of the GNU General Public License, either version 2
12
 * of the License, or any later version.
13
 *
14
 * For the full copyright and license information, please read the
15
 * LICENSE.txt file that was distributed with this source code.
16
 *
17
 * The TYPO3 project - inspiring people to share!
18
 */
19
20
use ApacheSolrForTypo3\Solr\IndexQueue\Item;
21
use ApacheSolrForTypo3\Solr\Domain\Site\Site;
22
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
23
use ApacheSolrForTypo3\Solr\System\Records\AbstractRepository;
24
use Doctrine\DBAL\ConnectionException;
25
use Doctrine\DBAL\Exception as DBALException;
26
use Doctrine\DBAL\Driver\Exception as DBALDriverException;
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
 */
39
class QueueItemRepository extends AbstractRepository
40
{
41
    /**
42
     * @var string
43
     */
44
    protected $table = 'tx_solr_indexqueue_item';
45
46
    /**
47
     * @var SolrLogManager
48
     */
49
    protected $logger;
50
51
    /**
52
     * QueueItemRepository constructor.
53
     *
54
     * @param SolrLogManager|null $logManager
55
     */
56 135
    public function __construct(SolrLogManager $logManager = null)
57
    {
58 135
        $this->logger = $logManager ?? GeneralUtility::makeInstance(
59 135
            SolrLogManager::class,
60
            /** @scrutinizer ignore-type */
61
            __CLASS__
62 135
        );
63 135
    }
64
65
    /**
66
     * Fetches the last indexed row
67
     *
68
     * @param int $rootPageId The root page uid for which to get the last indexed row
69
     * @return array
70
     *
71
     * @throws DBALDriverException
72
     *
73
     * @throws \Doctrine\DBAL\DBALException
74
     */
75 5
    public function findLastIndexedRow(int $rootPageId): array
76
    {
77 5
        $queryBuilder = $this->getQueryBuilder();
78
        return $queryBuilder
79 5
            ->select('uid', 'indexed')
80 5
            ->from($this->table)
81 5
            ->where(
82
                /** @scrutinizer ignore-type */
83 5
                $queryBuilder->expr()->eq('root', $rootPageId)
84
            )
85 5
            ->andWhere(
86
                /** @scrutinizer ignore-type */
87 5
                $queryBuilder->expr()->neq('indexed', 0)
88
            )
89 5
            ->orderBy('indexed', 'DESC')
90 5
            ->setMaxResults(1)
91 5
            ->execute()
92 5
            ->fetchAllAssociative();
93
    }
94
95
    /**
96
     * Finds indexing errors for the current site
97
     *
98
     * @param Site $site
99
     * @return array Error items for the current site's Index Queue
100
     *
101
     * @throws DBALDriverException
102
     * @throws \Doctrine\DBAL\DBALException
103
     */
104 3
    public function findErrorsBySite(Site $site): array
105
    {
106 3
        $queryBuilder = $this->getQueryBuilder();
107
        return $queryBuilder
108 3
            ->select('uid', 'item_type', 'item_uid', 'errors')
109 3
            ->from($this->table)
110 3
            ->andWhere(
111
                /** @scrutinizer ignore-type */
112 3
                $queryBuilder->expr()->notLike('errors', $queryBuilder->createNamedParameter('')),
113 3
                $queryBuilder->expr()->eq('root', $site->getRootPageId())
0 ignored issues
show
Bug introduced by
$queryBuilder->expr()->e...$site->getRootPageId()) of type string is incompatible with the type Doctrine\DBAL\Query\Expr...n|array<integer,string> expected by parameter $where of TYPO3\CMS\Core\Database\...ueryBuilder::andWhere(). ( Ignorable by Annotation )

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

113
                /** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('root', $site->getRootPageId())
Loading history...
114
            )
115 3
            ->execute()
116 3
            ->fetchAllAssociative();
117
    }
118
119
    /**
120
     * Resets all the errors for all index queue items.
121
     *
122
     * @return int affected rows
123
     *
124
     * @throws \Doctrine\DBAL\DBALException
125
     */
126 1
    public function flushAllErrors(): int
127
    {
128 1
        $queryBuilder = $this->getQueryBuilder();
129 1
        return (int)$this->getPreparedFlushErrorQuery($queryBuilder)
130 1
            ->execute();
131
    }
132
133
    /**
134
     * Flushes the errors for a single site.
135
     *
136
     * @param Site $site
137
     * @return int
138
     *
139
     * @throws \Doctrine\DBAL\DBALException
140
     */
141 1
    public function flushErrorsBySite(Site $site): int
142
    {
143 1
        $queryBuilder = $this->getQueryBuilder();
144 1
        return (int)$this->getPreparedFlushErrorQuery($queryBuilder)
145 1
            ->andWhere(
146
                /** @scrutinizer ignore-type */
147 1
                $queryBuilder->expr()->eq('root', $site->getRootPageId())
148
            )
149 1
            ->execute();
150
    }
151
152
    /**
153
     * Flushes the error for a single item.
154
     *
155
     * @param Item $item
156
     * @return int affected rows
157
     *
158
     * @throws \Doctrine\DBAL\DBALException
159
     */
160 2
    public function flushErrorByItem(Item $item): int
161
    {
162 2
        $queryBuilder = $this->getQueryBuilder();
163 2
        return (int)$this->getPreparedFlushErrorQuery($queryBuilder)
164 2
            ->andWhere(
165
                /** @scrutinizer ignore-type */
166 2
                $queryBuilder->expr()->eq('uid', $item->getIndexQueueUid())
167
            )
168 2
            ->execute();
169
    }
170
171
    /**
172
     * Initializes the QueryBuilder with a query the resets the error field for items that have an error.
173
     *
174
     * @param QueryBuilder $queryBuilder
175
     * @return QueryBuilder
176
     */
177 4
    private function getPreparedFlushErrorQuery(QueryBuilder $queryBuilder): QueryBuilder
178
    {
179
        return $queryBuilder
180 4
            ->update($this->table)
181 4
            ->set('errors', '')
182 4
            ->where(
183
                /** @scrutinizer ignore-type */
184 4
                $queryBuilder->expr()->notLike('errors', $queryBuilder->createNamedParameter(''))
185
            );
186
    }
187
188
    /**
189
     * Updates an existing queue entry by $itemType $itemUid and $rootPageId.
190
     *
191
     * @param string $itemType The item's type, usually a table name.
192
     * @param int $itemUid The item's uid, usually an integer uid, could be a
193
     *      different value for non-database-record types.
194
     * @param int $rootPageId The uid of the rootPage
195
     * @param int $changedTime The forced change time that should be used for updating
196
     * @param string $indexingConfiguration The name of the related indexConfiguration
197
     * @return int affected rows
198
     *
199
     * @throws \Doctrine\DBAL\DBALException
200
     */
201 13
    public function updateExistingItemByItemTypeAndItemUidAndRootPageId(
202
        string $itemType,
203
        int $itemUid,
204
        int $rootPageId,
205
        int $changedTime,
206
        string $indexingConfiguration = ''
207
    ): int {
208 13
        $queryBuilder = $this->getQueryBuilder();
209
        $queryBuilder
210 13
            ->update($this->table)
211 13
            ->set('changed', $changedTime)
212 13
            ->andWhere(
213
                /** @scrutinizer ignore-type */
214 13
                $queryBuilder->expr()->eq('item_type', $queryBuilder->createNamedParameter($itemType)),
215
                /** @scrutinizer ignore-type */
216 13
                $queryBuilder->expr()->eq('item_uid', $itemUid),
217
                /** @scrutinizer ignore-type */
218 13
                $queryBuilder->expr()->eq('root', $rootPageId)
219
            );
220
221 13
        if (!empty($indexingConfiguration)) {
222 13
            $queryBuilder->set('indexing_configuration', $indexingConfiguration);
223
        }
224
225 13
        return (int)$queryBuilder->execute();
226
    }
227
228
    /**
229
     * Adds an item to the index queue.
230
     *
231
     * Not meant for public use.
232
     *
233
     * @param string $itemType The item's type, usually a table name.
234
     * @param int $itemUid The item's uid, usually an integer uid, could be a different value for non-database-record types.
235
     * @param int $rootPageId
236
     * @param int $changedTime
237
     * @param string $indexingConfiguration The item's indexing configuration to use. Optional, overwrites existing / determined configuration.
238
     * @return int the number of inserted rows, which is typically 1
239
     *
240
     * @throws \Doctrine\DBAL\DBALException
241
     */
242 56
    public function add(
243
        string $itemType,
244
        int $itemUid,
245
        int $rootPageId,
246
        int $changedTime,
247
        string $indexingConfiguration
248
    ): int {
249 56
        $queryBuilder = $this->getQueryBuilder();
250
        return (int)$queryBuilder
251 56
            ->insert($this->table)
252 56
            ->values([
253 56
                'root' => $rootPageId,
254 56
                'item_type' => $itemType,
255 56
                'item_uid' => $itemUid,
256 56
                'changed' => $changedTime,
257 56
                'errors' => '',
258 56
                'indexing_configuration' => $indexingConfiguration
259
            ])
260 56
            ->execute();
261
    }
262
263
    /**
264
     * Retrieves the count of items that match certain filters. Each filter is passed as parts of the where claus combined with AND.
265
     *
266
     * @param array $sites
267
     * @param array $indexQueueConfigurationNames
268
     * @param array $itemTypes
269
     * @param array $itemUids
270
     * @param array $uids
271
     * @return int
272
     *
273
     * @throws DBALDriverException
274
     * @throws \Doctrine\DBAL\DBALException
275
     */
276 1
    public function countItems(
277
        array $sites = [],
278
        array $indexQueueConfigurationNames = [],
279
        array $itemTypes = [],
280
        array $itemUids = [],
281
        array $uids = []
282
    ): int {
283 1
        $rootPageIds = Site::getRootPageIdsFromSites($sites);
284 1
        $indexQueueConfigurationList = implode(',', $indexQueueConfigurationNames);
285 1
        $itemTypeList = implode(',', $itemTypes);
286 1
        $itemUids = array_map('intval', $itemUids);
287 1
        $uids = array_map('intval', $uids);
288
289 1
        $queryBuilderForCountingItems = $this->getQueryBuilder();
290 1
        $queryBuilderForCountingItems->count('uid')->from($this->table);
291 1
        $queryBuilderForCountingItems = $this->addItemWhereClauses(
292 1
            $queryBuilderForCountingItems,
293
            $rootPageIds,
294
            $indexQueueConfigurationList,
295
            $itemTypeList,
296
            $itemUids,
297
            $uids
298
        );
299
300
        return (int)$queryBuilderForCountingItems
301 1
            ->execute()
302 1
            ->fetchOne();
303
    }
304
305
    /**
306
     * Gets the most recent changed time of a page's content elements
307
     *
308
     * @param int $pageUid
309
     * @return int|null Timestamp of the most recent content element change or null if nothing is found.
310
     *
311
     * @throws DBALDriverException
312
     * @throws \Doctrine\DBAL\DBALException
313
     */
314 38
    public function getPageItemChangedTimeByPageUid(int $pageUid): ?int
315
    {
316 38
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
317 38
            ->getQueryBuilderForTable('tt_content');
318 38
        $queryBuilder->getRestrictions()->removeAll();
319 38
        $pageContentLastChangedTime = $queryBuilder
320 38
            ->add('select', $queryBuilder->expr()->max('tstamp', 'changed_time'))
321 38
            ->from('tt_content')
322 38
            ->where(
323
                /** @scrutinizer ignore-type */
324 38
                $queryBuilder->expr()->eq('pid', $pageUid)
325
            )
326 38
            ->execute()
327 38
            ->fetchAssociative();
328
329 38
        return $pageContentLastChangedTime['changed_time'];
330
    }
331
332
    /**
333
     * Gets the most recent changed time for an item taking into account
334
     * localized records.
335
     *
336
     * @param string $itemType The item's type, usually a table name.
337
     * @param int $itemUid The item's uid
338
     * @return int Timestamp of the most recent content element change
339
     *
340
     * @throws DBALDriverException
341
     * @throws \Doctrine\DBAL\DBALException
342
     */
343 61
    public function getLocalizableItemChangedTime(string $itemType, int $itemUid): int
344
    {
345 61
        $localizedChangedTime = 0;
346
347 61
        if (isset($GLOBALS['TCA'][$itemType]['ctrl']['transOrigPointerField'])) {
348
            // table is localizable
349 61
            $translationOriginalPointerField = $GLOBALS['TCA'][$itemType]['ctrl']['transOrigPointerField'];
350 61
            $timeStampField = $GLOBALS['TCA'][$itemType]['ctrl']['tstamp'];
351
352 61
            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($itemType);
353 61
            $queryBuilder->getRestrictions()->removeAll();
354 61
            $localizedChangedTime = $queryBuilder
355 61
                ->add('select', $queryBuilder->expr()->max($timeStampField, 'changed_time'))
356 61
                ->from($itemType)
357 61
                ->orWhere(
358
                    /** @scrutinizer ignore-type */
359 61
                    $queryBuilder->expr()->eq('uid', $itemUid),
360 61
                    $queryBuilder->expr()->eq($translationOriginalPointerField, $itemUid)
361
                )
362 61
                ->execute()
363 61
                ->fetchOne();
364
        }
365 61
        return (int)$localizedChangedTime;
366
    }
367
368
    /**
369
     * Returns prepared QueryBuilder for contains* methods in this repository
370
     *
371
     * @param string $itemType
372
     * @param int $itemUid
373
     * @return QueryBuilder
374
     */
375 67
    protected function getQueryBuilderForContainsMethods(string $itemType, int $itemUid): QueryBuilder
376
    {
377 67
        $queryBuilder = $this->getQueryBuilder();
378 67
        return $queryBuilder->count('uid')->from($this->table)
379 67
            ->andWhere(
380
                /** @scrutinizer ignore-type */
381 67
                $queryBuilder->expr()->eq('item_type', $queryBuilder->createNamedParameter($itemType)),
382
                /** @scrutinizer ignore-type */
383 67
                $queryBuilder->expr()->eq('item_uid', $itemUid)
384
            );
385
    }
386
387
    /**
388
     * Checks whether the Index Queue contains a specific item.
389
     *
390
     * @param string $itemType The item's type, usually a table name.
391
     * @param int $itemUid The item's uid
392
     * @return bool TRUE if the item is found in the queue, FALSE otherwise
393
     *
394
     * @throws \Doctrine\DBAL\DBALException
395
     * @throws DBALDriverException
396
     */
397 8
    public function containsItem(string $itemType, int $itemUid): bool
398
    {
399 8
        return (bool)$this->getQueryBuilderForContainsMethods($itemType, $itemUid)
400 8
            ->execute()
401 8
            ->fetchOne();
402
    }
403
404
    /**
405
     * Checks whether the Index Queue contains a specific item.
406
     *
407
     * @param string $itemType The item's type, usually a table name.
408
     * @param int $itemUid The item's uid
409
     * @param integer $rootPageId
410
     * @return bool TRUE if the item is found in the queue, FALSE otherwise
411
     *
412
     * @throws \Doctrine\DBAL\DBALException
413
     * @throws DBALDriverException
414
     */
415 61
    public function containsItemWithRootPageId(string $itemType, int $itemUid, int $rootPageId): bool
416
    {
417 61
        $queryBuilder = $this->getQueryBuilderForContainsMethods($itemType, $itemUid);
418
        return (bool)$queryBuilder
419 61
            ->andWhere(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('root', $rootPageId))
420 61
            ->execute()
421 61
            ->fetchOne();
422
    }
423
424
    /**
425
     * Checks whether the Index Queue contains a specific item that has been
426
     * marked as indexed.
427
     *
428
     * @param string $itemType The item's type, usually a table name.
429
     * @param int $itemUid The item's uid
430
     * @return bool TRUE if the item is found in the queue and marked as indexed, FALSE otherwise
431
     *
432
     * @throws \Doctrine\DBAL\DBALException
433
     * @throws DBALDriverException
434
     */
435 2
    public function containsIndexedItem(string $itemType, int $itemUid): bool
436
    {
437 2
        $queryBuilder = $this->getQueryBuilderForContainsMethods($itemType, $itemUid);
438
        return (bool)$queryBuilder
439 2
            ->andWhere(/** @scrutinizer ignore-type */ $queryBuilder->expr()->gt('indexed', 0))
440 2
            ->execute()
441 2
            ->fetchOne();
442
    }
443
444
    /**
445
     * Removes an item from the Index Queue.
446
     *
447
     * @param string $itemType The type of the item to remove, usually a table name.
448
     * @param int|null $itemUid The uid of the item to remove
449
     *
450
     * @throws ConnectionException
451
     * @throws Throwable
452
     * @throws \Doctrine\DBAL\DBALException
453
     */
454 37
    public function deleteItem(string $itemType, int $itemUid = null)
455
    {
456 37
        $itemUids = empty($itemUid) ? [] : [$itemUid];
457 37
        $this->deleteItems([], [], [$itemType], $itemUids);
458 37
    }
459
460
    /**
461
     * Removes all items of a certain type from the Index Queue.
462
     *
463
     * @param string $itemType The type of items to remove, usually a table name.
464
     *
465
     * @throws ConnectionException
466
     * @throws Throwable
467
     * @throws \Doctrine\DBAL\DBALException
468
     */
469 1
    public function deleteItemsByType(string $itemType)
470
    {
471 1
        $this->deleteItem($itemType);
472 1
    }
473
474
    /**
475
     * Removes all items of a certain site from the Index Queue. Accepts an
476
     * optional parameter to limit the deleted items by indexing configuration.
477
     *
478
     * @param Site $site The site to remove items for.
479
     * @param string $indexingConfigurationName Name of a specific indexing configuration
480
     *
481
     * @throws ConnectionException
482
     * @throws Throwable
483
     * @throws \Doctrine\DBAL\DBALException
484
     */
485 7
    public function deleteItemsBySite(Site $site, string $indexingConfigurationName = '')
486
    {
487 7
        $indexingConfigurationNames = empty($indexingConfigurationName) ? [] : [$indexingConfigurationName];
488 7
        $this->deleteItems([$site], $indexingConfigurationNames);
489 7
    }
490
491
    /**
492
     * Removes items in the index queue filtered by the passed arguments.
493
     *
494
     * @param array $sites
495
     * @param array $indexQueueConfigurationNames
496
     * @param array $itemTypes
497
     * @param array $itemUids
498
     * @param array $uids
499
     *
500
     * @throws ConnectionException
501
     * @throws \Doctrine\DBAL\DBALException
502
     * @throws Throwable
503
     */
504 44
    public function deleteItems(
505
        array $sites = [],
506
        array $indexQueueConfigurationNames = [],
507
        array $itemTypes = [],
508
        array $itemUids = [],
509
        array $uids = []
510
    ): void {
511 44
        $rootPageIds = Site::getRootPageIdsFromSites($sites);
512 44
        $indexQueueConfigurationList = implode(",", $indexQueueConfigurationNames);
513 44
        $itemTypeList = implode(",", $itemTypes);
514 44
        $itemUids = array_map("intval", $itemUids);
515 44
        $uids = array_map("intval", $uids);
516
517 44
        $queryBuilderForDeletingItems = $this->getQueryBuilder();
518 44
        $queryBuilderForDeletingItems->delete($this->table);
519 44
        $queryBuilderForDeletingItems = $this->addItemWhereClauses($queryBuilderForDeletingItems, $rootPageIds, $indexQueueConfigurationList, $itemTypeList, $itemUids, $uids);
520
521 44
        $queryBuilderForDeletingProperties = $this->buildQueryForPropertyDeletion($queryBuilderForDeletingItems, $rootPageIds, $indexQueueConfigurationList, $itemTypeList, $itemUids, $uids);
522
523 44
        $queryBuilderForDeletingItems->getConnection()->beginTransaction();
524
        try {
525 44
            $queryBuilderForDeletingItems->execute();
526 44
            $queryBuilderForDeletingProperties->execute();
527
528 44
            $queryBuilderForDeletingItems->getConnection()->commit();
529
        } catch (Throwable $e) {
530
            $queryBuilderForDeletingItems->getConnection()->rollback();
531
            throw $e;
532
        }
533 44
    }
534
535
    /**
536
     * Initializes the query builder to delete items in the index queue filtered by the passed arguments.
537
     *
538
     * @param QueryBuilder $queryBuilderForDeletingItems
539
     * @param array $rootPageIds filter on a set of rootPageUids.
540
     * @param string $indexQueueConfigurationList
541
     * @param string $itemTypeList
542
     * @param array $itemUids filter on a set of item uids
543
     * @param array $uids filter on a set of queue item uids
544
     * @return QueryBuilder
545
     */
546 46
    private function addItemWhereClauses(
547
        QueryBuilder $queryBuilderForDeletingItems,
548
        array $rootPageIds,
549
        string $indexQueueConfigurationList,
550
        string $itemTypeList,
551
        array $itemUids,
552
        array $uids
553
    ): QueryBuilder {
554 46
        if (!empty($rootPageIds)) {
555 7
            $queryBuilderForDeletingItems->andWhere(
556
                /** @scrutinizer ignore-type */
557 7
                $queryBuilderForDeletingItems->expr()->in('root', $rootPageIds)
558
            );
559
        }
560
561 46
        if (!empty($indexQueueConfigurationList)) {
562 9
            $queryBuilderForDeletingItems->andWhere(
563
                /** @scrutinizer ignore-type */
564 9
                $queryBuilderForDeletingItems->expr()->in(
565 9
                    'indexing_configuration',
566 9
                    $queryBuilderForDeletingItems->createNamedParameter($indexQueueConfigurationList)
567
                )
568
            );
569
        }
570
571 46
        if (!empty($itemTypeList)) {
572 37
            $queryBuilderForDeletingItems->andWhere(
573
                /** @scrutinizer ignore-type */
574 37
                $queryBuilderForDeletingItems->expr()->in(
575 37
                    'item_type',
576 37
                    $queryBuilderForDeletingItems->createNamedParameter($itemTypeList)
577
                )
578
            );
579
        }
580
581 46
        if (!empty($itemUids)) {
582 36
            $queryBuilderForDeletingItems->andWhere(
583
                /** @scrutinizer ignore-type */
584 36
                $queryBuilderForDeletingItems->expr()->in('item_uid', $itemUids)
585
            );
586
        }
587
588 46
        if (!empty($uids)) {
589 1
            $queryBuilderForDeletingItems->andWhere(
590
                /** @scrutinizer ignore-type */
591 1
                $queryBuilderForDeletingItems->expr()->in('uid', $uids)
592
            );
593
        }
594
595 46
        return $queryBuilderForDeletingItems;
596
    }
597
598
    /**
599
     * Initializes a query builder to delete the indexing properties of an item by the passed conditions.
600
     *
601
     * @param QueryBuilder $queryBuilderForDeletingItems
602
     * @param array $rootPageIds
603
     * @param string $indexQueueConfigurationList
604
     * @param string $itemTypeList
605
     * @param array $itemUids
606
     * @param array $uids
607
     * @return QueryBuilder
608
     *
609
     * @throws DBALDriverException
610
     * @throws \Doctrine\DBAL\DBALException
611
     */
612 44
    private function buildQueryForPropertyDeletion(
613
        QueryBuilder $queryBuilderForDeletingItems,
614
        array $rootPageIds,
615
        string $indexQueueConfigurationList,
616
        string $itemTypeList,
617
        array $itemUids,
618
        array $uids
619
    ): QueryBuilder {
620 44
        $queryBuilderForSelectingProperties = $queryBuilderForDeletingItems->getConnection()->createQueryBuilder();
621
        $queryBuilderForSelectingProperties
622 44
            ->select('items.uid')
623 44
            ->from('tx_solr_indexqueue_indexing_property', 'properties')
624 44
            ->innerJoin(
625 44
                'properties',
626 44
                $this->table,
627 44
                'items',
628 44
                (string)$queryBuilderForSelectingProperties->expr()->andX(
629 44
                    $queryBuilderForSelectingProperties->expr()->eq('items.uid', $queryBuilderForSelectingProperties->quoteIdentifier('properties.item_id')),
630 44
                    empty($rootPageIds) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.root', $rootPageIds),
631 44
                    empty($indexQueueConfigurationList) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.indexing_configuration', $queryBuilderForSelectingProperties->createNamedParameter($indexQueueConfigurationList)),
632 44
                    empty($itemTypeList) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.item_type', $queryBuilderForSelectingProperties->createNamedParameter($itemTypeList)),
633 44
                    empty($itemUids) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.item_uid', $itemUids),
634 44
                    empty($uids) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.uid', $uids)
635
                )
636
            );
637 44
        $propertyEntriesToDelete = implode(
638 44
            ',',
639 44
            array_column(
640
                $queryBuilderForSelectingProperties
641 44
                    ->execute()
642 44
                    ->fetchAllAssociative(),
643 44
                'uid'
644
            )
645
        );
646
647 44
        $queryBuilderForDeletingProperties = $queryBuilderForDeletingItems->getConnection()->createQueryBuilder();
648
649
        // make sure executing the property deletion query doesn't fail if there are no properties to delete
650 44
        if (empty($propertyEntriesToDelete)) {
651 43
            $propertyEntriesToDelete = '0';
652
        }
653
654 44
        $queryBuilderForDeletingProperties->delete('tx_solr_indexqueue_indexing_property')->where(
655 44
            $queryBuilderForDeletingProperties->expr()->in('item_id', $propertyEntriesToDelete)
0 ignored issues
show
Bug introduced by
$queryBuilderForDeleting...ropertyEntriesToDelete) of type string is incompatible with the type Doctrine\DBAL\Query\Expr...on|array<integer,mixed> expected by parameter $predicates of TYPO3\CMS\Core\Database\...y\QueryBuilder::where(). ( Ignorable by Annotation )

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

655
            /** @scrutinizer ignore-type */ $queryBuilderForDeletingProperties->expr()->in('item_id', $propertyEntriesToDelete)
Loading history...
656
        );
657
658 44
        return $queryBuilderForDeletingProperties;
659
    }
660
661
    /**
662
     * Removes all items from the Index Queue.
663
     *
664
     * @return int The number of affected rows. For a truncate this is unreliable as there is no meaningful information.
665
     */
666 1
    public function deleteAllItems(): int
667
    {
668 1
        return $this->getQueryBuilder()->getConnection()->truncate($this->table);
669
    }
670
671
    /**
672
     * Gets a single Index Queue item by its uid.
673
     *
674
     * @param int $uid Index Queue item uid
675
     * @return Item|null The request Index Queue item or NULL if no item with $itemId was found
676
     *
677
     * @throws DBALDriverException
678
     * @throws \Doctrine\DBAL\DBALException
679
     */
680 28
    public function findItemByUid(int $uid): ?Item
681
    {
682 28
        $queryBuilder = $this->getQueryBuilder();
683 28
        $indexQueueItemRecord = $queryBuilder
684 28
            ->select('*')
685 28
            ->from($this->table)
686 28
            ->where(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('uid', $uid))
687 28
            ->execute()
688 28
            ->fetchAssociative();
689
690 28
        if (!isset($indexQueueItemRecord['uid'])) {
691 3
            return null;
692
        }
693
694 25
        return GeneralUtility::makeInstance(Item::class, /** @scrutinizer ignore-type */ $indexQueueItemRecord);
695
    }
696
697
    /**
698
     * Gets Index Queue items by type and uid.
699
     *
700
     * @param string $itemType item type, usually  the table name
701
     * @param int $itemUid item uid
702
     * @return Item[] An array of items matching $itemType and $itemUid
703
     *
704
     * @throws ConnectionException
705
     * @throws DBALDriverException
706
     * @throws Throwable
707
     * @throws \Doctrine\DBAL\DBALException
708
     */
709 40
    public function findItemsByItemTypeAndItemUid(string $itemType, int $itemUid): array
710
    {
711 40
        $queryBuilder = $this->getQueryBuilder();
712 40
        $compositeExpression = $queryBuilder->expr()->andX(
713
            /** @scrutinizer ignore-type */
714 40
            $queryBuilder->expr()->eq('item_type', $queryBuilder->getConnection()->quote($itemType, PDO::PARAM_STR)),
715 40
            $queryBuilder->expr()->eq('item_uid', $itemUid)
716
        );
717 40
        return $this->getItemsByCompositeExpression($compositeExpression, $queryBuilder);
718
    }
719
720
    /**
721
     * Returns a collection of items by CompositeExpression.
722
     *
723
     * @param CompositeExpression|null $expression Optional expression to filter records.
724
     * @param QueryBuilder|null $queryBuilder QueryBuilder to use
725
     * @return array
726
     *
727
     * @throws ConnectionException
728
     * @throws DBALDriverException
729
     * @throws Throwable
730
     * @throws \Doctrine\DBAL\DBALException
731
     */
732 40
    protected function getItemsByCompositeExpression(
733
        CompositeExpression $expression = null,
734
        QueryBuilder $queryBuilder = null
735
    ): array {
736 40
        if (!$queryBuilder instanceof QueryBuilder) {
737
            $queryBuilder = $this->getQueryBuilder();
738
        }
739
740 40
        $queryBuilder->select('*')->from($this->table);
741 40
        if (isset($expression)) {
742 40
            $queryBuilder->where($expression);
743
        }
744
745 40
        $indexQueueItemRecords = $queryBuilder
746 40
            ->execute()
747 40
            ->fetchAllAssociative();
748 40
        return $this->getIndexQueueItemObjectsFromRecords($indexQueueItemRecords);
749
    }
750
751
    /**
752
     * Returns all items in the queue.
753
     *
754
     * @return Item[] all Items from Queue without restrictions
755
     *
756
     * @throws ConnectionException
757
     * @throws DBALDriverException
758
     * @throws Throwable
759
     * @throws \Doctrine\DBAL\DBALException
760
     */
761 1
    public function findAll(): array
762
    {
763 1
        $queryBuilder = $this->getQueryBuilder();
764 1
        $allRecords = $queryBuilder
765 1
            ->select('*')
766 1
            ->from($this->table)
767 1
            ->execute()
768 1
            ->fetchAllAssociative();
769 1
        return $this->getIndexQueueItemObjectsFromRecords($allRecords);
770
    }
771
772
    /**
773
     * Gets $limit number of items to index for a particular $site.
774
     *
775
     * @param Site $site TYPO3 site
776
     * @param int $limit Number of items to get from the queue
777
     * @return Item[] Items to index to the given solr server
778
     *
779
     * @throws ConnectionException
780
     * @throws DBALDriverException
781
     * @throws Throwable
782
     * @throws \Doctrine\DBAL\DBALException
783
     */
784 3
    public function findItemsToIndex(Site $site, int $limit = 50): array
785
    {
786 3
        $queryBuilder = $this->getQueryBuilder();
787
        // determine which items to index with this run
788 3
        $indexQueueItemRecords = $queryBuilder
789 3
            ->select('*')
790 3
            ->from($this->table)
791 3
            ->andWhere(
792
                /** @scrutinizer ignore-type */
793 3
                $queryBuilder->expr()->eq('root', $site->getRootPageId()),
794
                /** @scrutinizer ignore-type */
795 3
                $queryBuilder->expr()->gt('changed', 'indexed'),
796
                /** @scrutinizer ignore-type */
797 3
                $queryBuilder->expr()->lte('changed', time()),
798
                /** @scrutinizer ignore-type */
799 3
                $queryBuilder->expr()->eq('errors', $queryBuilder->createNamedParameter(''))
800
            )
801 3
            ->orderBy('indexing_priority', 'DESC')
802 3
            ->addOrderBy('changed', 'DESC')
803 3
            ->addOrderBy('uid', 'DESC')
804 3
            ->setMaxResults($limit)
805 3
            ->execute()
806 3
            ->fetchAllAssociative();
807
808 3
        return $this->getIndexQueueItemObjectsFromRecords($indexQueueItemRecords);
809
    }
810
811
    /**
812
     * Retrieves the count of items that match certain filters. Each filter is passed as parts of the where claus combined with AND.
813
     *
814
     * @param array $sites
815
     * @param array $indexQueueConfigurationNames
816
     * @param array $itemTypes
817
     * @param array $itemUids
818
     * @param array $uids
819
     * @param int $start
820
     * @param int $limit
821
     * @return array
822
     *
823
     * @throws ConnectionException
824
     * @throws DBALDriverException
825
     * @throws Throwable
826
     * @throws \Doctrine\DBAL\DBALException
827
     */
828 1
    public function findItems(
829
        array $sites = [],
830
        array $indexQueueConfigurationNames = [],
831
        array $itemTypes = [],
832
        array $itemUids = [],
833
        array $uids = [],
834
        int   $start = 0,
835
        int   $limit = 50
836
    ): array {
837 1
        $rootPageIds = Site::getRootPageIdsFromSites($sites);
838 1
        $indexQueueConfigurationList = implode(",", $indexQueueConfigurationNames);
839 1
        $itemTypeList = implode(",", $itemTypes);
840 1
        $itemUids = array_map("intval", $itemUids);
841 1
        $uids = array_map("intval", $uids);
842 1
        $itemQueryBuilder = $this->getQueryBuilder()->select('*')->from($this->table);
843 1
        $itemQueryBuilder = $this->addItemWhereClauses($itemQueryBuilder, $rootPageIds, $indexQueueConfigurationList, $itemTypeList, $itemUids, $uids);
844 1
        $itemRecords = $itemQueryBuilder->setFirstResult($start)
845 1
            ->setMaxResults($limit)
846 1
            ->execute()
847 1
            ->fetchAllAssociative();
848 1
        return $this->getIndexQueueItemObjectsFromRecords($itemRecords);
849
    }
850
851
    /**
852
     * Creates an array of ApacheSolrForTypo3\Solr\IndexQueue\Item objects from an array of
853
     * index queue records.
854
     *
855
     * @param array $indexQueueItemRecords Array of plain index queue records
856
     * @return array Array of ApacheSolrForTypo3\Solr\IndexQueue\Item objects
857
     *
858
     * @throws ConnectionException
859
     * @throws DBALDriverException
860
     * @throws Throwable
861
     * @throws \Doctrine\DBAL\DBALException
862
     */
863 42
    protected function getIndexQueueItemObjectsFromRecords(array $indexQueueItemRecords): array
864
    {
865 42
        $tableRecords = $this->getAllQueueItemRecordsByUidsGroupedByTable($indexQueueItemRecords);
866 42
        return $this->getQueueItemObjectsByRecords($indexQueueItemRecords, $tableRecords);
867
    }
868
869
    /**
870
     * Returns the records for suitable item type.
871
     *
872
     * @param array $indexQueueItemRecords
873
     * @return array
874
     *
875
     * @throws DBALDriverException
876
     * @throws \Doctrine\DBAL\DBALException
877
     */
878 42
    protected function getAllQueueItemRecordsByUidsGroupedByTable(array $indexQueueItemRecords): array
879
    {
880 42
        $tableUids = [];
881 42
        $tableRecords = [];
882
        // grouping records by table
883 42
        foreach ($indexQueueItemRecords as $indexQueueItemRecord) {
884 40
            $tableUids[$indexQueueItemRecord['item_type']][] = $indexQueueItemRecord['item_uid'];
885
        }
886
887
        // fetching records by table, saves us a lot of single queries
888 42
        foreach ($tableUids as $table => $uids) {
889 40
            $uidList = implode(',', $uids);
890
891 40
            $queryBuilderForRecordTable = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
892 40
            $queryBuilderForRecordTable->getRestrictions()->removeAll();
893 40
            $resultsFromRecordTable = $queryBuilderForRecordTable
894 40
                ->select('*')
895 40
                ->from($table)
896 40
                ->where(/** @scrutinizer ignore-type */ $queryBuilderForRecordTable->expr()->in('uid', $uidList))
897 40
                ->execute();
898 40
            $records = [];
899 40
            while ($record = $resultsFromRecordTable->fetchAssociative()) {
900 39
                $records[$record['uid']] = $record;
901
            }
902
903 40
            $tableRecords[$table] = $records;
904 40
            $this->hookPostProcessFetchRecordsForIndexQueueItem($table, $uids, $tableRecords);
905
        }
906
907 42
        return $tableRecords;
908
    }
909
910
    /**
911
     * Calls defined in postProcessFetchRecordsForIndexQueueItem hook method.
912
     *
913
     * @param string $table
914
     * @param array $uids
915
     * @param array $tableRecords
916
     *
917
     * @return void
918
     */
919 40
    protected function hookPostProcessFetchRecordsForIndexQueueItem(string $table, array $uids, array &$tableRecords)
920
    {
921 40
        if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessFetchRecordsForIndexQueueItem'] ?? null)) {
922 40
            return;
923
        }
924
        $params = ['table' => $table, 'uids' => $uids, 'tableRecords' => &$tableRecords];
925
        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessFetchRecordsForIndexQueueItem'] as $reference) {
926
            GeneralUtility::callUserFunction($reference, $params, $this);
927
        }
928
    }
929
930
    /**
931
     * Instantiates a list of Item objects from database records.
932
     *
933
     * @param array $indexQueueItemRecords records from database
934
     * @param array $tableRecords
935
     * @return array
936
     *
937
     * @throws ConnectionException
938
     * @throws Throwable
939
     * @throws \Doctrine\DBAL\DBALException
940
     */
941 42
    protected function getQueueItemObjectsByRecords(array $indexQueueItemRecords, array $tableRecords): array
942
    {
943 42
        $indexQueueItems = [];
944 42
        foreach ($indexQueueItemRecords as $indexQueueItemRecord) {
945 40
            if (isset($tableRecords[$indexQueueItemRecord['item_type']][$indexQueueItemRecord['item_uid']])) {
946 39
                $indexQueueItems[] = GeneralUtility::makeInstance(
947 39
                    Item::class,
948
                    /** @scrutinizer ignore-type */
949 39
                    $indexQueueItemRecord,
950
                    /** @scrutinizer ignore-type */
951 39
                    $tableRecords[$indexQueueItemRecord['item_type']][$indexQueueItemRecord['item_uid']]
952
                );
953
            } else {
954 1
                $this->logger->log(
955 1
                    SolrLogManager::ERROR,
956 1
                    'Record missing for Index Queue item. Item removed.',
957
                    [
958 1
                        $indexQueueItemRecord
959
                    ]
960
                );
961 1
                $this->deleteItem(
962 1
                    $indexQueueItemRecord['item_type'],
963 1
                    $indexQueueItemRecord['item_uid']
964
                );
965
            }
966
        }
967
968 42
        return $indexQueueItems;
969
    }
970
971
    /**
972
     * Marks an item as failed and causes the indexer to skip the item in the
973
     * next run.
974
     *
975
     * @param int|Item $item Either the item's Index Queue uid or the complete item
976
     * @param string $errorMessage Error message
977
     * @return int affected rows
978
     *
979
     * @throws \Doctrine\DBAL\DBALException
980
     */
981 6
    public function markItemAsFailed($item, string $errorMessage = ''): int
982
    {
983 6
        $itemUid = ($item instanceof Item) ? $item->getIndexQueueUid() : (int)$item;
984 6
        $errorMessage = empty($errorMessage) ? '1' : $errorMessage;
985
986 6
        $queryBuilder = $this->getQueryBuilder();
987
        return (int)$queryBuilder
988 6
            ->update($this->table)
989 6
            ->set('errors', $errorMessage)
990 6
            ->where($queryBuilder->expr()->eq('uid', $itemUid))
0 ignored issues
show
Bug introduced by
$queryBuilder->expr()->eq('uid', $itemUid) of type string is incompatible with the type Doctrine\DBAL\Query\Expr...on|array<integer,mixed> expected by parameter $predicates of TYPO3\CMS\Core\Database\...y\QueryBuilder::where(). ( Ignorable by Annotation )

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

990
            ->where(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('uid', $itemUid))
Loading history...
991 6
            ->execute();
992
    }
993
994
    /**
995
     * Sets the timestamp of when an item last has been indexed.
996
     *
997
     * @param Item $item
998
     * @return int affected rows
999
     *
1000
     * @throws \Doctrine\DBAL\DBALException
1001
     */
1002 2
    public function updateIndexTimeByItem(Item $item): int
1003
    {
1004 2
        $queryBuilder = $this->getQueryBuilder();
1005
        return (int)$queryBuilder
1006 2
            ->update($this->table)
1007 2
            ->set('indexed', time())
1008 2
            ->where($queryBuilder->expr()->eq('uid', $item->getIndexQueueUid()))
0 ignored issues
show
Bug introduced by
$queryBuilder->expr()->e...em->getIndexQueueUid()) of type string is incompatible with the type Doctrine\DBAL\Query\Expr...on|array<integer,mixed> expected by parameter $predicates of TYPO3\CMS\Core\Database\...y\QueryBuilder::where(). ( Ignorable by Annotation )

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

1008
            ->where(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('uid', $item->getIndexQueueUid()))
Loading history...
1009 2
            ->execute();
1010
    }
1011
1012
    /**
1013
     * Sets the change timestamp of an item.
1014
     *
1015
     * @param Item $item
1016
     * @param int $changedTime
1017
     * @return int affected rows
1018
     *
1019
     * @throws \Doctrine\DBAL\DBALException
1020
     */
1021
    public function updateChangedTimeByItem(Item $item, int $changedTime): int
1022
    {
1023
        $queryBuilder = $this->getQueryBuilder();
1024
        return (int)$queryBuilder
1025
            ->update($this->table)
1026
            ->set('changed', $changedTime)
1027
            ->where($queryBuilder->expr()->eq('uid', $item->getIndexQueueUid()))
0 ignored issues
show
Bug introduced by
$queryBuilder->expr()->e...em->getIndexQueueUid()) of type string is incompatible with the type Doctrine\DBAL\Query\Expr...on|array<integer,mixed> expected by parameter $predicates of TYPO3\CMS\Core\Database\...y\QueryBuilder::where(). ( Ignorable by Annotation )

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

1027
            ->where(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('uid', $item->getIndexQueueUid()))
Loading history...
1028
            ->execute();
1029
    }
1030
1031
    /**
1032
     * Initializes Queue by given sql
1033
     *
1034
     * Note: Do not use platform specific functions!
1035
     *
1036
     * @param string $sqlStatement Native SQL statement
1037
     * @return int The number of affected rows.
1038
     *
1039
     * @throws DBALException
1040
     * @internal
1041
     */
1042 13
    public function initializeByNativeSQLStatement(string $sqlStatement): int
1043
    {
1044 13
        return $this->getQueryBuilder()
1045 13
            ->getConnection()
1046 13
            ->executeStatement($sqlStatement);
1047
    }
1048
1049
    /**
1050
     * Retrieves an array of pageIds from mountPoints that already have a queue entry.
1051
     *
1052
     * @param string $identifier identifier of the mount point
1053
     * @return array pageIds from mountPoints that already have a queue entry
1054
     *
1055
     * @throws DBALDriverException
1056
     * @throws \Doctrine\DBAL\DBALException
1057
     */
1058 7
    public function findPageIdsOfExistingMountPagesByMountIdentifier(string $identifier): array
1059
    {
1060 7
        $queryBuilder = $this->getQueryBuilder();
1061 7
        $resultSet = $queryBuilder
1062 7
            ->select('item_uid')
1063 7
            ->add('select', $queryBuilder->expr()->count('*', 'queueItemCount'), true)
1064 7
            ->from($this->table)
1065 7
            ->where(
1066 7
                $queryBuilder->expr()->eq('item_type', $queryBuilder->createNamedParameter('pages')),
0 ignored issues
show
Bug introduced by
$queryBuilder->expr()->e...amedParameter('pages')) of type string is incompatible with the type Doctrine\DBAL\Query\Expr...on|array<integer,mixed> expected by parameter $predicates of TYPO3\CMS\Core\Database\...y\QueryBuilder::where(). ( Ignorable by Annotation )

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

1066
                /** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('item_type', $queryBuilder->createNamedParameter('pages')),
Loading history...
1067 7
                $queryBuilder->expr()->eq('pages_mountidentifier', $queryBuilder->createNamedParameter($identifier))
1068
            )
1069 7
            ->groupBy('item_uid')
1070 7
            ->execute();
1071
1072 7
        $mountedPagesIdsWithQueueItems = [];
1073 7
        while ($record = $resultSet->fetchAssociative()) {
1074
            if ($record['queueItemCount'] > 0) {
1075
                $mountedPagesIdsWithQueueItems[] = $record['item_uid'];
1076
            }
1077
        }
1078
1079 7
        return $mountedPagesIdsWithQueueItems;
1080
    }
1081
1082
    /**
1083
     * Retrieves an array of items for mount destinations matched by root page ID, Mount Identifier and a list of mounted page IDs.
1084
     *
1085
     * @param int $rootPid
1086
     * @param string $identifier identifier of the mount point
1087
     * @param array $mountedPids An array of mounted page IDs
1088
     * @return array
1089
     *
1090
     * @throws DBALDriverException
1091
     * @throws \Doctrine\DBAL\DBALException
1092
     */
1093 7
    public function findAllIndexQueueItemsByRootPidAndMountIdentifierAndMountedPids(
1094
        int $rootPid,
1095
        string $identifier,
1096
        array $mountedPids
1097
    ): array {
1098 7
        $queryBuilder = $this->getQueryBuilder();
1099
        return $queryBuilder
1100 7
            ->select('*')
1101 7
            ->from($this->table)
1102 7
            ->where(
1103 7
                $queryBuilder->expr()->eq('root', $queryBuilder->createNamedParameter($rootPid, PDO::PARAM_INT)),
0 ignored issues
show
Bug introduced by
$queryBuilder->expr()->e...otPid, PDO::PARAM_INT)) of type string is incompatible with the type Doctrine\DBAL\Query\Expr...on|array<integer,mixed> expected by parameter $predicates of TYPO3\CMS\Core\Database\...y\QueryBuilder::where(). ( Ignorable by Annotation )

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

1103
                /** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('root', $queryBuilder->createNamedParameter($rootPid, PDO::PARAM_INT)),
Loading history...
1104 7
                $queryBuilder->expr()->eq('item_type', $queryBuilder->createNamedParameter('pages')),
1105 7
                $queryBuilder->expr()->in('item_uid', $mountedPids),
1106 7
                $queryBuilder->expr()->eq('has_indexing_properties', $queryBuilder->createNamedParameter(1, PDO::PARAM_INT)),
1107 7
                $queryBuilder->expr()->eq('pages_mountidentifier', $queryBuilder->createNamedParameter($identifier))
1108
            )
1109 7
            ->execute()
1110 7
            ->fetchAllAssociative();
1111
    }
1112
1113
    /**
1114
     * Updates has_indexing_properties field for given Item
1115
     *
1116
     * @param int $itemUid
1117
     * @param bool $hasIndexingPropertiesFlag
1118
     * @return int number of affected rows, 1 on success
1119
     *
1120
     * @throws \Doctrine\DBAL\DBALException
1121
     */
1122 9
    public function updateHasIndexingPropertiesFlagByItemUid(int $itemUid, bool $hasIndexingPropertiesFlag): int
1123
    {
1124 9
        $queryBuilder = $this->getQueryBuilder();
1125
        return (int)$queryBuilder
1126 9
            ->update($this->table)
1127 9
            ->where(
1128
                /** @scrutinizer ignore-type */
1129 9
                $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($itemUid, PDO::PARAM_INT))
1130
            )
1131 9
            ->set(
1132 9
                'has_indexing_properties',
1133 9
                $queryBuilder->createNamedParameter($hasIndexingPropertiesFlag, PDO::PARAM_INT),
1134 9
                false
1135 9
            )->execute();
1136
    }
1137
}
1138