[BUGFIX] Catch DatabaseRecordException when editing record with deleted relation 97/55197/8
authorAndreas Fernandez <a.fernandez@scripting-base.de>
Fri, 22 Dec 2017 10:35:05 +0000 (11:35 +0100)
committerAndreas Wolf <andreas.wolf@typo3.org>
Sat, 27 Jan 2018 11:10:46 +0000 (12:10 +0100)
Editing a record with a deleted related record leads to an uncaught
DatabaseRecordException. This patch catches the exception and
ignores such records, but logs a warning.

Due to possible errors occurring with certain DBMS (e.g. MySQL
strict) columns may require a default value now in TCA.

Resolves: #83412
Releases: master, 8.7
Change-Id: I5adaf385443350ce245dd83da6e5f1a16d9c9afb
Reviewed-on: https://review.typo3.org/55197
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Reiner Teubner <rteubner@me.com>
Tested-by: Reiner Teubner <rteubner@me.com>
Reviewed-by: Andreas Wolf <andreas.wolf@typo3.org>
Tested-by: Andreas Wolf <andreas.wolf@typo3.org>
typo3/sysext/backend/Classes/Form/FormDataProvider/AbstractDatabaseRecordProvider.php
typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInline.php

index 2751340..9193842 100644 (file)
@@ -14,6 +14,8 @@ namespace TYPO3\CMS\Backend\Form\FormDataProvider;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerAwareTrait;
 use TYPO3\CMS\Backend\Form\Exception\DatabaseRecordException;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
@@ -22,8 +24,10 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Extended by other provider that fetch records from database
  */
-abstract class AbstractDatabaseRecordProvider
+abstract class AbstractDatabaseRecordProvider implements LoggerAwareInterface
 {
+    use LoggerAwareTrait;
+
     /**
      * Fetch a record from database. Deleted records will NOT be fetched.
      * Method is similar to BackendUtility::getRecord, but is more picky
index 4f1c99b..b4d6794 100644 (file)
@@ -152,7 +152,20 @@ class TcaInline extends AbstractDatabaseRecordProvider implements FormDataProvid
             // localized but miss default language record
             $fieldNameWithDefaultLanguageUid = $GLOBALS['TCA'][$childTableName]['ctrl']['transOrigPointerField'];
             foreach ($connectedUidsOfLocalizedOverlay as $localizedUid) {
-                $localizedRecord = $this->getRecordFromDatabase($childTableName, $localizedUid);
+                try {
+                    $localizedRecord = $this->getRecordFromDatabase($childTableName, $localizedUid);
+                } catch (DatabaseRecordException $e) {
+                    // The child could not be compiled, probably it was deleted and a dangling mm record exists
+                    $this->logger->warning(
+                        $e->getMessage(),
+                        [
+                            'table' => $childTableName,
+                            'uid' => $localizedUid,
+                            'exception' => $e
+                        ]
+                    );
+                    continue;
+                }
                 $uidOfDefaultLanguageRecord = $localizedRecord[$fieldNameWithDefaultLanguageUid];
                 if (in_array($uidOfDefaultLanguageRecord, $connectedUidsOfDefaultLanguageRecord)) {
                     // This localized child has a default language record. Remove this record from list of default language records
@@ -166,7 +179,20 @@ class TcaInline extends AbstractDatabaseRecordProvider implements FormDataProvid
                 foreach ($connectedUidsOfDefaultLanguageRecord as $defaultLanguageUid) {
                     // If there are still uids in $connectedUidsOfDefaultLanguageRecord, these are records that
                     // exist in default language, but are not localized yet. Compile and mark those
-                    $compiledChild = $this->compileChild($result, $fieldName, $defaultLanguageUid);
+                    try {
+                        $compiledChild = $this->compileChild($result, $fieldName, $defaultLanguageUid);
+                    } catch (DatabaseRecordException $e) {
+                        // The child could not be compiled, probably it was deleted and a dangling mm record exists
+                        $this->logger->warning(
+                            $e->getMessage(),
+                            [
+                                'table' => $childTableName,
+                                'uid' => $localizedUid,
+                                'exception' => $e
+                            ]
+                        );
+                        continue;
+                    }
                     $compiledChild['isInlineDefaultLanguageRecordInLocalizedParentContext'] = true;
                     $result['processedTca']['columns'][$fieldName]['children'][] = $compiledChild;
                 }