diff --git a/Classes/Task/CleanupIndexTask.php b/Classes/Task/CleanupIndexTask.php
new file mode 100644
index 0000000000..e9c9f0f4e5
--- /dev/null
+++ b/Classes/Task/CleanupIndexTask.php
@@ -0,0 +1,102 @@
+
+ */
+class CleanupIndexTask extends AbstractSolrTask
+{
+ protected ?int $deleteOlderThanDays = null;
+
+ public function getDeleteOlderThanDays(): ?int
+ {
+ return $this->deleteOlderThanDays;
+ }
+
+ public function setDeleteOlderThanDays(?int $deleteOlderThanDays): void
+ {
+ $this->deleteOlderThanDays = $deleteOlderThanDays;
+ }
+
+ /**
+ * Deletes old documents from index
+ *
+ * @return bool Returns TRUE on success, FALSE on failure.
+ *
+ * @throws DBALConnectionException
+ * @throws DBALException
+ *
+ * @noinspection PhpMissingReturnTypeInspection See {@link \TYPO3\CMS\Scheduler\Task\AbstractTask::execute()}
+ */
+ public function execute()
+ {
+ $cleanUpResult = true;
+ $solrConfiguration = $this->getSite()->getSolrConfiguration();
+ $solrServers = GeneralUtility::makeInstance(ConnectionManager::class)->getConnectionsBySite($this->getSite());
+ $enableCommitsSetting = $solrConfiguration->getEnableCommits();
+
+ foreach ($solrServers as $solrServer) {
+ $deleteQuery = 'siteHash:' . $this->getSite()->getSiteHash() . sprintf(' AND indexed:[* TO NOW-%dDAYS]', $this->deleteOlderThanDays ?? 1);
+ $solrServer->getWriteService()->deleteByQuery($deleteQuery);
+
+ if (!$enableCommitsSetting) {
+ // Do not commit
+ continue;
+ }
+
+ $response = $solrServer->getWriteService()->commit(false, false);
+ if ($response->getHttpStatus() != 200) {
+ $cleanUpResult = false;
+ break;
+ }
+ }
+
+ return $cleanUpResult;
+ }
+
+ /**
+ * This method is designed to return some additional information about the task,
+ * that may help to set it apart from other tasks from the same class
+ * This additional information is used - for example - in the Scheduler's BE module
+ * This method should be implemented in most task classes
+ *
+ * @return string Information to display
+ *
+ * @throws DBALException
+ *
+ * @noinspection PhpMissingReturnTypeInspection See {@link \TYPO3\CMS\Scheduler\Task\AbstractTask::getAdditionalInformation()}
+ */
+ public function getAdditionalInformation()
+ {
+ $site = $this->getSite();
+ if (is_null($site)) {
+ return 'Invalid site configuration for scheduler please re-create the task!';
+ }
+
+ return 'Site: ' . $this->getSite()->getLabel();
+ }
+}
diff --git a/Classes/Task/CleanupTaskAdditionalFieldProvider.php b/Classes/Task/CleanupTaskAdditionalFieldProvider.php
new file mode 100644
index 0000000000..5b410ccca7
--- /dev/null
+++ b/Classes/Task/CleanupTaskAdditionalFieldProvider.php
@@ -0,0 +1,197 @@
+
+ */
+class CleanupTaskAdditionalFieldProvider extends AbstractAdditionalFieldProvider
+{
+ protected array $taskInformation = [];
+
+ /**
+ * Scheduler task
+ */
+ protected ?CleanupIndexTask $task;
+
+ protected ?SchedulerModuleController $schedulerModule = null;
+
+ /**
+ * Selected site
+ */
+ protected ?Site $site = null;
+
+ protected SiteRepository $siteRepository;
+
+ protected ?PageRenderer $pageRenderer = null;
+
+ public function __construct()
+ {
+ $this->siteRepository = GeneralUtility::makeInstance(SiteRepository::class);
+ }
+
+ /**
+ * Initialize object
+ *
+ * @throws DBALException
+ */
+ protected function initialize(
+ array $taskInfo,
+ ?CleanupIndexTask $task,
+ SchedulerModuleController $schedulerModule
+ ): void {
+ /* ReIndexTask @var $task */
+ $this->taskInformation = $taskInfo;
+ $this->task = $task;
+ $this->schedulerModule = $schedulerModule;
+
+ $currentAction = $schedulerModule->getCurrentAction();
+
+ if ($currentAction->equals(Action::EDIT)) {
+ $this->site = $this->siteRepository->getSiteByRootPageId((int)$task->getRootPageId());
+ }
+ }
+
+ /**
+ * Used to define fields to provide the Solr server address when adding
+ * or editing a task.
+ *
+ * @param array $taskInfo reference to the array containing the info used in the add/edit form
+ * @param CleanupIndexTask $task when editing, reference to the current task object. Null when adding.
+ * @param SchedulerModuleController $schedulerModule reference to the calling object (Scheduler's BE module)
+ *
+ * @return array Array containing all the information pertaining to the additional fields
+ * The array is multidimensional, keyed to the task class name and each field's id
+ * For each field it provides an associative sub-array with the following:
+ *
+ * @throws BackendFormException
+ * @throws UnexpectedTYPO3SiteInitializationException
+ * @throws DBALException
+ *
+ * @noinspection PhpParameterByRefIsNotUsedAsReferenceInspection
+ * @noinspection PhpMissingReturnTypeInspection
+ */
+ public function getAdditionalFields(
+ array &$taskInfo,
+ $task,
+ SchedulerModuleController $schedulerModule
+ ) {
+ $additionalFields = [];
+
+ if (!$this->isTaskInstanceofCleanupIndexTask($task)) {
+ return $additionalFields;
+ }
+
+ $this->initialize($taskInfo, $task, $schedulerModule);
+ $siteSelectorField = GeneralUtility::makeInstance(SiteSelectorField::class);
+
+ $additionalFields['site'] = [
+ 'code' => $siteSelectorField->getAvailableSitesSelector(
+ 'tx_scheduler[site]',
+ $this->site
+ ),
+ 'label' => 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf:field_site',
+ ];
+
+ $additionalFields['deleteOlderThanDays'] = [
+ 'code' => '',
+ 'label' => 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf:task.cleanupIndex.deleteOlderThanDays',
+ ];
+
+ return $additionalFields;
+ }
+
+ /**
+ * Checks any additional data that is relevant to this task. If the task
+ * class is not relevant, the method is expected to return TRUE
+ *
+ * @param array $submittedData reference to the array containing the data submitted by the user
+ * @param SchedulerModuleController $schedulerModule reference to the calling object (Scheduler's BE module)
+ *
+ * @return bool True if validation was ok (or selected class is not relevant), FALSE otherwise
+ *
+ * @throws UnexpectedTYPO3SiteInitializationException
+ *
+ * @noinspection PhpParameterByRefIsNotUsedAsReferenceInspection
+ * @noinspection PhpMissingReturnTypeInspection
+ */
+ public function validateAdditionalFields(
+ array &$submittedData,
+ SchedulerModuleController $schedulerModule
+ ): bool {
+ $result = false;
+
+ // validate site
+ $sites = $this->siteRepository->getAvailableSites();
+ if (array_key_exists($submittedData['site'], $sites)) {
+ $result = true;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Saves any additional input into the current task object if the task
+ * class matches.
+ *
+ * @param array $submittedData array containing the data submitted by the user
+ * @param CleanupIndexTask $task reference to the current task object
+ */
+ public function saveAdditionalFields(
+ array $submittedData,
+ CleanupIndexTask|AbstractTask $task
+ ): void {
+ if (!$this->isTaskInstanceofCleanupIndexTask($task)) {
+ return;
+ }
+
+ $task->setRootPageId((int)$submittedData['site']);
+ $task->setDeleteOlderThanDays($submittedData['deleteOlderThanDays'] ? (int)$submittedData['deleteOlderThanDays'] : null);
+ }
+
+ /**
+ * Check that a task is an instance of ReIndexTask
+ */
+ protected function isTaskInstanceofCleanupIndexTask(?AbstractTask $task): bool
+ {
+ if ((!is_null($task)) && (!($task instanceof CleanupIndexTask))) {
+ throw new LogicException(
+ '$task must be an instance of ReIndexTask, '
+ . 'other instances are not supported.',
+ 1487500366
+ );
+ }
+ return true;
+ }
+}
diff --git a/Classes/Task/ReIndexTask.php b/Classes/Task/ReIndexTask.php
index 745a545b77..4aa6c55042 100644
--- a/Classes/Task/ReIndexTask.php
+++ b/Classes/Task/ReIndexTask.php
@@ -17,7 +17,6 @@
namespace ApacheSolrForTypo3\Solr\Task;
-use ApacheSolrForTypo3\Solr\ConnectionManager;
use ApacheSolrForTypo3\Solr\Domain\Index\Queue\QueueInitializationService;
use Doctrine\DBAL\ConnectionException as DBALConnectionException;
use Doctrine\DBAL\Exception as DBALException;
@@ -37,7 +36,7 @@ class ReIndexTask extends AbstractSolrTask
protected array $indexingConfigurationsToReIndex = [];
/**
- * Purges/commits all Solr indexes, initializes the Index Queue
+ * Initializes the Index Queue
* and returns TRUE if the execution was successful
*
* @return bool Returns TRUE on success, FALSE on failure.
@@ -49,55 +48,13 @@ class ReIndexTask extends AbstractSolrTask
*/
public function execute()
{
- // clean up
- $cleanUpResult = $this->cleanUpIndex();
-
// initialize for re-indexing
/** @var QueueInitializationService $indexQueueInitializationService */
$indexQueueInitializationService = GeneralUtility::makeInstance(QueueInitializationService::class);
$indexQueueInitializationResults = $indexQueueInitializationService
->initializeBySiteAndIndexConfigurations($this->getSite(), $this->indexingConfigurationsToReIndex);
- return $cleanUpResult && !in_array(false, $indexQueueInitializationResults);
- }
-
- /**
- * Removes documents of the selected types from the index.
- *
- * @return bool TRUE if clean up was successful, FALSE on error
- *
- * @throws DBALException
- */
- protected function cleanUpIndex(): bool
- {
- $cleanUpResult = true;
- $solrConfiguration = $this->getSite()->getSolrConfiguration();
- $solrServers = GeneralUtility::makeInstance(ConnectionManager::class)->getConnectionsBySite($this->getSite());
- $typesToCleanUp = [];
- $enableCommitsSetting = $solrConfiguration->getEnableCommits();
-
- foreach ($this->indexingConfigurationsToReIndex as $indexingConfigurationName) {
- $type = $solrConfiguration->getIndexQueueTypeOrFallbackToConfigurationName($indexingConfigurationName);
- $typesToCleanUp[] = $type;
- }
-
- foreach ($solrServers as $solrServer) {
- $deleteQuery = 'type:(' . implode(' OR ', $typesToCleanUp) . ')' . ' AND siteHash:' . $this->getSite()->getSiteHash();
- $solrServer->getWriteService()->deleteByQuery($deleteQuery);
-
- if (!$enableCommitsSetting) {
- // Do not commit
- continue;
- }
-
- $response = $solrServer->getWriteService()->commit(false, false);
- if ($response->getHttpStatus() != 200) {
- $cleanUpResult = false;
- break;
- }
- }
-
- return $cleanUpResult;
+ return !in_array(false, $indexQueueInitializationResults);
}
/**
diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf
index bb61629b0e..a22e0cb6e9 100644
--- a/Resources/Private/Language/de.locallang.xlf
+++ b/Resources/Private/Language/de.locallang.xlf
@@ -36,6 +36,18 @@
Forced webroot (Nur notwendig wenn webroot von PATH_site abweicht)
+
+
+ Index-Bereinigung
+
+
+
+ Löscht alte Dokumente aus dem Index
+
+
+
+ Lösche alle Dokumente älter als # Tage
+
Solr host
diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf
index a668a93742..00a2c81ed7 100644
--- a/Resources/Private/Language/locallang.xlf
+++ b/Resources/Private/Language/locallang.xlf
@@ -110,6 +110,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/ext_localconf.php b/ext_localconf.php
index 242b911648..278890582c 100644
--- a/ext_localconf.php
+++ b/ext_localconf.php
@@ -15,6 +15,8 @@
use ApacheSolrForTypo3\Solr\IndexQueue\RecordMonitor;
use ApacheSolrForTypo3\Solr\Routing\Enhancer\SolrFacetMaskAndCombineEnhancer;
use ApacheSolrForTypo3\Solr\System\Configuration\ExtensionConfiguration;
+use ApacheSolrForTypo3\Solr\Task\CleanupIndexTask;
+use ApacheSolrForTypo3\Solr\Task\CleanupTaskAdditionalFieldProvider;
use ApacheSolrForTypo3\Solr\Task\EventQueueWorkerTask;
use ApacheSolrForTypo3\Solr\Task\EventQueueWorkerTaskAdditionalFieldProvider;
use ApacheSolrForTypo3\Solr\Task\IndexQueueWorkerTask;
@@ -87,6 +89,13 @@
'additionalFields' => EventQueueWorkerTaskAdditionalFieldProvider::class,
];
+ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][CleanupIndexTask::class] = [
+ 'extension' => 'solr',
+ 'title' => 'LLL:EXT:solr/Resources/Private/Language/locallang_.xlf:task.cleanupIndex.title',
+ 'description' => 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf:task.cleanupIndex.description',
+ 'additionalFields' => CleanupTaskAdditionalFieldProvider::class,
+ ];
+
if (!isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][TableGarbageCollectionTask::class]['options']['tables']['tx_solr_statistics'])) {
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][TableGarbageCollectionTask::class]['options']['tables']['tx_solr_statistics'] = [
'dateField' => 'tstamp',