Skip to content

Commit

Permalink
[BUGFIX] Fix monitoring of mounted pages
Browse files Browse the repository at this point in the history
EXT:solr fails to detect changes on mounted pages correctly in
some special occasions:

* mounted pages not considered during garbage removal / ce updates
* no_search_sub_entries flag not respected by GarbageRemover
  strategies
* existing queue items of mounted pages not updated

By adjusting the monitoring related components the issues are fixed,
affected components:

* GarbageRemover strategies
* page initializer
* RecordMonitor
* DataUpdateHandler

Fixes: TYPO3-Solr#4275
  • Loading branch information
dkd-friedrich committed Jan 7, 2025
1 parent fe71a4f commit b43c563
Show file tree
Hide file tree
Showing 11 changed files with 470 additions and 28 deletions.
14 changes: 13 additions & 1 deletion Classes/Domain/Index/Queue/GarbageRemover/AbstractStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
use ApacheSolrForTypo3\Solr\IndexQueue\Queue;
use ApacheSolrForTypo3\Solr\IndexQueue\QueueInterface;
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
use ApacheSolrForTypo3\Solr\Traits\SkipRecordByRootlineConfigurationTrait;
use Doctrine\DBAL\Exception as DBALException;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use UnexpectedValueException;

Expand All @@ -33,6 +35,8 @@
*/
abstract class AbstractStrategy
{
use SkipRecordByRootlineConfigurationTrait;

protected QueueInterface $queue;
protected ConnectionManager $connectionManager;
protected SiteRepository $siteRepository;
Expand Down Expand Up @@ -82,7 +86,15 @@ protected function deleteInSolrAndRemoveFromIndexQueue(string $table, int $uid):
protected function deleteInSolrAndUpdateIndexQueue(string $table, int $uid): void
{
$this->deleteIndexDocuments($table, $uid);
$this->queue->updateItem($table, $uid);

$record = BackendUtility::getRecord($table, $uid);
if ($record === null) {
return;
}

if (!$this->skipRecordByRootlineConfiguration((int)($record['pid'] ?? 0))) {
$this->queue->updateItem($table, $uid);
}
}

/**
Expand Down
19 changes: 19 additions & 0 deletions Classes/Domain/Index/Queue/GarbageRemover/PageStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@

namespace ApacheSolrForTypo3\Solr\Domain\Index\Queue\GarbageRemover;

use ApacheSolrForTypo3\Solr\Domain\Index\Queue\RecordMonitor\Helper\MountPagesUpdater;
use ApacheSolrForTypo3\Solr\Domain\Site\Exception\UnexpectedTYPO3SiteInitializationException;
use Doctrine\DBAL\Exception as DBALException;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
* Class PageStrategy
Expand All @@ -42,6 +44,23 @@ protected function removeGarbageOfByStrategy(string $table, int $uid): void
}
}

/**
* Deletes a page from Solr and updates the item in the index queue
* The MountPagesUpdater takes care of mounted pages
*
* @throws DBALException
* @throws UnexpectedTYPO3SiteInitializationException
*/
protected function deleteInSolrAndUpdateIndexQueue(string $table, int $uid): void
{
parent::deleteInSolrAndUpdateIndexQueue($table, $uid);

if ($table === 'pages') {
$mountPagesUpdater = GeneralUtility::makeInstance(MountPagesUpdater::class);
$mountPagesUpdater->update($uid);
}
}

/**
* Determines the relevant page id for a content element update. Deletes the page from solr and requeues the
* page for a reindex.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
use ApacheSolrForTypo3\Solr\System\Records\Pages\PagesRepository;
use ApacheSolrForTypo3\Solr\System\TCA\TCAService;
use ApacheSolrForTypo3\Solr\Traits\SkipRecordByRootlineConfigurationTrait;
use ApacheSolrForTypo3\Solr\Util;
use Doctrine\DBAL\Exception as DBALException;
use Throwable;
Expand All @@ -46,6 +47,8 @@
*/
class DataUpdateHandler extends AbstractUpdateHandler
{
use SkipRecordByRootlineConfigurationTrait;

/**
* List of fields in the update field array that
* are required for processing
Expand Down Expand Up @@ -388,7 +391,9 @@ protected function processPageRecord(int $uid, int $pid, array $updatedFields =
}
$rootPageIds = [$configurationPageId];

$this->processRecord('pages', $uid, $rootPageIds);
if (!$this->skipRecordByRootlineConfiguration($uid)) {
$this->processRecord('pages', $uid, $rootPageIds);
}

$this->updateCanonicalPages($uid);
$this->mountPageUpdater->update($uid);
Expand Down
17 changes: 16 additions & 1 deletion Classes/IndexQueue/Initializer/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use PDO;
use Throwable;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Messaging\FlashMessage;
Expand Down Expand Up @@ -224,8 +225,22 @@ protected function addMountedPagesToIndexQueue(array $mountedPages, array $mount
{
$mountPointIdentifier = $this->getMountPointIdentifier($mountProperties);
$mountPointPageIsWithExistingQueueEntry = $this->queueItemRepository->findPageIdsOfExistingMountPagesByMountIdentifier($mountPointIdentifier);
$mountedPagesThatNeedToBeAdded = array_diff($mountedPages, $mountPointPageIsWithExistingQueueEntry);

// update existing queue entries to trigger reindexing
array_walk(
$mountPointPageIsWithExistingQueueEntry,
function (int $pageUid): void {
$tstamp = GeneralUtility::makeInstance(Context::class)
->getPropertyFromAspect('date', 'timestamp') ?? time();
$items = $this->queueItemRepository->findItemsByItemTypeAndItemUid('pages', $pageUid);
foreach ($items as $item) {
$this->queueItemRepository->updateChangedTimeByItem($item, $tstamp);
}
}
);

// add new items if necessary
$mountedPagesThatNeedToBeAdded = array_diff($mountedPages, $mountPointPageIsWithExistingQueueEntry);
if (count($mountedPagesThatNeedToBeAdded) === 0) {
//nothing to do
return;
Expand Down
30 changes: 7 additions & 23 deletions Classes/IndexQueue/RecordMonitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@
use ApacheSolrForTypo3\Solr\Domain\Index\Queue\UpdateHandler\Events\RecordUpdatedEvent;
use ApacheSolrForTypo3\Solr\Domain\Index\Queue\UpdateHandler\Events\VersionSwappedEvent;
use ApacheSolrForTypo3\Solr\Traits\SkipMonitoringTrait;
use ApacheSolrForTypo3\Solr\Traits\SkipRecordByRootlineConfigurationTrait;
use ApacheSolrForTypo3\Solr\Util;
use Psr\EventDispatcher\EventDispatcherInterface;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\Exception\Page\PageNotFoundException;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Core\Utility\RootlineUtility;

/**
* A class that monitors changes to the records so that the changed record get
Expand All @@ -38,6 +37,7 @@
class RecordMonitor
{
use SkipMonitoringTrait;
use SkipRecordByRootlineConfigurationTrait;

protected array $trackedRecords = [];
protected EventDispatcherInterface $eventDispatcher;
Expand Down Expand Up @@ -144,7 +144,11 @@ public function processDatamap_afterDatabaseOperations(
$recordPid = $recordInfo['pid'] ?? null;
}
}
if (!is_null($recordPid) && $this->skipRecordByRootlineConfiguration((int)$recordPid)) {
if (
!is_null($recordPid)
&& !GeneralUtility::inList('pages,tt_content', $table)
&& $this->skipRecordByRootlineConfiguration((int)$recordPid)
) {
return;
}

Expand All @@ -164,24 +168,4 @@ public function processDatamap_afterDatabaseOperations(
new RecordUpdatedEvent((int)$recordUid, $table, $fields)
);
}

/**
* Check if at least one page in the record's rootline is configured to exclude sub-entries from indexing
*/
protected function skipRecordByRootlineConfiguration(int $pid): bool
{
/** @var RootlineUtility $rootlineUtility */
$rootlineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $pid);
try {
$rootline = $rootlineUtility->get();
} catch (PageNotFoundException) {
return true;
}
foreach ($rootline as $page) {
if (isset($page['no_search_sub_entries']) && $page['no_search_sub_entries']) {
return true;
}
}
return false;
}
}
45 changes: 45 additions & 0 deletions Classes/Traits/SkipRecordByRootlineConfigurationTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

