Failed Conditions
Push — task/2976_TYPO3.11_compatibili... ( f1093c...e29358 )
by Rafael
28:11
created

updateHasIndexingPropertiesFlagByItemUid()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 10
c 0
b 0
f 0
dl 0
loc 14
ccs 10
cts 10
cp 1
rs 9.9332
cc 1
nc 1
nop 2
crap 1
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 133
    public function __construct(SolrLogManager $logManager = null)
57
    {
58 133
        $this->logger = $logManager ?? GeneralUtility::makeInstance(
59 133
            SolrLogManager::class,
60
            /** @scrutinizer ignore-type */
61 133
            __CLASS__
62
        );
63 133
    }
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 $this->getPreparedFlushErrorQuery($queryBuilder)
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getPrepare...otPageId()))->execute() returns the type Doctrine\DBAL\ForwardCompatibility\Result which is incompatible with the type-hinted return integer.
Loading history...
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 $this->getPreparedFlushErrorQuery($queryBuilder)
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getPrepare...QueueUid()))->execute() returns the type Doctrine\DBAL\ForwardCompatibility\Result which is incompatible with the type-hinted return integer.
Loading history...
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 13
                $queryBuilder->expr()->eq('item_uid', $itemUid),
0 ignored issues
show
Bug introduced by
$queryBuilder->expr()->eq('item_uid', $itemUid) 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

215
                /** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('item_uid', $itemUid),
Loading history...
216 13
                $queryBuilder->expr()->eq('root', $rootPageId)
217
            );
218
219 13
        if (!empty($indexingConfiguration)) {
220 13
            $queryBuilder->set('indexing_configuration', $indexingConfiguration);
221
        }
222
223 13
        return (int)$queryBuilder->execute();
224
    }
225
226
    /**
227
     * Adds an item to the index queue.
228
     *
229
     * Not meant for public use.
230
     *
231
     * @param string $itemType The item's type, usually a table name.
232
     * @param int $itemUid The item's uid, usually an integer uid, could be a different value for non-database-record types.
233
     * @param int $rootPageId
234
     * @param int $changedTime
235
     * @param string $indexingConfiguration The item's indexing configuration to use. Optional, overwrites existing / determined configuration.
236
     * @return int the number of inserted rows, which is typically 1
237
     *
238
     * @throws \Doctrine\DBAL\DBALException
239
     */
240 56
    public function add(
241
        string $itemType,
242
        int $itemUid,
243
        int $rootPageId,
244
        int $changedTime,
245
        string $indexingConfiguration
246
    ): int {
247 56
        $queryBuilder = $this->getQueryBuilder();
248
        return (int)$queryBuilder
249 56
            ->insert($this->table)
250 56
            ->values([
251 56
                'root' => $rootPageId,
252 56
                'item_type' => $itemType,
253 56
                'item_uid' => $itemUid,
254 56
                'changed' => $changedTime,
255 56
                'errors' => '',
256 56
                'indexing_configuration' => $indexingConfiguration
257
            ])
258 56
            ->execute();
259
    }
260
261
    /**
262
     * Retrieves the count of items that match certain filters. Each filter is passed as parts of the where claus combined with AND.
263
     *
264
     * @param array $sites
265
     * @param array $indexQueueConfigurationNames
266
     * @param array $itemTypes
267
     * @param array $itemUids
268
     * @param array $uids
269
     * @return int
270
     *
271
     * @throws DBALDriverException
272
     * @throws \Doctrine\DBAL\DBALException
273
     */
274 1
    public function countItems(
275
        array $sites = [],
276
        array $indexQueueConfigurationNames = [],
277
        array $itemTypes = [],
278
        array $itemUids = [],
279
        array $uids = []
280
    ): int {
281 1
        $rootPageIds = Site::getRootPageIdsFromSites($sites);
282 1
        $indexQueueConfigurationList = implode(',', $indexQueueConfigurationNames);
283 1
        $itemTypeList = implode(',', $itemTypes);
284 1
        $itemUids = array_map('intval', $itemUids);
285 1
        $uids = array_map('intval', $uids);
286
287 1
        $queryBuilderForCountingItems = $this->getQueryBuilder();
288 1
        $queryBuilderForCountingItems->count('uid')->from($this->table);
289 1
        $queryBuilderForCountingItems = $this->addItemWhereClauses(
290 1
            $queryBuilderForCountingItems,
291
            $rootPageIds,
292
            $indexQueueConfigurationList,
293
            $itemTypeList,
294
            $itemUids,
295
            $uids
296
        );
297
298
        return (int)$queryBuilderForCountingItems
299 1
            ->execute()
300 1
            ->fetchOne();
301
    }
302
303
    /**
304
     * Gets the most recent changed time of a page's content elements
305
     *
306
     * @param int $pageUid
307
     * @return int|null Timestamp of the most recent content element change or null if nothing is found.
308
     *
309
     * @throws DBALDriverException
310
     * @throws \Doctrine\DBAL\DBALException
311
     */
312 38
    public function getPageItemChangedTimeByPageUid(int $pageUid): ?int
