[BUGFIX] Fields of type group file are not properly indexed 10/27310/10
authorMarc Bastian Heinrichs <typo3@mbh-software.de>
Mon, 3 Feb 2014 22:52:43 +0000 (23:52 +0100)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Mon, 17 Mar 2014 20:43:35 +0000 (21:43 +0100)
If an record with a field of type "group", internal_type "file"
should be indexed in the ReferenceIndex an SQL error exception
gets thrown. So the relation to the file isn't represented in the
refindex. Thus those files are also missing in exports created
with system extension impexp.

This is caused by wrong array keys and incorrectly storing a file
relation as DB relation since merge of FAL.

Resolves: #56353
Resolves: #56352
Releases: 6.2, 6.1, 6.0
Change-Id: I78211efcb6bf3032811ef0b0e20ed7f98f9fa8fb
Reviewed-on: https://review.typo3.org/27310
Tested-by: Sebastian Fischer
Tested-by: Christian Zenker
Reviewed-by: Wouter Wolters
Reviewed-by: Anja Leichsenring
Tested-by: Anja Leichsenring
typo3/sysext/core/Classes/Database/ReferenceIndex.php

index 887d895..72e681c 100644 (file)
@@ -172,7 +172,7 @@ class ReferenceIndex {
                                                        $this->createEntryData_dbRels($table, $uid, $fieldname, '', $deleted, $dat['itemArray']);
                                                        break;
                                                case 'file_reference':
-
+                                                       // not used (see getRelations()), but fallback to file
                                                case 'file':
                                                        $this->createEntryData_fileRels($table, $uid, $fieldname, '', $deleted, $dat['newValueFiles']);
                                                        break;
@@ -295,6 +295,7 @@ class ReferenceIndex {
         * @param integer $uid UID of source record (where reference is located)
         * @param string $fieldname Fieldname of source record (where reference is located)
         * @param string $flexpointer Pointer to location inside flexform struc
+        * @param integer $deleted
         * @param array $keys Data array with soft reference keys
         * @return void
         * @todo Define visibility
@@ -311,7 +312,7 @@ class ReferenceIndex {
                                                                        $this->relations[] = $this->createEntryData($table, $uid, $fieldname, $flexpointer, $deleted, $tableName, $recordId, '', -1, $spKey, $subKey);
                                                                        break;
                                                                case 'file_reference':
-
+                                                                       // not used (see getRelations()), but fallback to file
                                                                case 'file':
                                                                        $this->relations[] = $this->createEntryData($table, $uid, $fieldname, $flexpointer, $deleted, '_FILE', 0, $el['subst']['relFileName'], -1, $spKey, $subKey);
                                                                        break;
@@ -352,19 +353,42 @@ class ReferenceIndex {
                        if (!in_array($field, $nonFields) && is_array($GLOBALS['TCA'][$table]['columns'][$field]) && (!$onlyField || $onlyField === $field)) {
                                $conf = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
                                // Add files
-                               if ($result = $this->getRelations_procFiles($value, $conf, $uid)) {
-                                       // Creates an entry for the field with all the files:
-                                       $outRow[$field] = array(
-                                               'type' => 'db',
-                                               'itemArray' => $result
-                                       );
+                               $resultsFromFiles = $this->getRelations_procFiles($value, $conf, $uid);
+                               if (!empty($resultsFromFiles)) {
+                                       // We have to fill different arrays here depending on the result.
+                                       // internal_type file is still a relation of type file and
+                                       // since http://forge.typo3.org/issues/49538 internal_type file_reference
+                                       // is a database relation to a sys_file record
+                                       $fileResultsFromFiles = array();
+                                       $dbResultsFromFiles = array();
+                                       foreach ($resultsFromFiles as $resultFromFiles) {
+                                               if (isset($resultFromFiles['table']) && $resultFromFiles['table'] === 'sys_file') {
+                                                       $dbResultsFromFiles[] = $resultFromFiles;
+                                               } else {
+                                                       // Creates an entry for the field with all the files:
+                                                       $fileResultsFromFiles[] = $resultFromFiles;
+                                               }
+                                       }
+                                       if (!empty($fileResultsFromFiles)) {
+                                               $outRow[$field] = array(
+                                                       'type' => 'file',
+                                                       'newValueFiles' => $fileResultsFromFiles
+                                               );
+                                       }
+                                       if (!empty($dbResultsFromFiles)) {
+                                               $outRow[$field] = array(
+                                                       'type' => 'db',
+                                                       'itemArray' => $dbResultsFromFiles
+                                               );
+                                       }
                                }
                                // Add DB:
-                               if ($result = $this->getRelations_procDB($value, $conf, $uid, $table, $field)) {
+                               $resultsFromDatabase = $this->getRelations_procDB($value, $conf, $uid, $table, $field);
+                               if (!empty($resultsFromDatabase)) {
                                        // Create an entry for the field with all DB relations:
                                        $outRow[$field] = array(
                                                'type' => 'db',
-                                               'itemArray' => $result
+                                               'itemArray' => $resultsFromDatabase
                                        );
                                }
                                // For "flex" fieldtypes we need to traverse the structure looking for file and db references of course!
@@ -469,7 +493,7 @@ class ReferenceIndex {
         * @param string $value Field value
         * @param array $conf Field configuration array of type "TCA/columns
         * @param integer $uid Field uid
-        * @return array If field type is OK it will return an array with the files inside. Else FALSE
+        * @return bool|array If field type is OK it will return an array with the files inside. Else FALSE
         * @todo Define visibility
         */
        public function getRelations_procFiles($value, $conf, $uid) {
@@ -507,8 +531,12 @@ class ReferenceIndex {
                                        try {
                                                $file = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->retrieveFileOrFolderObject($file);
                                                if ($file instanceof \TYPO3\CMS\Core\Resource\FileInterface) {
-                                                       $newValueFile['table'] = 'sys_file';
-                                                       $newValueFile['id'] = $file->getUid();
+                                                       // For setting this as sys_file relation later, the keys filename, ID and ID_absFile
+                                                       // have not to be included, because the are not evaluated for db relations.
+                                                       $newValueFile = array(
+                                                               'table' => 'sys_file',
+                                                               'id' => $file->getUid()
+                                                       );
                                                }
                                        } catch (\Exception $e) {
 
@@ -609,7 +637,7 @@ class ReferenceIndex {
                                                                        }
                                                                        break;
                                                                case 'file_reference':
-
+                                                                       // not used (see getRelations()), but fallback to file
                                                                case 'file':
                                                                        $error = $this->setReferenceValue_fileRels($refRec, $dat['newValueFiles'], $newValue, $dataArray);
                                                                        if ($error) {
@@ -923,4 +951,4 @@ class ReferenceIndex {
                return array($headerContent, $bodyContent, count($errors));
        }
 
-}
+}
\ No newline at end of file