[!!!][FEATURE] FormEngine element level refactoring
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Database / ReferenceIndex.php
index c6a1c25..abc5a0b 100644 (file)
@@ -215,9 +215,12 @@ class ReferenceIndex
         $queryBuilder = $connection->createQueryBuilder();
         $queryBuilder->getRestrictions()->removeAll();
         $queryResult = $queryBuilder->select('*')->from('sys_refindex')->where(
-            $queryBuilder->expr()->eq('tablename', $queryBuilder->createNamedParameter($tableName)),
-            $queryBuilder->expr()->eq('recuid', (int)$uid),
-            $queryBuilder->expr()->eq('workspace', (int)$this->getWorkspaceId())
+            $queryBuilder->expr()->eq('tablename', $queryBuilder->createNamedParameter($tableName, \PDO::PARAM_STR)),
+            $queryBuilder->expr()->eq('recuid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)),
+            $queryBuilder->expr()->eq(
+                'workspace',
+                $queryBuilder->createNamedParameter($this->getWorkspaceId(), \PDO::PARAM_INT)
+            )
         )->execute();
         $currentRelations = [];
         while ($relation = $queryResult->fetch()) {
@@ -312,7 +315,8 @@ class ReferenceIndex
         $deleteField = $GLOBALS['TCA'][$tableName]['ctrl']['delete'];
 
         if ($tableRelationFields === '*') {
-            // If one field of a record is of type flex, all fields have to be fetched to be passed to BackendUtility::getFlexFormDS
+            // If one field of a record is of type flex, all fields have to be fetched
+            // to be passed to FlexFormTools->getDataStructureIdentifier()
             $selectFields = '*';
         } else {
             // otherwise only fields that might contain relations are fetched
@@ -413,7 +417,7 @@ class ReferenceIndex
             'workspace' => $this->getWorkspaceId(),
             'ref_table' => $ref_table,
             'ref_uid' => $ref_uid,
-            'ref_string' => $ref_string
+            'ref_string' => mb_substr($ref_string, 0, 1024)
         ];
     }
 
@@ -552,7 +556,7 @@ class ReferenceIndex
                     }
                 }
                 // Add a softref definition for link fields if the TCA does not specify one already
