[BUGFIX] Prevent infinite loop in TceformsUpdateWizard 32/37032/6
authorNicole Cordes <typo3@cordes.co>
Fri, 20 Feb 2015 00:55:57 +0000 (01:55 +0100)
committerMarkus Klein <klein.t3@reelworx.at>
Mon, 2 Mar 2015 20:22:41 +0000 (21:22 +0100)
If you have more than 1000 missing files within file relations in
tt_content.image and pages.media an infinite loop pops up, because
always the same records are fetched from database. This patch stores
the uids of failed records for each table to prevent the infinite loop
and restart processing after timeout.

Releases: 6.2
Resolves: #57393
Change-Id: I559be13efe88ae3111321dafb8d6a79886f903ae
Reviewed-on: http://review.typo3.org/37032
Reviewed-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Göran Bodenschatz <coding@46halbe.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Markus Klein <klein.t3@reelworx.at>
Tested-by: Markus Klein <klein.t3@reelworx.at>
typo3/sysext/install/Classes/Updates/TceformsUpdateWizard.php

index c74487c..a0b9fdf 100644 (file)
@@ -85,6 +85,21 @@ class TceformsUpdateWizard extends AbstractUpdate {
        );
 
        /**
+        * @var \TYPO3\CMS\Core\Registry
+        */
+       protected $registry;
+
+       /**
+        * @var string
+        */
+       protected $registryNamespace = 'TceformsUpdateWizard';
+
+       /**
+        * @var array
+        */
+       protected $recordOffset = array();
+
+       /**
         * Constructor
         */
        public function __construct() {
@@ -102,6 +117,8 @@ class TceformsUpdateWizard extends AbstractUpdate {
                $storageRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository');
                $storages = $storageRepository->findAll();
                $this->storage = $storages[0];
+               $this->registry = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Registry');
+               $this->recordOffset = $this->registry->get($this->registryNamespace, 'recordOffset', array());
        }
 
        /**
@@ -177,11 +194,17 @@ class TceformsUpdateWizard extends AbstractUpdate {
                                                $fieldsToGet[] = $fieldConfiguration['links'];
                                        }
 
+                                       if (!isset($this->recordOffset[$table])) {
+                                               $this->recordOffset[$table] = 0;
+                                       }
+
                                        do {
-                                               $records = $this->getRecordsFromTable($table, $fieldToMigrate, $fieldsToGet, self::RECORDS_PER_QUERY);
+                                               $limit = $this->recordOffset[$table] . ',' . self::RECORDS_PER_QUERY;
+                                               $records = $this->getRecordsFromTable($table, $fieldToMigrate, $fieldsToGet, $limit);
                                                foreach ($records as $record) {
                                                        $this->migrateField($table, $record, $fieldToMigrate, $fieldConfiguration, $customMessages);
                                                }
+                                               $this->registry->set($this->registryNamespace, 'recordOffset', $this->recordOffset);
                                        } while (count($records) === self::RECORDS_PER_QUERY);
 
                                        // add the field to the "finished fields" if things didn't fail above
@@ -191,6 +214,7 @@ class TceformsUpdateWizard extends AbstractUpdate {
                                }
                        }
                        $this->markWizardAsDone(implode(',', $finishedFields));
+                       $this->registry->remove($this->registryNamespace, 'recordOffset');
                } catch (\Exception $e) {
                        $customMessages .= PHP_EOL . $e->getMessage();
                }
@@ -230,7 +254,7 @@ class TceformsUpdateWizard extends AbstractUpdate {
                        . ' AND ' . $fieldToMigrate . ' != \'\''
                        . ' AND CAST(CAST(' . $fieldToMigrate . ' AS DECIMAL) AS CHAR) <> CAST(' . $fieldToMigrate . ' AS CHAR)'
                        . $deletedCheck;
-               $result = $this->database->exec_SELECTgetRows($fields, $table, $where, '', '', $limit);
+               $result = $this->database->exec_SELECTgetRows($fields, $table, $where, '', 'uid', $limit);
                if ($result === NULL) {
                        throw new \RuntimeException('Database query failed. Error was: ' . $this->database->sql_error());
                }
@@ -378,6 +402,8 @@ class TceformsUpdateWizard extends AbstractUpdate {
                if ($i === count($fieldItems)) {
                        $this->database->exec_UPDATEquery($table, 'uid=' . $row['uid'], array($fieldname => $i));
                        $queries[] = str_replace(LF, ' ', $this->database->debug_lastBuiltQuery);
+               } else {
+                       $this->recordOffset[$table]++;
                }
                return $queries;
        }