313
    {
314 38
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
315 38
            ->getQueryBuilderForTable('tt_content');
316 38
        $queryBuilder->getRestrictions()->removeAll();
317
        $pageContentLastChangedTime = $queryBuilder
318 38
            ->add('select', $queryBuilder->expr()->max('tstamp', 'changed_time'))
319 38
            ->from('tt_content')
320 38
            ->where(
321
                /** @scrutinizer ignore-type */
322 38
                $queryBuilder->expr()->eq('pid', $pageUid)
323
            )
324 38
            ->execute()
325 38
            ->fetchAssociative();
326
327 38
        return $pageContentLastChangedTime['changed_time'];
328
    }
329
330
    /**
331
     * Gets the most recent changed time for an item taking into account
332
     * localized records.
333
     *
334
     * @param string $itemType The item's type, usually a table name.
335
     * @param int $itemUid The item's uid
336
     * @return int Timestamp of the most recent content element change
337
     *
338
     * @throws DBALDriverException
339
     * @throws \Doctrine\DBAL\DBALException
340
     */
341 61
    public function getLocalizableItemChangedTime(string $itemType, int $itemUid): int
342
    {
343 61
        $localizedChangedTime = 0;
344
345 61
        if (isset($GLOBALS['TCA'][$itemType]['ctrl']['transOrigPointerField'])) {
346
            // table is localizable
347 61
            $translationOriginalPointerField = $GLOBALS['TCA'][$itemType]['ctrl']['transOrigPointerField'];
348 61
            $timeStampField = $GLOBALS['TCA'][$itemType]['ctrl']['tstamp'];
349
350 61
            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($itemType);
351 61
            $queryBuilder->getRestrictions()->removeAll();
352
            $localizedChangedTime = $queryBuilder
353 61
                ->add('select', $queryBuilder->expr()->max($timeStampField, 'changed_time'))
354 61
                ->from($itemType)
355 61
                ->orWhere(
356
                    /** @scrutinizer ignore-type */
357 61
                    $queryBuilder->expr()->eq('uid', $itemUid),
358 61
                    $queryBuilder->expr()->eq($translationOriginalPointerField, $itemUid)
359
                )
360 61
                ->execute()
361 61
                ->fetchOne();
362
        }
363 61
        return (int)$localizedChangedTime;
364
    }
365
366
    /**
367
     * Returns prepared QueryBuilder for contains* methods in this repository
368
     *
369
     * @param string $itemType
370
     * @param int $itemUid
371
     * @return QueryBuilder
372
     */
373 67
    protected function getQueryBuilderForContainsMethods(string $itemType, int $itemUid): QueryBuilder
