[BUGFIX] Invalid localization overlay of cObject FILES 39/29739/9
authorOliver Hader <oliver@typo3.org>
Wed, 30 Apr 2014 07:44:01 +0000 (09:44 +0200)
committerSteffen Ritter <info@rs-websystems.de>
Wed, 11 Jun 2014 14:54:53 +0000 (16:54 +0200)
The TypoScript cObject FILES does not consider localization
overlays and behavior correctly when it comes additional
translation table (e.g. for pages).

Concerning pages_language_overlay.media, there is no default
fallback to the values of the default language. This behavior
is the same to TYPO3 4.5. If the localization shall fallback
to the default language, the "mergeIfNotBlank" property needs
to be used for the accordant field.

For having the localization handling working properly the
FILES cObject section "references" must not set the properties
"table" and "uid" - otherwise the values will just be overriden
by those TypoScript settings.

Resolves: #58352
Resolves: #47869
Releases: 6.2
Change-Id: I8e915654e5ab1ed1eafe86411930f9fbfcc225ae
Reviewed-on: https://review.typo3.org/29739
Reviewed-by: Steffen Ritter
Tested-by: Steffen Ritter
typo3/sysext/core/Classes/Resource/Service/FrontendContentAdapterService.php
typo3/sysext/frontend/Classes/ContentObject/FilesContentObject.php
typo3/sysext/frontend/Classes/Page/PageRepository.php

index 38a0e00..54ee327 100644 (file)
@@ -97,12 +97,7 @@ class FrontendContentAdapterService {
                if (array_key_exists($table, static::$migrateFields)) {
                        foreach (static::$migrateFields[$table] as $migrateFieldName => $oldFieldNames) {
                                if ($row !== NULL && isset($row[$migrateFieldName]) && self::fieldIsInType($migrateFieldName, $table, $row)) {
-                                       /** @var $fileRepository \TYPO3\CMS\Core\Resource\FileRepository */
-                                       $fileRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\FileRepository');
-                                       if ($table === 'pages' && isset($row['_LOCALIZED_UID']) && intval($row['sys_language_uid']) > 0) {
-                                               $table = 'pages_language_overlay';
-                                       }
-                                       $files = $fileRepository->findByRelation($table, $migrateFieldName, isset($row['_LOCALIZED_UID']) ? intval($row['_LOCALIZED_UID']) : intval($row['uid']));
+                                       $files = self::getPageRepository()->getFileReferences($table, $migrateFieldName, $row);
                                        $fileFieldContents = array(
                                                'paths' => array(),
                                                'titleTexts' => array(),
@@ -208,4 +203,12 @@ class FrontendContentAdapterService {
                        return in_array($row[$fieldConfiguration['__typeMatch']['typeField']], $fieldConfiguration['__typeMatch']['types']);
                }
        }
+
+       /**
+        * @return \TYPO3\CMS\Frontend\Page\PageRepository
+        */
+       static protected function getPageRepository() {
+               return $GLOBALS['TSFE']->sys_page;
+       }
+
 }
index 5ee572f..e5c4da1 100644 (file)
@@ -86,19 +86,7 @@ class FilesContentObject extends \TYPO3\CMS\Frontend\ContentObject\AbstractConte
                                }
                        }
 
-                       // It's important that this always stays "fieldName" and not be renamed to "field" as it would otherwise collide with the stdWrap key of that name
-                       if (!empty($conf['references.'])) {
-                               $referencesFieldName = $this->cObj->stdWrapValue('fieldName', $conf['references.']);
-                               if ($referencesFieldName) {
-                                       $table = $this->cObj->getCurrentTable();
-                                       if ($table === 'pages' && isset($this->cObj->data['_LOCALIZED_UID']) && (int)$this->cObj->data['sys_language_uid'] > 0) {
-                                               $table = 'pages_language_overlay';
-                                       }
-                                       $referencesForeignTable = $this->cObj->stdWrapValue('table', $conf['references.'], $table);
-                                       $referencesForeignUid = $this->cObj->stdWrapValue('uid', $conf['references.'], isset($this->cObj->data['_LOCALIZED_UID']) ? $this->cObj->data['_LOCALIZED_UID'] : $this->cObj->data['uid']);
-                                       $this->addToArray($this->getFileRepository()->findByRelation($referencesForeignTable, $referencesFieldName, $referencesForeignUid), $fileObjects);
-                               }
-                       }
+                       $this->handleFileReferences($conf, (array)$this->cObj->data, $fileObjects);
                }
                if ($conf['files'] || $conf['files.']) {
                        /*
@@ -281,6 +269,66 @@ class FilesContentObject extends \TYPO3\CMS\Frontend\ContentObject\AbstractConte
        }
 
        /**
+        * Handles and resolves file references.
+        *
+        * @param array $configuration TypoScript configuration
+        * @param array $element The parent element referencing to files
+        * @param array $fileObjects Collection of file objects
+        * @return void
+        */
+       protected function handleFileReferences(array $configuration, array $element, array &$fileObjects) {
+               if (empty($configuration['references.'])) {
+                       return;
+               }
+
+               // It's important that this always stays "fieldName" and not be renamed to "field" as it would otherwise collide with the stdWrap key of that name
+               $referencesFieldName = $this->cObj->stdWrapValue('fieldName', $configuration['references.']);
+
+               // If no reference fieldName is set, there's nothing to do
+               if (empty($referencesFieldName)) {
+                       return;
+               }
+
+               $currentId = !empty($element['uid']) ? $element['uid'] : 0;
+               $tableName = $this->cObj->getCurrentTable();
+
+               // Fetch the references of the default element
+               $referencesForeignTable = $this->cObj->stdWrapValue('table', $configuration['references.'], $tableName);
+               $referencesForeignUid = $this->cObj->stdWrapValue('uid', $configuration['references.'], $currentId);
+
+               $pageRepository = $this->getPageRepository();
+               // Fetch element if definition has been modified via TypoScript
+               if ($referencesForeignTable !== $tableName || $referencesForeignUid !== $currentId) {
+                       $element = $pageRepository->getRawRecord(
+                               $referencesForeignTable,
+                               $referencesForeignUid,
+                               '*',
+                               FALSE
+                       );
+
+                       $pageRepository->versionOL($referencesForeignTable, $element, TRUE);
+                       if ($referencesForeignTable === 'pages') {
+                               $element = $pageRepository->getPageOverlay($element);
+                       } else {
+                               $element = $pageRepository->getRecordOverlay(
+                                       $referencesForeignTable,
+                                       $element,
+                                       $GLOBALS['TSFE']->sys_language_content,
+                                       $GLOBALS['TSFE']->sys_language_contentOL
+                               );
+                       }
+               }
+
+               $references = $pageRepository->getFileReferences(
+                       $referencesForeignTable,
+                       $referencesFieldName,
+                       $element
+               );
+
+               $this->addToArray($references, $fileObjects);
+       }
+
+       /**
         * Adds $newItems to $theArray, which is passed by reference. Array must only consist of numerical keys.
         *
         * @param mixed $newItems Array with new items or single object that's added.
@@ -307,4 +355,11 @@ class FilesContentObject extends \TYPO3\CMS\Frontend\ContentObject\AbstractConte
                return $this->cObj->stdWrapValue($key, $config, $defaultValue);
        }
 
+       /**
+        * @return \TYPO3\CMS\Frontend\Page\PageRepository
+        */
+       protected function getPageRepository() {
+               return $GLOBALS['TSFE']->sys_page;
+       }
+
 }
