[BUGFIX] Sorting of localized records is wrong after copying
authorStanislas Rolland <typo3@sjbr.ca>
Wed, 19 Oct 2011 16:15:50 +0000 (12:15 -0400)
committerStanislas Rolland <typo3@sjbr.ca>
Wed, 25 Jan 2012 23:37:54 +0000 (00:37 +0100)
Solution: When copying a record in original language, if a localized
record of the destination record exists for language A, then the
localized record of the copied record, if it exists for language A,
should be inserted after the localized record, in language A, of the
destination record.
The same applies when moving a record in original language.
Similar situation arises when a new localization record is created.

Note: Backport from 4.7

Change-Id: Idf4222171134a161b346d600427d460f6f74d62b
Resolves: #30469
Releases: 4.5, 4.6, 4.7
Reviewed-on: http://review.typo3.org/8680
Reviewed-by: Georg Ringer
Tested-by: Georg Ringer
Reviewed-by: Tolleiv Nietsch
Tested-by: Tolleiv Nietsch
t3lib/class.t3lib_tcemain.php

index 6cab735..83002c1 100644 (file)
@@ -2686,7 +2686,7 @@ class t3lib_TCEmain {
                                                if ($language == 0) {
                                                                //repointing the new translation records to the parent record we just created
                                                        $overrideValues[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] = $theNewSQLID;
-                                                       $this->copyL10nOverlayRecords($table, $uid, $destPid < 0 ? $tscPID : $destPid, $first, $overrideValues, $excludeFields);
+                                                       $this->copyL10nOverlayRecords($table, $uid, $destPid, $first, $overrideValues, $excludeFields);
                                                }
 
                                                return $theNewSQLID;
@@ -3264,15 +3264,15 @@ class t3lib_TCEmain {
 
 
        /**
-        * Find l10n-overlay records and perform the requested move action for these records.
+        * Find l10n-overlay records and perform the requested copy action for these records.
         *
         * @param       string          $table: Record Table
         * @param       string          $uid: Record UID
-        * @param       string          $destPid: Position to move to
+        * @param       string          $destPid: Position to copy to
         * @return      void
         */
        function copyL10nOverlayRecords($table, $uid, $destPid, $first = 0, $overrideValues = array(), $excludeFields = '') {
-                       //there's no need to perform this for page-records
+                       // There's no need to perform this for page-records or for tables that are not localizeable
                if (!t3lib_BEfunc::isTableLocalizable($table) || !empty($GLOBALS['TCA'][$table]['ctrl']['transForeignTable']) || !empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'])) {
                        return;
                }
@@ -3282,10 +3282,32 @@ class t3lib_TCEmain {
                        $where = ' AND t3ver_oid=0';
                }
 
+                       // If $destPid is < 0, get the pid of the record with uid equal to abs($destPid)
+               $tscPID = t3lib_BEfunc::getTSconfig_pidValue($table, $uid, $destPid);
+
+                       // Get the localized records to be copied
                $l10nRecords = t3lib_BEfunc::getRecordsByField($table, $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], $uid, $where);
                if (is_array($l10nRecords)) {
+                               // If $destPid < 0, then it is the uid of the original language record we are inserting after
+                       if ($destPid < 0) {
+                               $localizedDestPids = array();
+                                       // Get the localized records of the record we are inserting after
+                               $destL10nRecords = t3lib_BEfunc::getRecordsByField($table, $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], abs($destPid), $where);
+                                       // Index the localized record uids by language
+                               if (is_array($destL10nRecords)) {
+                                       foreach ($destL10nRecords as $record) {
+                                               $localizedDestPids[$record[$GLOBALS['TCA'][$table]['ctrl']['languageField']]] = -$record['uid'];
+                                       }
+                               }
+                       }
+                               // Copy the localized records after the corresponding localizations of the destination record
                        foreach ($l10nRecords as $record) {
-                               $this->copyRecord($table, $record['uid'], $destPid, $first, $overrideValues, $excludeFields, $record[$GLOBALS['TCA'][$table]['ctrl']['languageField']]);
+                               $localizedDestPid = intval($localizedDestPids[$record[$GLOBALS['TCA'][$table]['ctrl']['languageField']]]);
+                               if ($localizedDestPid < 0) {
+                                       $this->copyRecord($table, $record['uid'], $localizedDestPid, $first, $overrideValues, $excludeFields, $record[$GLOBALS['TCA'][$table]['ctrl']['languageField']]);
+                               } else {
+                                       $this->copyRecord($table, $record['uid'], $destPid < 0 ? $tscPID : $destPid, $first, $overrideValues, $excludeFields, $record[$GLOBALS['TCA'][$table]['ctrl']['languageField']]);
+                               }
                        }
                }
        }