374
    {
375 67
        $queryBuilder = $this->getQueryBuilder();
376 67
        return $queryBuilder->count('uid')->from($this->table)
377 67
            ->andWhere(
378
                /** @scrutinizer ignore-type */
379 67
                $queryBuilder->expr()->eq('item_type', $queryBuilder->createNamedParameter($itemType)),
380 67
                $queryBuilder->expr()->eq('item_uid', $itemUid)
0 ignored issues
show
Bug introduced by
$queryBuilder->expr()->eq('item_uid', $itemUid) 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

380
                /** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('item_uid', $itemUid)
Loading history...
381
            );
382
    }
383
384
    /**
385
     * Checks whether the Index Queue contains a specific item.
386
     *
387
     * @param string $itemType The item's type, usually a table name.
388
     * @param int $itemUid The item's uid
389
     * @return bool TRUE if the item is found in the queue, FALSE otherwise
390
     *
391
     * @throws \Doctrine\DBAL\DBALException
392
     * @throws DBALDriverException
393
     */
394 8
    public function containsItem(string $itemType, int $itemUid): bool
395
    {
396 8
        return (bool)$this->getQueryBuilderForContainsMethods($itemType, $itemUid)
397 8
            ->execute()
398 8
            ->fetchOne();
399
    }
400
401
    /**
402
     * Checks whether the Index Queue contains a specific item.
403
     *
404
     * @param string $itemType The item's type, usually a table name.
405
     * @param int $itemUid The item's uid
406
     * @param integer $rootPageId
407
     * @return bool TRUE if the item is found in the queue, FALSE otherwise
408
     *
409
     * @throws \Doctrine\DBAL\DBALException
410
     * @throws DBALDriverException
411
     */
412 61
    public function containsItemWithRootPageId(string $itemType, int $itemUid, int $rootPageId): bool
413
    {
414 61
        $queryBuilder = $this->getQueryBuilderForContainsMethods($itemType, $itemUid);
415
        return (bool)$queryBuilder
416 61
            ->andWhere(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('root', $rootPageId))
417 61
            ->execute()
418 61
            ->fetchOne();
419
    }
420
421
    /**
422
     * Checks whether the Index Queue contains a specific item that has been
423
     * marked as indexed.
424
     *
425
     * @param string $itemType The item's type, usually a table name.
426
     * @param int $itemUid The item's uid
427
     * @return bool TRUE if the item is found in the queue and marked as indexed, FALSE otherwise
428
     *
429
     * @throws \Doctrine\DBAL\DBALException
430
     * @throws DBALDriverException
431
     */
432 2
    public function containsIndexedItem(string $itemType, int $itemUid): bool
433
    {
434 2
        $queryBuilder = $this->getQueryBuilderForContainsMethods($itemType, $itemUid);
435
        return (bool)$queryBuilder
436 2
            ->andWhere(/** @scrutinizer ignore-type */ $queryBuilder->expr()->gt('indexed', 0))
437 2
            ->execute()
438 2
            ->fetchOne();
439
    }
440
441
    /**
442
     * Removes an item from the Index Queue.
443
     *
444
     * @param string $itemType The type of the item to remove, usually a table name.
445
     * @param int|null $itemUid The uid of the item to remove
446
     *
447
     * @throws ConnectionException
448
     * @throws Throwable
449
     * @throws \Doctrine\DBAL\DBALException
450
     */
451 37
    public function deleteItem(string $itemType, int $itemUid = null)
452
    {
453 37
        $itemUids = empty($itemUid) ? [] : [$itemUid];
454 37
        $this->deleteItems([], [], [$itemType], $itemUids);
455 37
    }
456
457
    /**
458
     * Removes all items of a certain type from the Index Queue.
459
     *
460
     * @param string $itemType The type of items to remove, usually a table name.
461
     *
462
     * @throws ConnectionException
463
     * @throws Throwable
464
     * @throws \Doctrine\DBAL\DBALException
465
     */
466 1
    public function deleteItemsByType(string $itemType)
467
    {
468 1
        $this->deleteItem($itemType);
469 1
    }
470
471
    /**
472
     * Removes all items of a certain site from the Index Queue. Accepts an
473
     * optional parameter to limit the deleted items by indexing configuration.
474
     *
475
     * @param Site $site The site to remove items for.
476
     * @param string $indexingConfigurationName Name of a specific indexing configuration
477
     *
478
     * @throws ConnectionException
479
     * @throws Throwable
480
     * @throws \Doctrine\DBAL\DBALException
481
     */
482 7
    public function deleteItemsBySite(Site $site, string $indexingConfigurationName = '')
483
    {
484 7
        $indexingConfigurationNames = empty($indexingConfigurationName) ? [] : [$indexingConfigurationName];
485 7
        $this->deleteItems([$site], $indexingConfigurationNames);
486 7
    }
487
488
    /**
489
     * Removes items in the index queue filtered by the passed arguments.
490
     *
491
     * @param array $sites
492
     * @param array $indexQueueConfigurationNames
493
     * @param array $itemTypes
494
     * @param array $itemUids
495
     * @param array $uids
496
     *
497
     * @throws ConnectionException
498
     * @throws \Doctrine\DBAL\DBALException
499
     * @throws Throwable
500
     */
501 44
    public function deleteItems(
502
        array $sites = [],
503
        array $indexQueueConfigurationNames = [],
504
        array $itemTypes = [],
505
        array $itemUids = [],
506
        array $uids = []
507
    ): void {
508 44
        $rootPageIds = Site::getRootPageIdsFromSites($sites);
509 44
        $indexQueueConfigurationList = implode(",", $indexQueueConfigurationNames);
510 44
        $itemTypeList = implode(",", $itemTypes);
511 44
        $itemUids = array_map("intval", $itemUids);
512 44
        $uids = array_map("intval", $uids);
513
514 44
        $queryBuilderForDeletingItems = $this->getQueryBuilder();
515 44
        $queryBuilderForDeletingItems->delete($this->table);
516 44
        $queryBuilderForDeletingItems = $this->addItemWhereClauses($queryBuilderForDeletingItems, $rootPageIds, $indexQueueConfigurationList, $itemTypeList, $itemUids, $uids);
517
518 44
        $queryBuilderForDeletingProperties = $this->buildQueryForPropertyDeletion($queryBuilderForDeletingItems, $rootPageIds, $indexQueueConfigurationList, $itemTypeList, $itemUids, $uids);
519
520 44
        $queryBuilderForDeletingItems->getConnection()->beginTransaction();
521
        try {
522 44
            $queryBuilderForDeletingItems->execute();
523 44
            $queryBuilderForDeletingProperties->execute();
524
525 44
            $queryBuilderForDeletingItems->getConnection()->commit();
526
        } catch (Throwable $e) {
527
            $queryBuilderForDeletingItems->getConnection()->rollback();
528
            throw $e;
529
        }
530 44
    }
531
532
    /**
533
     * Initializes the query builder to delete items in the index queue filtered by the passed arguments.
534
     *
535
     * @param QueryBuilder $queryBuilderForDeletingItems
536
     * @param array $rootPageIds filter on a set of rootPageUids.
537
     * @param string $indexQueueConfigurationList
538
     * @param string $itemTypeList
539
     * @param array $itemUids filter on a set of item uids
540
     * @param array $uids filter on a set of queue item uids
541
     * @return QueryBuilder
542
     */
543 46
    private function addItemWhereClauses(
544
        QueryBuilder $queryBuilderForDeletingItems,
545
        array $rootPageIds,
546
        string $indexQueueConfigurationList,
547
        string $itemTypeList,
548
        array $itemUids,
549
        array $uids
550
    ): QueryBuilder {
551 46
        if (!empty($rootPageIds)) {
552 7
            $queryBuilderForDeletingItems->andWhere(
553
                /** @scrutinizer ignore-type */
554 7
                $queryBuilderForDeletingItems->expr()->in('root', $rootPageIds)
555
            );
556
        }
557
558 46
        if (!empty($indexQueueConfigurationList)) {
559 9
            $queryBuilderForDeletingItems->andWhere(
560
                /** @scrutinizer ignore-type */
561 9
                $queryBuilderForDeletingItems->expr()->in(
562 9
                    'indexing_configuration',
563 9
                    $queryBuilderForDeletingItems->createNamedParameter($indexQueueConfigurationList)
564
                )
565
            );
566
        }
567
568 46
        if (!empty($itemTypeList)) {
569 37
            $queryBuilderForDeletingItems->andWhere(
570
                /** @scrutinizer ignore-type */
571 37
                $queryBuilderForDeletingItems->expr()->in(
572 37
                    'item_type',
573 37
                    $queryBuilderForDeletingItems->createNamedParameter($itemTypeList)
574
                )
575
            );
576
        }
577
578 46
        if (!empty($itemUids)) {
579 36
            $queryBuilderForDeletingItems->andWhere($queryBuilderForDeletingItems->expr()->in('item_uid', $itemUids));
0 ignored issues
show
Bug introduced by
$queryBuilderForDeleting...('item_uid', $itemUids) 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

579
            $queryBuilderForDeletingItems->andWhere(/** @scrutinizer ignore-type */ $queryBuilderForDeletingItems->expr()->in('item_uid', $itemUids));
Loading history...
580
        }
581
582 46
        if (!empty($uids)) {
583 1
            $queryBuilderForDeletingItems->andWhere($queryBuilderForDeletingItems->expr()->in('uid', $uids));
584
        }
585
586 46
        return $queryBuilderForDeletingItems;
587
    }
588
589
    /**
590
     * Initializes a query builder to delete the indexing properties of an item by the passed conditions.
591
     *
592
     * @param QueryBuilder $queryBuilderForDeletingItems
593
     * @param array $rootPageIds
594
     * @param string $indexQueueConfigurationList
595
     * @param string $itemTypeList
596
     * @param array $itemUids
597
     * @param array $uids
598
     * @return QueryBuilder
599
     *
600
     * @throws DBALDriverException
601
     * @throws \Doctrine\DBAL\DBALException
602
     */
603 44
    private function buildQueryForPropertyDeletion(
604
        QueryBuilder $queryBuilderForDeletingItems,
605
        array $rootPageIds,
606
        string $indexQueueConfigurationList,
607
        string $itemTypeList,
608
        array $itemUids,
609
        array $uids
610
    ): QueryBuilder {
611 44
        $queryBuilderForSelectingProperties = $queryBuilderForDeletingItems->getConnection()->createQueryBuilder();
612
        $queryBuilderForSelectingProperties
613 44
            ->select('items.uid')
614 44
            ->from('tx_solr_indexqueue_indexing_property', 'properties')
615 44
            ->innerJoin(
616 44
                'properties',
617 44
                $this->table,
618 44
                'items',
619 44
                (string)$queryBuilderForSelectingProperties->expr()->andX(
620 44
                    $queryBuilderForSelectingProperties->expr()->eq('items.uid', $queryBuilderForSelectingProperties->quoteIdentifier('properties.item_id')),
621 44
                    empty($rootPageIds) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.root', $rootPageIds),
622 44
                    empty($indexQueueConfigurationList) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.indexing_configuration', $queryBuilderForSelectingProperties->createNamedParameter($indexQueueConfigurationList)),
623 44
                    empty($itemTypeList) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.item_type', $queryBuilderForSelectingProperties->createNamedParameter($itemTypeList)),
624 44
                    empty($itemUids) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.item_uid', $itemUids),
625 44
                    empty($uids) ? '' : $queryBuilderForSelectingProperties->expr()->in('items.uid', $uids)
626
                )
627
            );
628 44
        $propertyEntriesToDelete = implode(
629 44
            ',',
630 44
            array_column(
631
                $queryBuilderForSelectingProperties
632 44
                    ->execute()
633 44
                    ->fetchAllAssociative(),
634 44
                'uid'
635
            )
636
        );
637
638 44
        $queryBuilderForDeletingProperties = $queryBuilderForDeletingItems->getConnection()->createQueryBuilder();
639
640
        // make sure executing the property deletion query doesn't fail if there are no properties to delete
641 44
        if (empty($propertyEntriesToDelete)) {
642 43
            $propertyEntriesToDelete = '0';
643
        }
644
645 44
        $queryBuilderForDeletingProperties->delete('tx_solr_indexqueue_indexing_property')->where(
646 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

646
            /** @scrutinizer ignore-type */ $queryBuilderForDeletingProperties->expr()->in('item_id', $propertyEntriesToDelete)
Loading history...
647
        );
648
649 44
        return $queryBuilderForDeletingProperties;
650
    }
651
652
    /**
653
     * Removes all items from the Index Queue.
654
     *
655
     * @return int The number of affected rows. For a truncate this is unreliable as there is no meaningful information.
656
     */
657 1
    public function deleteAllItems(): int
658
    {
659 1
        return $this->getQueryBuilder()->getConnection()->truncate($this->table);
660
    }
661
662
    /**
663
     * Gets a single Index Queue item by its uid.
664
     *
665
     * @param int $uid Index Queue item uid
666
     * @return Item|null The request Index Queue item or NULL if no item with $itemId was found
667
     *
668
     * @throws DBALDriverException
669
     * @throws \Doctrine\DBAL\DBALException
670
     */
671 28
    public function findItemByUid(int $uid): ?Item
672
    {
673 28
        $queryBuilder = $this->getQueryBuilder();
674
        $indexQueueItemRecord = $queryBuilder
675 28
            ->select('*')
676 28
            ->from($this->table)
677 28
            ->where(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('uid', $uid))
678 28
            ->execute()
679 28
            ->fetchAssociative();
680
681 28
        if (!isset($indexQueueItemRecord['uid'])) {
682 3
            return null;
683
        }
684
685 25
        return GeneralUtility::makeInstance(Item::class, /** @scrutinizer ignore-type */ $indexQueueItemRecord);
686
    }
687
688
    /**
689
     * Gets Index Queue items by type and uid.
690
     *
691
     * @param string $itemType item type, usually  the table name
692
     * @param int $itemUid item uid
693
     * @return Item[] An array of items matching $itemType and $itemUid
694
     *
695
     * @throws ConnectionException
696
     * @throws DBALDriverException
697
     * @throws Throwable
698
     * @throws \Doctrine\DBAL\DBALException
699
     */
700 40
    public function findItemsByItemTypeAndItemUid(string $itemType, int $itemUid): array
701
    {
702 40
        $queryBuilder = $this->getQueryBuilder();
703 40
        $compositeExpression = $queryBuilder->expr()->andX(
704
            /** @scrutinizer ignore-type */
705 40
            $queryBuilder->expr()->eq('item_type', $queryBuilder->getConnection()->quote($itemType, PDO::PARAM_STR)),
706 40
            $queryBuilder->expr()->eq('item_uid', $itemUid)
707
        );
708 40
        return $this->getItemsByCompositeExpression($compositeExpression, $queryBuilder);
709
    }
710
711
    /**
712
     * Returns a collection of items by CompositeExpression.
713
     *
714
     * @param CompositeExpression|null $expression Optional expression to filter records.
715
     * @param QueryBuilder|null $queryBuilder QueryBuilder to use
716
     * @return array
717
     *
718
     * @throws ConnectionException
719
     * @throws DBALDriverException
720
     * @throws Throwable
721
     * @throws \Doctrine\DBAL\DBALException
722
     */
723 40
    protected function getItemsByCompositeExpression(
724
        CompositeExpression $expression = null,
725
        QueryBuilder $queryBuilder = null
726
    ): array {
727 40
        if (!$queryBuilder instanceof QueryBuilder) {
728
            $queryBuilder = $this->getQueryBuilder();
729
        }
730
731 40
        $queryBuilder->select('*')->from($this->table);
732 40
        if (isset($expression)) {
733 40
            $queryBuilder->where($expression);
734
        }
735
736
        $indexQueueItemRecords = $queryBuilder
737 40
            ->execute()
738 40
            ->fetchAllAssociative();
739 40
        return $this->getIndexQueueItemObjectsFromRecords($indexQueueItemRecords);
740
    }
741
742
    /**
743
     * Returns all items in the queue.
744
     *
745
     * @return Item[] all Items from Queue without restrictions
746
     *
747
     * @throws ConnectionException
748
     * @throws DBALDriverException
749
     * @throws Throwable
750
     * @throws \Doctrine\DBAL\DBALException
751
     */
752 1
    public function findAll(): array
753
    {
754 1
        $queryBuilder = $this->getQueryBuilder();
755
        $allRecords = $queryBuilder
756 1
            ->select('*')
757 1
            ->from($this->table)
758 1
            ->execute()
759 1
            ->fetchAllAssociative();
760 1
        return $this->getIndexQueueItemObjectsFromRecords($allRecords);
761
    }
762
763
    /**
764
     * Gets $limit number of items to index for a particular $site.
765
     *
766
     * @param Site $site TYPO3 site
767
     * @param int $limit Number of items to get from the queue
768
     * @return Item[] Items to index to the given solr server
769
     *
770
     * @throws ConnectionException
771
     * @throws DBALDriverException
772
     * @throws Throwable
773
     * @throws \Doctrine\DBAL\DBALException
774
     */
775 3
    public function findItemsToIndex(Site $site, int $limit = 50): array
776
    {
777 3
        $queryBuilder = $this->getQueryBuilder();
778
        // determine which items to index with this run
779
        $indexQueueItemRecords = $queryBuilder
780 3
            ->select('*')
781 3
            ->from($this->table)
782 3
            ->andWhere(
783 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

783
                /** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('root', $site->getRootPageId()),
Loading history...
784 3
                $queryBuilder->expr()->gt('changed', 'indexed'),
785 3
                $queryBuilder->expr()->lte('changed', time()),
786 3
                $queryBuilder->expr()->eq('errors', $queryBuilder->createNamedParameter(''))
787
            )
788 3
            ->orderBy('indexing_priority', 'DESC')
789 3
            ->addOrderBy('changed', 'DESC')
790 3
            ->addOrderBy('uid', 'DESC')
791 3
            ->setMaxResults($limit)
792 3
            ->execute()
793 3
            ->fetchAllAssociative();
794
795 3
        return $this->getIndexQueueItemObjectsFromRecords($indexQueueItemRecords);
796
    }
797
798
    /**
799
     * Retrieves the count of items that match certain filters. Each filter is passed as parts of the where claus combined with AND.
800
     *
801
     * @param array $sites
802
     * @param array $indexQueueConfigurationNames
803
     * @param array $itemTypes
804
     * @param array $itemUids
805
     * @param array $uids
806
     * @param int $start
807
     * @param int $limit
808
     * @return array
809
     *
810
     * @throws ConnectionException
811
     * @throws DBALDriverException
812
     * @throws Throwable
813
     * @throws \Doctrine\DBAL\DBALException
814
     */
815 1
    public function findItems(
816
        array $sites = [],
817
        array $indexQueueConfigurationNames = [],
818
        array $itemTypes = [],
819
        array $itemUids = [],
820
        array $uids = [],
821
        int   $start = 0,
822
        int   $limit = 50
823
    ): array {
824 1
        $rootPageIds = Site::getRootPageIdsFromSites($sites);
825 1
        $indexQueueConfigurationList = implode(",", $indexQueueConfigurationNames);
826 1
        $itemTypeList = implode(",", $itemTypes);
827 1
        $itemUids = array_map("intval", $itemUids);
828 1
        $uids = array_map("intval", $uids);
829 1
        $itemQueryBuilder = $this->getQueryBuilder()->select('*')->from($this->table);
830 1
        $itemQueryBuilder = $this->addItemWhereClauses($itemQueryBuilder, $rootPageIds, $indexQueueConfigurationList, $itemTypeList, $itemUids, $uids);
831 1
        $itemRecords = $itemQueryBuilder->setFirstResult($start)
832 1
            ->setMaxResults($limit)
833 1
            ->execute()
834 1
            ->fetchAllAssociative();
835 1
        return $this->getIndexQueueItemObjectsFromRecords($itemRecords);
836
    }
837
838
    /**
839
     * Creates an array of ApacheSolrForTypo3\Solr\IndexQueue\Item objects from an array of
840
     * index queue records.
841
     *
842
     * @param array $indexQueueItemRecords Array of plain index queue records
843
     * @return array Array of ApacheSolrForTypo3\Solr\IndexQueue\Item objects
844
     *
845
     * @throws ConnectionException
846
     * @throws DBALDriverException
847
     * @throws Throwable
848
     * @throws \Doctrine\DBAL\DBALException
849
     */
850 42
    protected function getIndexQueueItemObjectsFromRecords(array $indexQueueItemRecords): array
851
    {
852 42
        $tableRecords = $this->getAllQueueItemRecordsByUidsGroupedByTable($indexQueueItemRecords);
853 42
        return $this->getQueueItemObjectsByRecords($indexQueueItemRecords, $tableRecords);
854
    }
855
856
    /**
857
     * Returns the records for suitable item type.
858
     *
859
     * @param array $indexQueueItemRecords
860
     * @return array
861
     *
862
     * @throws DBALDriverException
863
     * @throws \Doctrine\DBAL\DBALException
864
     */
865 42
    protected function getAllQueueItemRecordsByUidsGroupedByTable(array $indexQueueItemRecords): array
866
    {
867 42
        $tableUids = [];
868 42
        $tableRecords = [];
869
        // grouping records by table
870 42
        foreach ($indexQueueItemRecords as $indexQueueItemRecord) {
871 40
            $tableUids[$indexQueueItemRecord['item_type']][] = $indexQueueItemRecord['item_uid'];
872
        }
873
874
        // fetching records by table, saves us a lot of single queries
875 42
        foreach ($tableUids as $table => $uids) {
876 40
            $uidList = implode(',', $uids);
877
878 40
            $queryBuilderForRecordTable = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
879 40
            $queryBuilderForRecordTable->getRestrictions()->removeAll();
880
            $resultsFromRecordTable = $queryBuilderForRecordTable
881 40
                ->select('*')
882 40
                ->from($table)
883 40
                ->where(/** @scrutinizer ignore-type */ $queryBuilderForRecordTable->expr()->in('uid', $uidList))
884 40
                ->execute();
885 40
            $records = [];
886 40
            while ($record = $resultsFromRecordTable->fetchAssociative()) {
887 39
                $records[$record['uid']] = $record;
888
            }
889
890 40
            $tableRecords[$table] = $records;
891 40
            $this->hookPostProcessFetchRecordsForIndexQueueItem($table, $uids, $tableRecords);
892
        }
893
894 42
        return $tableRecords;
895
    }
896
897
    /**
898
     * Calls defined in postProcessFetchRecordsForIndexQueueItem hook method.
899
     *
900
     * @param string $table
901
     * @param array $uids
902
     * @param array $tableRecords
903
     *
904
     * @return void
905
     */
906 40
    protected function hookPostProcessFetchRecordsForIndexQueueItem(string $table, array $uids, array &$tableRecords)
907
    {
908 40
        if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessFetchRecordsForIndexQueueItem'])) {
909 40
            return;
910
        }
911
        $params = ['table' => $table, 'uids' => $uids, 'tableRecords' => &$tableRecords];
912
        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessFetchRecordsForIndexQueueItem'] as $reference) {
913
            GeneralUtility::callUserFunction($reference, $params, $this);
914
        }
915
    }
916
917
    /**
918
     * Instantiates a list of Item objects from database records.
919
     *
920
     * @param array $indexQueueItemRecords records from database
921
     * @param array $tableRecords
922
     * @return array
923
     *
924
     * @throws ConnectionException
925
     * @throws Throwable
926
     * @throws \Doctrine\DBAL\DBALException
927
     */
928 42
    protected function getQueueItemObjectsByRecords(array $indexQueueItemRecords, array $tableRecords): array
929
    {
930 42
        $indexQueueItems = [];
931 42
        foreach ($indexQueueItemRecords as $indexQueueItemRecord) {
932 40
            if (isset($tableRecords[$indexQueueItemRecord['item_type']][$indexQueueItemRecord['item_uid']])) {
933 39
                $indexQueueItems[] = GeneralUtility::makeInstance(
934 39
                    Item::class,
935
                    /** @scrutinizer ignore-type */
936 39
                    $indexQueueItemRecord,
937
                    /** @scrutinizer ignore-type */
938 39
                    $tableRecords[$indexQueueItemRecord['item_type']][$indexQueueItemRecord['item_uid']]
939
                );
940
            } else {
941 1
                $this->logger->log(
942 1
                    SolrLogManager::ERROR,
943 1
                    'Record missing for Index Queue item. Item removed.',
944
                    [
945 1
                        $indexQueueItemRecord
946
                    ]
947
                );
948 1
                $this->deleteItem(
949 1
                    $indexQueueItemRecord['item_type'],
950 1
                    $indexQueueItemRecord['item_uid']
951
                );
952
            }
953
        }
954
955 42
        return $indexQueueItems;
956
    }
957
958
    /**
959
     * Marks an item as failed and causes the indexer to skip the item in the
960
     * next run.
961
     *
962
     * @param int|Item $item Either the item's Index Queue uid or the complete item
963
     * @param string $errorMessage Error message
964
     * @return int affected rows
965
     *
966
     * @throws \Doctrine\DBAL\DBALException
967
     */
968 6
    public function markItemAsFailed($item, string $errorMessage = ''): int
969
    {
970 6
        $itemUid = ($item instanceof Item) ? $item->getIndexQueueUid() : (int)$item;
971 6
        $errorMessage = empty($errorMessage) ? '1' : $errorMessage;
972
973 6
        $queryBuilder = $this->getQueryBuilder();
974
        return (int)$queryBuilder
975 6
            ->update($this->table)
976 6
            ->set('errors', $errorMessage)
977 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

977
            ->where(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('uid', $itemUid))
Loading history...
978 6
            ->execute();
979
    }
980
981
    /**
982
     * Sets the timestamp of when an item last has been indexed.
983
     *
984
     * @param Item $item
985
     * @return int affected rows
986
     *
987
     * @throws \Doctrine\DBAL\DBALException
988
     */
989 2
    public function updateIndexTimeByItem(Item $item): int
990
    {
991 2
        $queryBuilder = $this->getQueryBuilder();
992
        return (int)$queryBuilder
993 2
            ->update($this->table)
994 2
            ->set('indexed', time())
995 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

995
            ->where(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('uid', $item->getIndexQueueUid()))
Loading history...
996 2
            ->execute();
997
    }
998
999
    /**
1000
     * Sets the change timestamp of an item.
1001
     *
1002
     * @param Item $item
1003
     * @param int $changedTime
1004
     * @return int affected rows
1005
     *
1006
     * @throws \Doctrine\DBAL\DBALException
1007
     */
1008
    public function updateChangedTimeByItem(Item $item, int $changedTime): int
1009
    {
1010
        $queryBuilder = $this->getQueryBuilder();
1011
        return (int)$queryBuilder
1012
            ->update($this->table)
1013
            ->set('changed', $changedTime)
1014
            ->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

1014
            ->where(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('uid', $item->getIndexQueueUid()))
Loading history...
1015
            ->execute();
1016
    }
1017
1018
    /**
1019
     * Initializes Queue by given sql
1020
     *
1021
     * Note: Do not use platform specific functions!
1022
     *
1023
     * @param string $sqlStatement Native SQL statement
1024
     * @return int The number of affected rows.
1025
     *
1026
     * @throws DBALException
1027
     * @internal
1028
     */
1029 13
    public function initializeByNativeSQLStatement(string $sqlStatement): int
1030
    {
1031 13
        return $this->getQueryBuilder()
1032 13
            ->getConnection()
1033 13
            ->executeStatement($sqlStatement);
1034
    }
1035
1036
    /**
1037
     * Retrieves an array of pageIds from mountPoints that already have a queue entry.
1038
     *
1039
     * @param string $identifier identifier of the mount point
1040
     * @return array pageIds from mountPoints that already have a queue entry
1041
     *
1042
     * @throws DBALDriverException
1043
     * @throws \Doctrine\DBAL\DBALException
1044
     */
1045 7
    public function findPageIdsOfExistingMountPagesByMountIdentifier(string $identifier): array
1046
    {
1047 7
        $queryBuilder = $this->getQueryBuilder();
1048
        $resultSet = $queryBuilder
1049 7
            ->select('item_uid')
1050 7
            ->add('select', $queryBuilder->expr()->count('*', 'queueItemCount'), true)
1051 7
            ->from($this->table)
1052 7
            ->where(
1053 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

1053
                /** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('item_type', $queryBuilder->createNamedParameter('pages')),
Loading history...
1054 7
                $queryBuilder->expr()->eq('pages_mountidentifier', $queryBuilder->createNamedParameter($identifier))
1055
            )
1056 7
            ->groupBy('item_uid')
1057 7
            ->execute();
1058
1059 7
        $mountedPagesIdsWithQueueItems = [];
1060 7
        while ($record = $resultSet->fetchAssociative()) {
1061
            if ($record['queueItemCount'] > 0) {
1062
                $mountedPagesIdsWithQueueItems[] = $record['item_uid'];
1063
            }
1064
        }
1065
1066 7
        return $mountedPagesIdsWithQueueItems;
1067
    }
1068
1069
    /**
1070
     * Retrieves an array of items for mount destinations matched by root page ID, Mount Identifier and a list of mounted page IDs.
1071
     *
1072
     * @param int $rootPid
1073
     * @param string $identifier identifier of the mount point
1074
     * @param array $mountedPids An array of mounted page IDs
1075
     * @return array
1076
     *
1077
     * @throws DBALDriverException
1078
     * @throws \Doctrine\DBAL\DBALException
1079
     */
1080 7
    public function findAllIndexQueueItemsByRootPidAndMountIdentifierAndMountedPids(
1081
        int $rootPid,
1082
        string $identifier,
1083
        array $mountedPids
1084
    ): array {
1085 7
        $queryBuilder = $this->getQueryBuilder();
1086
        return $queryBuilder
1087 7
            ->select('*')
1088 7
            ->from($this->table)
1089 7
            ->where(
1090 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

1090
                /** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('root', $queryBuilder->createNamedParameter($rootPid, PDO::PARAM_INT)),
Loading history...
1091 7
                $queryBuilder->expr()->eq('item_type', $queryBuilder->createNamedParameter('pages')),
1092 7
                $queryBuilder->expr()->in('item_uid', $mountedPids),
1093 7
                $queryBuilder->expr()->eq('has_indexing_properties', $queryBuilder->createNamedParameter(1, PDO::PARAM_INT)),
1094 7
                $queryBuilder->expr()->eq('pages_mountidentifier', $queryBuilder->createNamedParameter($identifier))
1095
            )
1096 7
            ->execute()
1097 7
            ->fetchAllAssociative();
1098
    }
1099
1100
    /**
1101
     * Updates has_indexing_properties field for given Item
1102
     *
1103
     * @param int $itemUid
1104
     * @param bool $hasIndexingPropertiesFlag
1105
     * @return int number of affected rows, 1 on success
1106
     *
1107
     * @throws \Doctrine\DBAL\DBALException
1108
     */
1109 9
    public function updateHasIndexingPropertiesFlagByItemUid(int $itemUid, bool $hasIndexingPropertiesFlag): int
1110
    {
1111 9
        $queryBuilder = $this->getQueryBuilder();
1112
        return (int)$queryBuilder
1113 9
            ->update($this->table)
1114 9
            ->where(
1115
                /** @scrutinizer ignore-type */
1116 9
                $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($itemUid, PDO::PARAM_INT))
1117
            )
1118 9
            ->set(
1119 9
                'has_indexing_properties',
1120 9
                $queryBuilder->createNamedParameter($hasIndexingPropertiesFlag, PDO::PARAM_INT),
1121 9
                false
1122 9
            )->execute();
1123
    }
1124
}
1125