index 76d8559..55d1b01 100644 (file)
@@ -1360,6 +1360,48 @@ class PageRepository {
        }
 
        /**
+        * Gets file references for a given record field.
+        *
+        * @param string $tableName Name of the table
+        * @param string $fieldName Name of the field
+        * @param array $element The parent element referencing to files
+        * @return array
+        */
+       public function getFileReferences($tableName, $fieldName, array $element) {
+               /** @var $fileRepository \TYPO3\CMS\Core\Resource\FileRepository */
+               $fileRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\FileRepository');
+               $currentId = !empty($element['uid']) ? $element['uid'] : 0;
+
+               // Fetch the references of the default element
+               $references = $fileRepository->findByRelation($tableName, $fieldName, $currentId);
+
+               $localizedId = NULL;
+               if (isset($element['_LOCALIZED_UID'])) {
+                       $localizedId = $element['_LOCALIZED_UID'];
+               } elseif (isset($element['_PAGES_OVERLAY_UID'])) {
+                       $localizedId = $element['_PAGES_OVERLAY_UID'];
+               }
+
+               if (!empty($GLOBALS['TCA'][$tableName]['ctrl']['transForeignTable'])) {
+                       $tableName = $GLOBALS['TCA'][$tableName]['ctrl']['transForeignTable'];
+               }
+
+               $isTableLocalizable = (
+                       !empty($GLOBALS['TCA'][$tableName]['ctrl']['languageField'])
+                       && !empty($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])
+               );
+               if ($isTableLocalizable && $localizedId !== NULL) {
+                       $localizedReferences = $fileRepository->findByRelation($tableName, $fieldName, $localizedId);
+                       $localizedReferencesValue = $localizedReferences ?: '';
+                       if ($this->shouldFieldBeOverlaid($tableName, $fieldName, $localizedReferencesValue)) {
+                               $references = $localizedReferences;
+                       }
+               }
+
+               return $references;
+       }
+
+       /**
         * Determine if a field needs an overlay
         *
         * @param string $table TCA tablename