Commit c0d87152 authored by Thomas Hohn's avatar Thomas Hohn Committed by Christian Kuhn
Browse files

[FEATURE] Add signal to exclude tables from ReferenceIndex

A new signal is introduced to allow the exclusion of tables from the
ReferenceIndex. The checks whether tables or columns should be excluded
are extracted to methods.

Fixes: #79387
Releases: master
Change-Id: I5ef558bc1a1c63553e8a1dc193167d068f235487
Reviewed-on: https://review.typo3.org/51362

Reviewed-by: Stephan Großberndt's avatarStephan Großberndt <stephan@grossberndt.de>
Tested-by: Stephan Großberndt's avatarStephan Großberndt <stephan@grossberndt.de>
Tested-by: default avatarTYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
parent cc7b4ad5
......@@ -27,6 +27,7 @@ use TYPO3\CMS\Core\Resource\Folder;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
use TYPO3\CMS\Extbase\SignalSlot\Dispatcher;
/**
* Reference index processing and relation extraction
......@@ -44,37 +45,35 @@ use TYPO3\CMS\Core\Utility\PathUtility;
class ReferenceIndex
{
/**
* Definition of tables to exclude from searching for relations
* Definition of tables to exclude from the ReferenceIndex
*
* Only tables which do not contain any relations and never did so far since references also won't be deleted for
* these. Since only tables with an entry in $GLOBALS['TCA] are handled by ReferenceIndex there is no need to add
* *_mm-tables.
*
* This is implemented as an array with fields as keys and booleans as values to be able to fast isset() instead of
* slow in_array() lookup.
* Implemented as array with fields as keys and booleans as values for fast isset() lookup instead of slow in_array()
*
* @var array
* @see updateRefIndexTable()
* @todo #65461 Create configuration for tables to exclude from ReferenceIndex
* @see shouldExcludeTableFromReferenceIndex()
*/
protected static $nonRelationTables = [
protected static $excludedTables = [
'sys_log' => true,
'sys_history' => true,
'tx_extensionmanager_domain_model_extension' => true
];
/**
* Definition of fields to exclude from searching for relations
* Definition of fields to exclude from ReferenceIndex in *every* table
*
* This is implemented as an array with fields as keys and booleans as values to be able to fast isset() instead of
* slow in_array() lookup.
* Implemented as array with fields as keys and booleans as values for fast isset() lookup instead of slow in_array()
*
* @var array
* @see getRelations()
* @see fetchTableRelationFields()
* @todo #65460 Create configuration for fields to exclude from ReferenceIndex
* @see shouldExcludeTableColumnFromReferenceIndex()
*/
protected static $nonRelationFields = [
protected static $excludedColumns = [
'uid' => true,
'perms_userid' => true,
'perms_groupid' => true,
......@@ -195,7 +194,7 @@ class ReferenceIndex
];
// If this table cannot contain relations, skip it
if (isset(static::$nonRelationTables[$tableName])) {
if ($this->shouldExcludeTableFromReferenceIndex($tableName)) {
return $result;
}
......@@ -523,7 +522,7 @@ class ReferenceIndex
$uid = $row['uid'];
$outRow = [];
foreach ($row as $field => $value) {
if (!isset(static::$nonRelationFields[$field]) && is_array($GLOBALS['TCA'][$table]['columns'][$field]) && (!$onlyField || $onlyField === $field)) {
if ($this->shouldExcludeTableColumnFromReferenceIndex($table, $field, $onlyField) === false) {
$conf = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
// Add files
$resultsFromFiles = $this->getRelations_procFiles($value, $conf, $uid);
......@@ -1175,7 +1174,7 @@ class ReferenceIndex
: $GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping']['sys_refindex'];
foreach ($GLOBALS['TCA'] as $tableName => $cfg) {
if (isset(static::$nonRelationTables[$tableName])) {
if ($this->shouldExcludeTableFromReferenceIndex($tableName)) {
continue;
}
$tableConnectionName = empty($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'][$tableName])
......@@ -1338,6 +1337,50 @@ class ReferenceIndex
return [$headerContent, $bodyContent, $errorCount];
}
/**
* Checks if a given table should be excluded from ReferenceIndex
*
* @param string $tableName Name of the table
* @return bool true if it should be excluded
*/
protected function shouldExcludeTableFromReferenceIndex($tableName)
{
if (isset(static::$excludedTables[$tableName])) {
return static::$excludedTables[$tableName];
}
// Only exclude tables from ReferenceIndex which do not contain any relations and never did since existing references won't be deleted!
// There is no need to add tables without a definition in $GLOBALS['TCA] since ReferenceIndex only handles those.
$excludeTable = false;
$signalSlotDispatcher = GeneralUtility::makeInstance(Dispatcher::class);
$signalSlotDispatcher->dispatch(__CLASS__, 'shouldExcludeTableFromReferenceIndex', [$tableName, &$excludeTable]);
static::$excludedTables[$tableName] = $excludeTable;
return static::$excludedTables[$tableName];
}
/**
* Checks if a given column in a given table should be excluded in the ReferenceIndex process
*
* @param string $tableName Name of the table
* @param string $column Name of the column
* @param string $onlyColumn Name of a specific column to fetch
* @return bool true if it should be excluded
*/
protected function shouldExcludeTableColumnFromReferenceIndex($tableName, $column, $onlyColumn)
{
if (isset(static::$excludedColumns[$column])) {
return true;
}
if (is_array($GLOBALS['TCA'][$tableName]['columns'][$column]) && (!$onlyColumn || $onlyColumn === $column)) {
return false;
}
return true;
}
/**
* Returns the current BE user.
*
......
.. include:: ../../Includes.txt
==================================================================
Feature: #79387 - Add signal to exclude tables from ReferenceIndex
==================================================================
See :issue:`79387`
Description
===========
A new signal :php:`shouldExcludeTableFromReferenceIndex` is emitted in :php:`TYPO3\CMS\Core\Database\ReferenceIndex` which allows extensions to define tables
which should be excluded from ReferenceIndex.
Register the class which excludes tables in `ext_localconf.php`:
.. code-block:: php
$dispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class);
$dispatcher->connect(
\TYPO3\CMS\Core\Database\ReferenceIndex::class,
'shouldExcludeTableFromReferenceIndex',
\MyVendor\MyExtension\Slots\ReferenceIndexSlot::class,
'shouldExcludeTableFromReferenceIndex'
);
Your class could look like this:
.. code-block:: php
namespace MyVendor\MyExtension\Slot;
class ReferenceIndexSlot {
/**
* Exclude tables from ReferenceIndex which cannot contain a reference
*
* @param string $tableName Name of the table
* @param bool &$excludeTable Reference to a boolean whether to exclude the table from ReferenceIndex or not
*/
public function shouldExcludeTableFromReferenceIndex($tableName, &$excludeTable) {
if ($tableName === 'tx_myextension_mytable') {
$excludeTable = true;
}
}
}
Impact
======
This signal allows extensions to speed up the process of maintaining the ReferenceIndex: If an extension has tables in which by definition none of its columns
can contain any relations to other records it can be excluded from ReferenceIndex.
Only exclude tables from ReferenceIndex which do not contain any relations and never did since existing references won't be deleted if it is excluded! There is
no need to add tables without a definition in :php:`$GLOBALS['TCA]` since ReferenceIndex only handles those.
.. index:: Database
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment