602 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			602 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace WapplerSystems\Meilisearch\IndexQueue;
 | 
						|
 | 
						|
/***************************************************************
 | 
						|
 *  Copyright notice
 | 
						|
 *
 | 
						|
 *  (c) 2009-2015 Ingo Renner <ingo@typo3.org>
 | 
						|
 *  All rights reserved
 | 
						|
 *
 | 
						|
 *  This script is part of the TYPO3 project. The TYPO3 project is
 | 
						|
 *  free software; you can redistribute it and/or modify
 | 
						|
 *  it under the terms of the GNU General Public License as published by
 | 
						|
 *  the Free Software Foundation; either version 3 of the License, or
 | 
						|
 *  (at your option) any later version.
 | 
						|
 *
 | 
						|
 *  The GNU General Public License can be found at
 | 
						|
 *  http://www.gnu.org/copyleft/gpl.html.
 | 
						|
 *
 | 
						|
 *  This script is distributed in the hope that it will be useful,
 | 
						|
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 *  GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 *  This copyright notice MUST APPEAR in all copies of the script!
 | 
						|
 ***************************************************************/
 | 
						|
 | 
						|
use WapplerSystems\Meilisearch\AbstractDataHandlerListener;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Index\Queue\RecordMonitor\Helper\ConfigurationAwareRecordService;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Index\Queue\RecordMonitor\Helper\MountPagesUpdater;
 | 
						|
use WapplerSystems\Meilisearch\Domain\Index\Queue\RecordMonitor\Helper\RootPageResolver;
 | 
						|
use WapplerSystems\Meilisearch\FrontendEnvironment;
 | 
						|
use WapplerSystems\Meilisearch\GarbageCollector;
 | 
						|
use WapplerSystems\Meilisearch\System\Configuration\ExtensionConfiguration;
 | 
						|
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
 | 
						|
use WapplerSystems\Meilisearch\System\Logging\MeilisearchLogManager;
 | 
						|
use WapplerSystems\Meilisearch\System\Records\Pages\PagesRepository;
 | 
						|
use WapplerSystems\Meilisearch\System\TCA\TCAService;
 | 
						|
use WapplerSystems\Meilisearch\Util;
 | 
						|
use TYPO3\CMS\Backend\Utility\BackendUtility;
 | 
						|
use TYPO3\CMS\Core\DataHandling\DataHandler;
 | 
						|
use TYPO3\CMS\Core\Utility\GeneralUtility;
 | 
						|
use TYPO3\CMS\Core\Utility\MathUtility;
 | 
						|
 | 
						|
/**
 | 
						|
 * A class that monitors changes to records so that the changed record gets
 | 
						|
 * passed to the index queue to update the according index document.
 | 
						|
 *
 | 
						|
 * @author Ingo Renner <ingo@typo3.org>
 | 
						|
 */
 | 
						|