-                if ($conf['type'] === 'input' && isset($conf['wizards']['link']) && empty($conf['softref'])) {
+                if ($conf['type'] === 'input' && $conf['renderType'] === 'inputLink' && empty($conf['softref'])) {
                     $conf['softref'] = 'typolink';
                 }
                 // Add DB:
@@ -567,7 +571,8 @@ class ReferenceIndex
                 // For "flex" fieldtypes we need to traverse the structure looking for file and db references of course!
                 if ($conf['type'] === 'flex') {
                     // Get current value array:
-                    // NOTICE: failure to resolve Data Structures can lead to integrity problems with the reference index. Please look up the note in the JavaDoc documentation for the function \TYPO3\CMS\Backend\Utility\BackendUtility::getFlexFormDS()
+                    // NOTICE: failure to resolve Data Structures can lead to integrity problems with the reference index. Please look up
+                    // the note in the JavaDoc documentation for the function FlexFormTools->getDataStructureIdentifier()
                     $currentValueArray = GeneralUtility::xml2array($value);
                     // Traversing the XML structure, processing files:
                     if (is_array($currentValueArray)) {
@@ -659,7 +664,7 @@ class ReferenceIndex
             }
         }
         // Add a softref definition for link fields if the TCA does not specify one already
-        if ($dsConf['type'] === 'input' && isset($dsConf['wizards']['link']) && empty($dsConf['softref'])) {
+        if ($dsConf['type'] === 'input' && $dsConf['renderType'] === 'inputLink' && empty($dsConf['softref'])) {
             $dsConf['softref'] = 'typolink';
         }
         // Add DB:
@@ -822,7 +827,7 @@ class ReferenceIndex
                 ->select('*')
                 ->from('sys_refindex')
                 ->where(
-                    $queryBuilder->expr()->eq('hash', $queryBuilder->createNamedParameter($hash))
+                    $queryBuilder->expr()->eq('hash', $queryBuilder->createNamedParameter($hash, \PDO::PARAM_STR))
                 )
                 ->setMaxResults(1)
                 ->execute()
@@ -845,7 +850,10 @@ class ReferenceIndex
                 ->select('*')
                 ->from($referenceRecord['tablename'])
                 ->where(
-                    $queryBuilder->expr()->eq('uid',  (int)$referenceRecord['recuid'])
+                    $queryBuilder->expr()->eq(
+                        'uid',
+                        $queryBuilder->createNamedParameter($referenceRecord['recuid'], \PDO::PARAM_INT)
+                    )
                 )
                 ->setMaxResults(1)
                 ->execute()
@@ -1067,13 +1075,13 @@ class ReferenceIndex
      */
     protected function isDbReferenceField(array $configuration)
     {
-        return (
+        return
             ($configuration['type'] === 'group' && $configuration['internal_type'] === 'db')
             || (
                 ($configuration['type'] === 'select' || $configuration['type'] === 'inline')
                 && !empty($configuration['foreign_table'])
             )
-        );
+            ;
     }
 
     /**
@@ -1084,17 +1092,17 @@ class ReferenceIndex
      */
     public function isReferenceField(array $configuration)
     {
-        return (
+        return
             $this->isDbReferenceField($configuration)
             ||
             ($configuration['type'] === 'group' && ($configuration['internal_type'] === 'file' || $configuration['internal_type'] === 'file_reference')) // getRelations_procFiles
             ||
-            ($configuration['type'] === 'input' && isset($configuration['wizards']['link'])) // getRelations_procDB
+            ($configuration['type'] === 'input' && $configuration['renderType'] === 'inputLink') // getRelations_procDB
             ||
             $configuration['type'] === 'flex'
             ||
             isset($configuration['softref'])
-        );
+            ;
     }
 
     /**
@@ -1116,7 +1124,7 @@ class ReferenceIndex
                 // Check for flex field
                 if (isset($fieldDefinition['config']['type']) && $fieldDefinition['config']['type'] === 'flex') {
                     // Fetch all fields if the is a field of type flex in the table definition because the complete row is passed to
-                    // BackendUtility::getFlexFormDS in the end and might be needed in ds_pointerField or $hookObj->getFlexFormDS_postProcessDS
+                    // FlexFormTools->getDataStructureIdentifier() in the end and might be needed in ds_pointerField or a hook
                     return '*';
                 }
                 // Only fetch this field if it can contain a reference
@@ -1162,10 +1170,18 @@ class ReferenceIndex
         }
         // Traverse all tables:
         $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
+        $refIndexConnectionName = empty($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping']['sys_refindex'])
+                ? ConnectionPool::DEFAULT_CONNECTION_NAME
+                : $GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping']['sys_refindex'];
+
         foreach ($GLOBALS['TCA'] as $tableName => $cfg) {
             if (isset(static::$nonRelationTables[$tableName])) {
                 continue;
             }
+            $tableConnectionName = empty($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'][$tableName])
+                ? ConnectionPool::DEFAULT_CONNECTION_NAME
+                : $GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'][$tableName];
+
             $fields = ['uid'];
             if (BackendUtility::isTableWorkspaceEnabled($tableName)) {
                 $fields[] = 't3ver_wsid';
@@ -1187,14 +1203,12 @@ class ReferenceIndex
 
             $tableNames[] = $tableName;
             $tableCount++;
-            $uidList = [0];
             while ($record = $queryResult->fetch()) {
-                $refIndexObj = GeneralUtility::makeInstance(ReferenceIndex::class);
+                $refIndexObj = GeneralUtility::makeInstance(self::class);
                 if (isset($record['t3ver_wsid'])) {
                     $refIndexObj->setWorkspaceId($record['t3ver_wsid']);
                 }
                 $result = $refIndexObj->updateRefIndexTable($tableName, $record['uid'], $testOnly);
-                $uidList[] = $record['uid'];
                 $recCount++;
                 if ($result['addedNodes'] || $result['deletedNodes']) {
                     $error = 'Record ' . $tableName . ':' . $record['uid'] . ' had ' . $result['addedNodes'] . ' added indexes and ' . $result['deletedNodes'] . ' deleted indexes';
@@ -1205,15 +1219,45 @@ class ReferenceIndex
                 }
             }
 
+            // Subselect based queries only work on the same connection
+            if ($refIndexConnectionName !== $tableConnectionName) {
+                GeneralUtility::sysLog(
+                    sprintf(
+                        'Not checking table "%s" for lost indexes, "sys_refindex" table uses a different connection',
+                        $tableName
+                    ),
+                    'core',
+                    GeneralUtility::SYSLOG_SEVERITY_ERROR
+                );
+                continue;
+            }
+
             // Searching for lost indexes for this table
+            // Build sub-query to find lost records
+            $subQueryBuilder = $connectionPool->getQueryBuilderForTable($tableName);
+            $subQueryBuilder->getRestrictions()->removeAll();
+            $subQueryBuilder
+                ->select('uid')
+                ->from($tableName, 'sub_' . $tableName)
+                ->where(
+                    $subQueryBuilder->expr()->eq(
+                        'sub_' . $tableName . '.uid',
+                        $queryBuilder->quoteIdentifier('sys_refindex.recuid')
+                    )
+                );
+
+            // Main query to find lost records
             $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_refindex');
             $queryBuilder->getRestrictions()->removeAll();
             $lostIndexes = $queryBuilder
                 ->count('hash')
                 ->from('sys_refindex')
                 ->where(
-                    $queryBuilder->expr()->eq('tablename', $queryBuilder->createNamedParameter($tableName)),
-                    $queryBuilder->expr()->notIn('recuid', $uidList)
+                    $queryBuilder->expr()->eq(
+                        'tablename',
+                        $queryBuilder->createNamedParameter($tableName, \PDO::PARAM_STR)
+                    ),
+                    'NOT EXISTS (' . $subQueryBuilder->getSQL() . ')'
                 )
                 ->execute()
                 ->fetchColumn(0);
@@ -1228,9 +1272,13 @@ class ReferenceIndex
                     $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_refindex');
                     $queryBuilder->delete('sys_refindex')
                         ->where(
-                            $queryBuilder->expr()->eq('tablename', $queryBuilder->createNamedParameter($tableName)),
-                            $queryBuilder->expr()->notIn('recuid', $uidList)
-                        )->execute();
+                            $queryBuilder->expr()->eq(
+                                'tablename',
+                                $queryBuilder->createNamedParameter($tableName, \PDO::PARAM_STR)
+                            ),
+                            'NOT EXISTS (' . $subQueryBuilder->getSQL() . ')'
+                        )
+                        ->execute();
                 }
             }
         }