@@ -3464,6 +3486,8 @@ class t3lib_TCEmain {
                        }
                } else { // Put after another record
                        if ($sortRow) { // table is being sorted
+                                       // Save the position to which the original record is requested to be moved
+                               $originalRecordDestinationPid = $destPid;
                                $sortInfo = $this->getSortNumber($table, $uid, $destPid);
                                $destPid = $sortInfo['pid']; // Setting the destPid to the new pid of the record.
                                if (is_array($sortInfo)) { // If not an array, there was an error (which is already logged)
@@ -3479,7 +3503,7 @@ class t3lib_TCEmain {
                                                        // Create query for update:
                                                $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid=' . intval($uid), $updateFields);
                                                        // check for the localizations of that element
-                                               $this->moveL10nOverlayRecords($table, $uid, $destPid);
+                                               $this->moveL10nOverlayRecords($table, $uid, $destPid, $originalRecordDestinationPid);
 
                                                        // Call post processing hooks:
                                                foreach ($hookObjectsArr as $hookObj) {
@@ -3590,10 +3614,11 @@ class t3lib_TCEmain {
         * @param       string          $table: Record Table
         * @param       string          $uid: Record UID
         * @param       string          $destPid: Position to move to
+        * @param       string          $originalRecordDestinationPid: Position to move the original record to
         * @return      void
         */
-       function moveL10nOverlayRecords($table, $uid, $destPid) {
-                       //there's no need to perform this for page-records or not localizeable tables
+       function moveL10nOverlayRecords($table, $uid, $destPid, $originalRecordDestinationPid) {
+                       // There's no need to perform this for page-records or not localizeable tables
                if (!t3lib_BEfunc::isTableLocalizable($table) || !empty($GLOBALS['TCA'][$table]['ctrl']['transForeignTable']) || !empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'])) {
                        return;
                }
@@ -3604,8 +3629,26 @@ class t3lib_TCEmain {
                }
                $l10nRecords = t3lib_BEfunc::getRecordsByField($table, $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], $uid, $where);
                if (is_array($l10nRecords)) {
+                               // If $$originalRecordDestinationPid < 0, then it is the uid of the original language record we are inserting after
+                       if ($originalRecordDestinationPid < 0) {
+                               $localizedDestPids = array();
+                                       // Get the localized records of the record we are inserting after
+                               $destL10nRecords = t3lib_BEfunc::getRecordsByField($table, $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], abs($originalRecordDestinationPid), $where);
+                                       // Index the localized record uids by language
+                               if (is_array($destL10nRecords)) {
+                                       foreach ($destL10nRecords as $record) {
+                                               $localizedDestPids[$record[$GLOBALS['TCA'][$table]['ctrl']['languageField']]] = -$record['uid'];
+                                       }
+                               }
+                       }
+                               // Move the localized records after the corresponding localizations of the destination record
                        foreach ($l10nRecords as $record) {
-                               $this->moveRecord($table, $record['uid'], $destPid);
+                               $localizedDestPid = intval($localizedDestPids[$record[$GLOBALS['TCA'][$table]['ctrl']['languageField']]]);
+                               if ($localizedDestPid < 0) {
+                                       $this->moveRecord($table, $record['uid'], $localizedDestPid);
+                               } else {
+                                       $this->moveRecord($table, $record['uid'], $destPid);
+                               }
                        }
                }
        }
@@ -3682,9 +3725,10 @@ class t3lib_TCEmain {
                                                                                }
 
                                                                                if ($Ttable === $table) {
-
+                                                                                               // Get the uid of record after which this localized record should be inserted
+                                                                                       $previousUid = $this->getPreviousLocalizedRecordUid($table, $uid, $row['pid'], $language);
                                                                                                // Execute the copy:
-                                                                                       $newId = $this->copyRecord($table, $uid, -$uid, 1, $overrideValues, implode(',', $excludeFields), $language);
+                                                                                       $newId = $this->copyRecord($table, $uid, -$previousUid, 1, $overrideValues, implode(',', $excludeFields), $language);
                                                                                        $autoVersionNewId = $this->getAutoVersionId($table, $newId);
                                                                                        if (is_null($autoVersionNewId) === FALSE) {
                                                                                                $this->triggerRemapAction(
@@ -5822,6 +5866,44 @@ class t3lib_TCEmain {
        }
 
        /**
+        * Returning uid of previous localized record, if any, for tables with a "sortby" column
+        * Used when new localized records are created so that localized records are sorted in the same order as the default language records
+        *
+        * @param       string          Table name
+        * @param       integer         Uid of default language record
+        * @param       integer         Pid of default language record
+        * @param       integer         Language of localization
+        *
+        * @return      integer         uid of record after which the localized record should be inserted
+        */
+       protected function getPreviousLocalizedRecordUid($table, $uid, $pid, $language) {
+               $previousLocalizedRecordUid = $uid;
+               if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['sortby']) {
+                       $sortRow = $GLOBALS['TCA'][$table]['ctrl']['sortby'];
+                               // Get the sort value of the default language record
+                       $row = t3lib_BEfunc::getRecord($table, $uid, $sortRow . ',pid,uid');
+                       if (is_array($row)) {
+                                       // Find the previous record in default language on the same page
+                               $where = 'pid=' . intval($pid) . ' AND ' . 'sys_language_uid=0' . ' AND ' . $sortRow . '<' . intval($row[$sortRow]);
+
+                                       // Respect the colPos for content elements
+                               if ($table === 'tt_content') {
+                                       $where .= ' AND colPos=' . $row['colPos'];
+                               }
+                               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($sortRow . ',pid,uid', $table, $where . $this->deleteClause($table), '', $sortRow . ' DESC', '1');
+                                       // If there is an element, find its localized record in specified localization language
+                               if ($previousRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
+                                       $previousLocalizedRecord = t3lib_BEfunc::getRecordLocalization($table, $previousRow['uid'], $language);
+                                       if (is_array($previousLocalizedRecord[0])) {
+                                               $previousLocalizedRecordUid = $previousLocalizedRecord[0]['uid'];
+                                       }
+                               }
+                       }
+               }
+               return $previousLocalizedRecordUid;
+       }
+
+       /**
         * Setting up perms_* fields in $fieldArray based on TSconfig input
         * Used for new pages
         *
@@ -7089,4 +7171,4 @@ if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLA
        include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tcemain.php']);
 }
 
-?>
\ No newline at end of file
+?>