class RecordMonitor extends AbstractDataHandlerListener
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * Index Queue
 | 
						|
     *
 | 
						|
     * @var Queue
 | 
						|
     */
 | 
						|
    protected $indexQueue;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Mount Page Updater
 | 
						|
     *
 | 
						|
     * @var MountPagesUpdater
 | 
						|
     */
 | 
						|
    protected $mountPageUpdater;
 | 
						|
 | 
						|
    /**
 | 
						|
     * TCA Service
 | 
						|
     *
 | 
						|
     * @var TCAService
 | 
						|
     */
 | 
						|
    protected $tcaService;
 | 
						|
 | 
						|
    /**
 | 
						|
     * RootPageResolver
 | 
						|
     *
 | 
						|
     * @var RootPageResolver
 | 
						|
     */
 | 
						|
    protected $rootPageResolver;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var PagesRepository
 | 
						|
     */
 | 
						|
    protected $pagesRepository;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var MeilisearchLogManager
 | 
						|
     */
 | 
						|
    protected $logger = null;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var FrontendEnvironment
 | 
						|
     */
 | 
						|
    protected $frontendEnvironment = null;
 | 
						|
 | 
						|
    /**
 | 
						|
     * RecordMonitor constructor.
 | 
						|
     *
 | 
						|
     * @param Queue|null $indexQueue
 | 
						|
     * @param MountPagesUpdater|null $mountPageUpdater
 | 
						|
     * @param TCAService|null $TCAService
 | 
						|
     * @param RootPageResolver $rootPageResolver
 | 
						|
     * @param PagesRepository|null $pagesRepository
 | 
						|
     * @param MeilisearchLogManager|null $meilisearchLogManager
 | 
						|
     * @param ConfigurationAwareRecordService|null $recordService
 | 
						|
     */
 | 
						|
    public function __construct(
 | 
						|
        Queue $indexQueue = null,
 | 
						|
        MountPagesUpdater $mountPageUpdater = null,
 | 
						|
        TCAService $TCAService = null,
 | 
						|
        RootPageResolver $rootPageResolver = null,
 | 
						|
        PagesRepository $pagesRepository = null,
 | 
						|
        MeilisearchLogManager $meilisearchLogManager = null,
 | 
						|
        ConfigurationAwareRecordService $recordService = null,
 | 
						|
        FrontendEnvironment $frontendEnvironment = null
 | 
						|
    )
 | 
						|
    {
 | 
						|
        parent::__construct($recordService);
 | 
						|
        $this->indexQueue = $indexQueue ?? GeneralUtility::makeInstance(Queue::class);
 | 
						|
        $this->mountPageUpdater = $mountPageUpdater ?? GeneralUtility::makeInstance(MountPagesUpdater::class);
 | 
						|
        $this->tcaService = $TCAService ?? GeneralUtility::makeInstance(TCAService::class);
 | 
						|
        $this->rootPageResolver = $rootPageResolver ?? GeneralUtility::makeInstance(RootPageResolver::class);
 | 
						|
        $this->pagesRepository = $pagesRepository ?? GeneralUtility::makeInstance(PagesRepository::class);
 | 
						|
        $this->logger = $meilisearchLogManager ?? GeneralUtility::makeInstance(MeilisearchLogManager::class, /** @scrutinizer ignore-type */ __CLASS__);
 | 
						|
        $this->frontendEnvironment = $frontendEnvironment ?? GeneralUtility::makeInstance(FrontendEnvironment::class);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param MeilisearchLogManager $logger
 | 
						|
     */
 | 
						|
    public function setLogger(MeilisearchLogManager $logger)
 | 
						|
    {
 | 
						|
        $this->logger = $logger;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Holds the configuration when a recursive page queing should be triggered.
 | 
						|
     *
 | 
						|
     * Note: The SQL transaction is already committed, so the current state covers only "non"-changed fields.
 | 
						|
     *
 | 
						|
     * @var array
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    protected function getUpdateSubPagesRecursiveTriggerConfiguration()
 | 
						|
    {
 | 
						|
        return [
 | 
						|
            // the current page has the both fields "extendToSubpages" and "hidden" set from 1 to 0 => requeue subpages
 | 
						|
            'HiddenAndExtendToSubpageWereDisabled' => [
 | 
						|
                'changeSet' => [
 | 
						|
                    'hidden' => '0',
 | 
						|
                    'extendToSubpages' => '0'
 | 
						|
                ]
 | 
						|
            ],
 | 
						|
            // the current page has the field "extendToSubpages" enabled and the field "hidden" was set to 0 => requeue subpages
 | 
						|
            'extendToSubpageEnabledAndHiddenFlagWasRemoved' => [
 | 
						|
                'currentState' =>  ['extendToSubpages' => '1'],
 | 
						|
                'changeSet' => ['hidden' => '0']
 | 
						|
            ],
 | 
						|
            // the current page has the field "hidden" enabled and the field "extendToSubpages" was set to 0 => requeue subpages
 | 
						|
            'hiddenIsEnabledAndExtendToSubPagesWasRemoved' => [
 | 
						|
                'currentState' =>  ['hidden' => '1'],
 | 
						|
                'changeSet' => ['extendToSubpages' => '0']
 | 
						|
            ]
 | 
						|
        ];
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Hooks into TCE main and tracks record deletion commands.
 | 
						|
     *
 | 
						|
     * @param string $command The command.
 | 
						|
     * @param string $table The table the record belongs to
 | 
						|
     * @param int $uid The record's uid
 | 
						|
     * @param string $value
 | 
						|
     * @param DataHandler $tceMain TYPO3 Core Engine parent object
 | 
						|
     */
 | 
						|
    public function processCmdmap_preProcess(
 | 
						|
        $command,
 | 
						|
        $table,
 | 
						|
        $uid,
 | 
						|
        /** @noinspection PhpUnusedParameterInspection */
 | 
						|
        $value,
 | 
						|
        DataHandler $tceMain
 | 
						|
    ) {
 | 
						|
        if ($command === 'delete' && $table === 'tt_content' && $GLOBALS['BE_USER']->workspace == 0) {
 | 
						|
            // skip workspaces: index only LIVE workspace
 | 
						|
            $pid = $this->getValidatedPid($tceMain, $table, $uid);
 | 
						|
            $this->indexQueue->updateItem('pages', $pid, time());
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Hooks into TCE main and tracks workspace publish/swap events and
 | 
						|
     * page move commands in LIVE workspace.
 | 
						|
     *
 | 
						|
     * @param string $command The command.
 | 
						|
     * @param string $table The table the record belongs to
 | 
						|
     * @param int $uid The record's uid
 | 
						|
     * @param string $value
 | 
						|
     * @param DataHandler $tceMain TYPO3 Core Engine parent object
 | 
						|
     */
 | 
						|
    public function processCmdmap_postProcess($command, $table, $uid, $value, DataHandler $tceMain)
 | 
						|
    {
 | 
						|
        if ($this->isDraftRecord($table, $uid)) {
 | 
						|
            // skip workspaces: index only LIVE workspace
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        // track publish / swap events for records (workspace support)
 | 
						|
        // command "version"
 | 
						|
        if ($command === 'version' && $value['action'] === 'swap') {
 | 
						|
            $this->applyVersionSwap($table, $uid, $tceMain);
 | 
						|
        }
 | 
						|
 | 
						|
        // moving pages/records in LIVE workspace
 | 
						|
        if ($command === 'move' && $GLOBALS['BE_USER']->workspace == 0) {
 | 
						|
            if ($table === 'pages') {
 | 
						|
                $this->applyPageChangesToQueue($uid);
 | 
						|
            } else {
 | 
						|
                $this->applyRecordChangesToQueue($table, $uid, $value);
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Apply's version swap to the IndexQueue.
 | 
						|
     *
 | 
						|
     * @param string $table
 | 
						|
     * @param integer $uid
 | 
						|
     * @param DataHandler $tceMain
 | 
						|
     */
 | 
						|
    protected function applyVersionSwap($table, $uid, DataHandler $tceMain)
 | 
						|
    {
 | 
						|
        $isPageRelatedRecord = $table === 'tt_content' || $table === 'pages';
 | 
						|
        if($isPageRelatedRecord) {
 | 
						|
            $uid = $table === 'tt_content' ? $this->getValidatedPid($tceMain, $table, $uid) : $uid;
 | 
						|
            $this->applyPageChangesToQueue($uid);
 | 
						|
        } else {
 | 
						|
            $recordPageId = $this->getValidatedPid($tceMain, $table, $uid);
 | 
						|
            $this->applyRecordChangesToQueue($table, $uid, $recordPageId);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Add's a page to the queue and updates mounts, when it is enabled, otherwise ensure that the page is removed
 | 
						|
     * from the queue.
 | 
						|
     *
 | 
						|
     * @param integer $uid
 | 
						|
     */
 | 
						|
    protected function applyPageChangesToQueue($uid)
 | 
						|
    {
 | 
						|
        $meilisearchConfiguration = $this->getMeilisearchConfigurationFromPageId($uid);
 | 
						|
        $record = $this->configurationAwareRecordService->getRecord('pages', $uid, $meilisearchConfiguration);
 | 
						|
        if (!empty($record) && $this->tcaService->isEnabledRecord('pages', $record)) {
 | 
						|
            $this->mountPageUpdater->update($uid);
 | 
						|
            $this->indexQueue->updateItem('pages', $uid);
 | 
						|
        } else {
 | 
						|
            // TODO should be moved to garbage collector
 | 
						|
            $this->removeFromIndexAndQueueWhenItemInQueue('pages', $uid);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Add's a record to the queue if it is monitored and enabled, otherwise it removes the record from the queue.
 | 
						|
     *
 | 
						|
     * @param string $table
 | 
						|
     * @param integer $uid
 | 
						|
     * @param integer $pid
 | 
						|
     */
 | 
						|
    protected function applyRecordChangesToQueue($table, $uid, $pid)
 | 
						|
    {
 | 
						|
        $meilisearchConfiguration = $this->getMeilisearchConfigurationFromPageId($pid);
 | 
						|
        $isMonitoredTable = $meilisearchConfiguration->getIndexQueueIsMonitoredTable($table);
 | 
						|
 | 
						|
        if ($isMonitoredTable) {
 | 
						|
            $record = $this->configurationAwareRecordService->getRecord($table, $uid, $meilisearchConfiguration);
 | 
						|
 | 
						|
            if (!empty($record) && $this->tcaService->isEnabledRecord($table, $record)) {
 | 
						|
                $uid = $this->tcaService->getTranslationOriginalUidIfTranslated($table, $record, $uid);
 | 
						|
                $this->indexQueue->updateItem($table, $uid);
 | 
						|
            } else {
 | 
						|
                // TODO should be moved to garbage collector
 | 
						|
                $this->removeFromIndexAndQueueWhenItemInQueue($table, $uid);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Hooks into TCE Main and watches all record creations and updates. If it
 | 
						|
     * detects that the new/updated record belongs to a table configured for
 | 
						|
     * indexing through Meilisearch, we add the record to the index queue.
 | 
						|
     *
 | 
						|
     * @param string $status Status of the current operation, 'new' or 'update'
 | 
						|
     * @param string $table The table the record belongs to
 | 
						|
     * @param mixed $uid The record's uid, [integer] or [string] (like 'NEW...')
 | 
						|
     * @param array $fields The record's data
 | 
						|
     * @param DataHandler $tceMain TYPO3 Core Engine parent object
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function processDatamap_afterDatabaseOperations($status, $table, $uid, array $fields, DataHandler $tceMain) {
 | 
						|
        $recordTable = $table;
 | 
						|
        $recordUid = $uid;
 | 
						|
 | 
						|
        if ($this->skipMonitoringOfTable($table)) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        if ($status === 'new' && !MathUtility::canBeInterpretedAsInteger($recordUid)) {
 | 
						|
            $recordUid = $tceMain->substNEWwithIDs[$recordUid];
 | 
						|
        }
 | 
						|
        if ($this->isDraftRecord($table, $recordUid)) {
 | 
						|
            // skip workspaces: index only LIVE workspace
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        try {
 | 
						|
            $recordPageId = $this->getRecordPageId($status, $recordTable, $recordUid, $uid, $fields, $tceMain);
 | 
						|
 | 
						|
            // when a content element changes we need to updated the page instead
 | 
						|
            if ($recordTable === 'tt_content') {
 | 
						|
                $recordTable = 'pages';
 | 
						|
                $recordUid = $recordPageId;
 | 
						|
            }
 | 
						|
 | 
						|
            $this->processRecord($recordTable, $recordPageId, $recordUid, $fields);
 | 
						|
        } catch (NoPidException $e) {
 | 
						|
            $message = 'Record without valid pid was processed ' . $table . ':' . $uid;
 | 
						|
            $this->logger->log(MeilisearchLogManager::WARNING, $message);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Check if the provided table is explicitly configured for monitoring
 | 
						|
     *
 | 
						|
     * @param string $table
 | 
						|
     * @return bool
 | 
						|
     */
 | 
						|
    protected function skipMonitoringOfTable($table)
 | 
						|
    {
 | 
						|
        static $configurationMonitorTables;
 | 
						|
 | 
						|
        if (empty($configurationMonitorTables)) {
 | 
						|
            $configuration = GeneralUtility::makeInstance(ExtensionConfiguration::class);
 | 
						|
            $configurationMonitorTables = $configuration->getIsUseConfigurationMonitorTables();
 | 
						|
        }
 | 
						|
 | 
						|
        // No explicit configuration => all tables should be monitored
 | 
						|
        if (empty($configurationMonitorTables)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        return !in_array($table, $configurationMonitorTables);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Process the record located in processDatamap_afterDatabaseOperations
 | 
						|
     *
 | 
						|
     * @param string $recordTable The table the record belongs to
 | 
						|
     * @param int $recordPageId pageid
 | 
						|
     * @param mixed $recordUid The record's uid, [integer] or [string] (like 'NEW...')
 | 
						|
     * @param array $fields The record's data
 | 
						|
     */
 | 
						|
    protected function processRecord($recordTable, $recordPageId, $recordUid, $fields)
 | 
						|
    {
 | 
						|
        if ($recordTable === 'pages') {
 | 
						|
            $configurationPageId = $this->getConfigurationPageId($recordTable, $recordPageId, $recordUid);
 | 
						|
            if ($configurationPageId === 0) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            $rootPageIds = [$configurationPageId];
 | 
						|
        } else {
 | 
						|
            try {
 | 
						|
                $rootPageIds = $this->rootPageResolver->getResponsibleRootPageIds($recordTable, $recordUid);
 | 
						|
                if (empty($rootPageIds)) {
 | 
						|
                    $this->removeFromIndexAndQueueWhenItemInQueue($recordTable, $recordUid);
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            } catch ( \InvalidArgumentException $e) {
 | 
						|
                $this->removeFromIndexAndQueueWhenItemInQueue($recordTable, $recordUid);
 | 
						|
                return;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        foreach ($rootPageIds as $configurationPageId) {
 | 
						|
            $meilisearchConfiguration = $this->getMeilisearchConfigurationFromPageId($configurationPageId);
 | 
						|
            $isMonitoredRecord = $meilisearchConfiguration->getIndexQueueIsMonitoredTable($recordTable);
 | 
						|
            if (!$isMonitoredRecord) {
 | 
						|
                // when it is a non monitored record, we can skip it.
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
 | 
						|
            $record = $this->configurationAwareRecordService->getRecord($recordTable, $recordUid, $meilisearchConfiguration);
 | 
						|
            if (empty($record)) {
 | 
						|
                // TODO move this part to the garbage collector
 | 
						|
                // check if the item should be removed from the index because it no longer matches the conditions
 | 
						|
                $this->removeFromIndexAndQueueWhenItemInQueue($recordTable, $recordUid);
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            // Clear existing index queue items to prevent mount point duplicates.
 | 
						|
            // This needs to be done before the overlay handling, because handling an overlay record should
 | 
						|
            // not trigger a deletion.
 | 
						|
            $isTranslation = !empty($record['sys_language_uid']) && $record['sys_language_uid'] !== 0;
 | 
						|
            if ($recordTable === 'pages' && !$isTranslation) {
 | 
						|
                $this->indexQueue->deleteItem('pages', $recordUid);
 | 
						|
            }
 | 
						|
 | 
						|
            // only update/insert the item if we actually found a record
 | 
						|
            $isLocalizedRecord = $this->tcaService->isLocalizedRecord($recordTable, $record);
 | 
						|
            $recordUid = $this->tcaService->getTranslationOriginalUidIfTranslated($recordTable, $record, $recordUid);
 | 
						|
 | 
						|
            if ($isLocalizedRecord && !$this->getIsTranslationParentRecordEnabled($recordTable, $recordUid)) {
 | 
						|
                // we have a localized record without a visible parent record. Nothing to do.
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
 | 
						|
            if ($this->tcaService->isEnabledRecord($recordTable, $record)) {
 | 
						|
                $this->indexQueue->updateItem($recordTable, $recordUid);
 | 
						|
            }
 | 
						|
 | 
						|
            if ($recordTable === 'pages') {
 | 
						|
                $this->doPagesPostUpdateOperations($fields, $recordUid);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * This method is used to determine the pageId that should be used to retrieve the index queue configuration.
 | 
						|
     *
 | 
						|
     * @param string $recordTable
 | 
						|
     * @param integer $recordPageId
 | 
						|
     * @param integer $recordUid
 | 
						|
     * @return integer
 | 
						|
     */
 | 
						|
    protected function getConfigurationPageId($recordTable, $recordPageId, $recordUid)
 | 
						|
    {
 | 
						|
        $rootPageId = $this->rootPageResolver->getRootPageId($recordPageId);
 | 
						|
        if ($this->rootPageResolver->getIsRootPageId($rootPageId)) {
 | 
						|
            return $recordPageId;
 | 
						|
        }
 | 
						|
 | 
						|
        $alternativeSiteRoots = $this->rootPageResolver->getAlternativeSiteRootPagesIds($recordTable, $recordUid, $recordPageId);
 | 
						|
        $lastRootPage = array_pop($alternativeSiteRoots);
 | 
						|
        return empty($lastRootPage) ? 0 : $lastRootPage;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Checks if the parent record of the translated record is enabled.
 | 
						|
     *
 | 
						|
     * @param string $recordTable
 | 
						|
     * @param integer $recordUid
 | 
						|
     * @return bool
 | 
						|
     */
 | 
						|
    protected function getIsTranslationParentRecordEnabled($recordTable, $recordUid)
 | 
						|
    {
 | 
						|
        $l10nParentRecord = (array)BackendUtility::getRecord($recordTable, $recordUid, '*', '', false);
 | 
						|
        return $this->tcaService->isEnabledRecord($recordTable, $l10nParentRecord);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies needed updates when a pages record was processed by the RecordMonitor.
 | 
						|
     *
 | 
						|
     * @param array $fields
 | 
						|
     * @param int $recordUid
 | 
						|
     */
 | 
						|
    protected function doPagesPostUpdateOperations(array $fields, $recordUid)
 | 
						|
    {
 | 
						|
        $this->updateCanonicalPages($recordUid);
 | 
						|
        $this->mountPageUpdater->update($recordUid);
 | 
						|
 | 
						|
        if ($this->isRecursivePageUpdateRequired($recordUid, $fields)) {
 | 
						|
            $treePageIds = $this->getSubPageIds($recordUid);
 | 
						|
            $this->updatePageIdItems($treePageIds);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Determines the recordPageId (pid) of a record.
 | 
						|
     *
 | 
						|
     * @param string $status
 | 
						|
     * @param string $recordTable
 | 
						|
     * @param int $recordUid
 | 
						|
     * @param int $originalUid
 | 
						|
     * @param array $fields
 | 
						|
     * @param DataHandler $tceMain
 | 
						|
     *
 | 
						|
     * @return int
 | 
						|
     */
 | 
						|
    protected function getRecordPageId($status, $recordTable, $recordUid, $originalUid, array $fields, DataHandler $tceMain)
 | 
						|
    {
 | 
						|
        if ($recordTable === 'pages' && isset($fields['l10n_parent']) && intval($fields['l10n_parent']) > 0) {
 | 
						|
            return $fields['l10n_parent'];
 | 
						|
        }
 | 
						|
 | 
						|
        if ($status === 'update' && !isset($fields['pid'])) {
 | 
						|
            $recordPageId = $this->getValidatedPid($tceMain, $recordTable, $recordUid);
 | 
						|
            if (($recordTable === 'pages') && ($this->rootPageResolver->getIsRootPageId($recordUid))) {
 | 
						|
                $recordPageId = $originalUid;
 | 
						|
            }
 | 
						|
 | 
						|
            return $recordPageId;
 | 
						|
        }
 | 
						|
 | 
						|
        return $fields['pid'];
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Applies the updateItem instruction on a collection of pageIds.
 | 
						|
     *
 | 
						|
     * @param array $treePageIds
 | 
						|
     */
 | 
						|
    protected function updatePageIdItems(array $treePageIds)
 | 
						|
    {
 | 
						|
        foreach ($treePageIds as $treePageId) {
 | 
						|
            $this->indexQueue->updateItem('pages', $treePageId);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Removes record from the index queue and from the meilisearch index
 | 
						|
     *
 | 
						|
     * @param string $recordTable Name of table where the record lives
 | 
						|
     * @param int $recordUid Id of record
 | 
						|
     */
 | 
						|
    protected function removeFromIndexAndQueue($recordTable, $recordUid)
 | 
						|
    {
 | 
						|
        $garbageCollector = GeneralUtility::makeInstance(GarbageCollector::class);
 | 
						|
        $garbageCollector->collectGarbage($recordTable, $recordUid);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Removes record from the index queue and from the meilisearch index when the item is in the queue.
 | 
						|
     *
 | 
						|
     * @param string $recordTable Name of table where the record lives
 | 
						|
     * @param int $recordUid Id of record
 | 
						|
     */
 | 
						|
    protected function removeFromIndexAndQueueWhenItemInQueue($recordTable, $recordUid)
 | 
						|
    {
 | 
						|
        if (!$this->indexQueue->containsItem($recordTable, $recordUid)) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        $this->removeFromIndexAndQueue($recordTable, $recordUid);
 | 
						|
    }
 | 
						|
 | 
						|
    // Handle pages showing content from another page
 | 
						|
 | 
						|
    /**
 | 
						|
     * Triggers Index Queue updates for other pages showing content from the
 | 
						|
     * page currently being updated.
 | 
						|
     *
 | 
						|
     * @param int $pageId UID of the page currently being updated
 | 
						|
     */
 | 
						|
    protected function updateCanonicalPages($pageId)
 | 
						|
    {
 | 
						|
        $canonicalPages = $this->pagesRepository->findPageUidsWithContentsFromPid((int)$pageId);
 | 
						|
        foreach ($canonicalPages as $page) {
 | 
						|
            $this->indexQueue->updateItem('pages', $page['uid']);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Retrieves the pid of a record and throws an exception when getPid returns false.
 | 
						|
     *
 | 
						|
     * @param DataHandler $tceMain
 | 
						|
     * @param string $table
 | 
						|
     * @param integer $uid
 | 
						|
     * @throws NoPidException
 | 
						|
     * @return integer
 | 
						|
     */
 | 
						|
    protected function getValidatedPid(DataHandler $tceMain, $table, $uid)
 | 
						|
    {
 | 
						|
        $pid = $tceMain->getPID($table, $uid);
 | 
						|
        if ($pid === false) {
 | 
						|
            throw new NoPidException('Pid should not be false');
 | 
						|
        }
 | 
						|
 | 
						|
        $pid = intval($pid);
 | 
						|
        return $pid;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Checks if the record is a draft record.
 | 
						|
     *
 | 
						|
     * @param string $table
 | 
						|
     * @param int $uid
 | 
						|
     * @return bool
 | 
						|
     */
 | 
						|
    protected function isDraftRecord($table, $uid)
 | 
						|
    {
 | 
						|
        return Util::isDraftRecord($table, $uid);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param $pageId
 | 
						|
     * @param bool $initializeTsfe
 | 
						|
     * @param int $language
 | 
						|
     * @return TypoScriptConfiguration
 | 
						|
     */
 | 
						|
    protected function getMeilisearchConfigurationFromPageId($pageId)
 | 
						|
    {
 | 
						|
        return $this->frontendEnvironment->getMeilisearchConfigurationFromPageId($pageId);
 | 
						|
    }
 | 
						|
}
 |