namespace ApacheSolrForTypo3\Solr\Traits;

use TYPO3\CMS\Core\Exception\Page\PageNotFoundException;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\RootlineUtility;

trait SkipRecordByRootlineConfigurationTrait
{
/**
* Check if at least one page in the record's rootline is configured to exclude sub-entries from indexing
*/
protected function skipRecordByRootlineConfiguration(int $pid): bool
{
/** @var RootlineUtility $rootlineUtility */
$rootlineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $pid);
try {
$rootline = $rootlineUtility->get();
} catch (PageNotFoundException) {
return true;
}
foreach ($rootline as $page) {
if (isset($page['no_search_sub_entries']) && $page['no_search_sub_entries']) {
return true;
}
}
return false;
}
}
25 changes: 25 additions & 0 deletions Tests/Integration/IndexQueue/Fixtures/mount_page_updates.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"pages",
,"uid","pid","tstamp","hidden","doktype","mount_pid","mount_pid_ol","slug","title","no_search_sub_entries"
,2,1,1736145036,0,254,0,0,"/sysfolder","Sys folder (no_search_sub_entries)",1
,20,2,1736145036,0,1,0,0,"/mounted-page-in-sysfolder","Mounted page in sysfolder",0
,21,1,1736145036,0,1,0,0,"/mounted-page-on-root","Mounted page on root page",0
,22,2,1736145036,0,1,0,0,"/another-mounted-page-in-sysfolder","Another mounted page in sysfolder",0
,30,1,1736145036,0,7,20,1,"/mount-point-1","Mount point for page in sysfolder",0
,31,1,1736145036,0,7,21,1,"/mount-point-2","Mount point for page on root page",0
,32,1,1736145036,0,7,22,1,"/mount-point-3","Mount point for another page in sysfolder",0
"tt_content",
,"uid","pid","header","hidden"
,20,20,"ce on mounted page",0
,21,20,"hidden ce on mounted page",1
,22,21,"ce on mounted page",0
,23,21,"hidden ce on mounted page",1
,24,22,"ce on another mounted page",0
,25,22,"hidden ce on another mounted page",1
"tx_solr_indexqueue_item"
,"uid","root","item_type","item_uid","indexing_configuration","has_indexing_properties","pages_mountidentifier","errors"
,1,1,"pages",22,"pages",1,"22-32-1",""
"tx_solr_indexqueue_indexing_property"
,"uid","root","item_id","property_key","property_value"
,1,1,1,"mountPageSource",22
,2,1,1,"mountPageDestination",32
,3,1,1,"isMountedPage",1
Loading

0 comments on commit b43c563

Please sign in to comment.