[BUGFIX] Fix readable output for type "group" and MM-tables 83/35483/4
authorGeorg Ringer <georg.ringer@gmail.com>
Mon, 8 Sep 2014 11:36:42 +0000 (13:36 +0200)
committerMarkus Klein <klein.t3@reelworx.at>
Mon, 13 Apr 2015 10:08:02 +0000 (12:08 +0200)
If a TCA field uses the type "group" and a MM-table, a wrong value is
displayed in the list view. This is due to missing support for MM-tables
for type "group". Only the type "select" has an implementation.

This patch adds the implementation for the group field.

Change-Id: Ia57b7468d493962fc9877f12b685f08eecb012ac
Resolves: #52126
Resolves: #57129
Releases: master, 6.2
Reviewed-on: http://review.typo3.org/35483
Reviewed-by: Xavier Perseguers <xavier@typo3.org>
Tested-by: Xavier Perseguers <xavier@typo3.org>
Reviewed-by: Markus Klein <klein.t3@reelworx.at>
Tested-by: Markus Klein <klein.t3@reelworx.at>
typo3/sysext/backend/Classes/Utility/BackendUtility.php
typo3/sysext/backend/Tests/Unit/Utility/BackendUtilityTest.php

index 1ced3a5..877e5c7 100644 (file)
@@ -15,6 +15,7 @@ namespace TYPO3\CMS\Backend\Utility;
  */
 
 use TYPO3\CMS\Backend\Utility\IconUtility;
+use TYPO3\CMS\Core\Database\RelationHandler;
 use TYPO3\CMS\Core\Messaging\FlashMessage;
 use TYPO3\CMS\Core\Resource\File;
 use TYPO3\CMS\Core\Resource\ProcessedFile;
@@ -1521,7 +1522,7 @@ class BackendUtility {
                }
 
                $fileReferences = array();
-               /** @var $relationHandler \TYPO3\CMS\Core\Database\RelationHandler */
+               /** @var $relationHandler RelationHandler */
                $relationHandler = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\RelationHandler');
                if ($workspaceId !== NULL) {
                        $relationHandler->setWorkspaceId($workspaceId);
@@ -2114,7 +2115,7 @@ class BackendUtility {
                                                                }
                                                                $MMfield = join(',', $MMfields);
                                                        }
-                                                       /** @var $dbGroup \TYPO3\CMS\Core\Database\RelationHandler */
+                                                       /** @var $dbGroup RelationHandler */
                                                        $dbGroup = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\RelationHandler');
                                                        $dbGroup->start($value, $theColConf['foreign_table'], $theColConf['MM'], $uid, $table, $theColConf);
                                                        $selectUids = $dbGroup->tableArray[$theColConf['foreign_table']];
@@ -2125,7 +2126,7 @@ class BackendUtility {
                                                                        // Keep sorting of $selectUids
                                                                        $mmlA[array_search($MMrow['uid'], $selectUids)] = $noRecordLookup ?
                                                                                $MMrow['uid'] :
-                                                                               self::getRecordTitle($theColConf['foreign_table'], $MMrow, FALSE, $forceResult);
+                                                                               static::getRecordTitle($theColConf['foreign_table'], $MMrow, FALSE, $forceResult);
                                                                }
                                                                $GLOBALS['TYPO3_DB']->sql_free_result($MMres);
                                                                if (!empty($mmlA)) {
@@ -2190,23 +2191,71 @@ class BackendUtility {
                                case 'group':
                                        // resolve the titles for DB records
                                        if ($theColConf['internal_type'] === 'db') {
-                                               $finalValues = array();
-                                               $relationTableName = $theColConf['allowed'];
-                                               $explodedValues = GeneralUtility::trimExplode(',', $value, TRUE);
+                                               if ($theColConf['MM']) {
+                                                       if ($uid) {
+                                                               // Display the title of MM related records in lists
+                                                               if ($noRecordLookup) {
+                                                                       $MMfield = $theColConf['foreign_table'] . '.uid';
+                                                               } else {
+                                                                       $MMfields = array($theColConf['foreign_table'] . '.' . $GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label']);
+                                                                       $altLabelFields = explode(',', $GLOBALS['TCA'][$theColConf['foreign_table']]['ctrl']['label_alt']);
+                                                                       foreach ($altLabelFields as $f) {
+                                                                               $f = trim($f);
+                                                                               if ($f !== '') {
+                                                                                       $MMfields[] = $theColConf['foreign_table'] . '.' . $f;
+                                                                               }
+                                                                       }
+                                                                       $MMfield = join(',', $MMfields);
+                                                               }
+                                                               /** @var $dbGroup RelationHandler */
+                                                               $dbGroup = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\RelationHandler');
+                                                               $dbGroup->start($value, $theColConf['foreign_table'], $theColConf['MM'], $uid, $table, $theColConf);
+                                                               $selectUids = $dbGroup->tableArray[$theColConf['foreign_table']];
+                                                               if (!empty($selectUids) && is_array($selectUids)) {
+                                                                       $MMres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+                                                                               'uid, ' . $MMfield,
+                                                                               $theColConf['foreign_table'],
+                                                                               'uid IN (' . implode(',', $selectUids) . ')' . static::deleteClause($theColConf['foreign_table'])
+                                                                       );
+                                                                       $mmlA = array();
+                                                                       while ($MMrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($MMres)) {
+                                                                               // Keep sorting of $selectUids
+                                                                               $mmlA[array_search($MMrow['uid'], $selectUids)] = $noRecordLookup
+                                                                                       ? $MMrow['uid']
+                                                                                       : static::getRecordTitle($theColConf['foreign_table'], $MMrow, FALSE, $forceResult);
+                                                                       }
+                                                                       $GLOBALS['TYPO3_DB']->sql_free_result($MMres);
+                                                                       if (!empty($mmlA)) {
+                                                                               ksort($mmlA);
+                                                                               $l = implode('; ', $mmlA);
+                                                                       } else {
+                                                                               $l = 'N/A';
+                                                                       }
+                                                               } else {
+                                                                       $l = 'N/A';
+                                                               }
+                                                       } else {
+                                                               $l = 'N/A';
+                                                       }
+                                               } else {
+                                                       $finalValues = array();
+                                                       $relationTableName = $theColConf['allowed'];
+                                                       $explodedValues = GeneralUtility::trimExplode(',', $value, TRUE);
 
-                                               foreach ($explodedValues as $explodedValue) {
+                                                       foreach ($explodedValues as $explodedValue) {
 
-                                                       if (MathUtility::canBeInterpretedAsInteger($explodedValue)) {
-                                                               $relationTableNameForField = $relationTableName;
-                                                       } else {
-                                                               list($relationTableNameForField, $explodedValue) = self::splitTable_Uid($explodedValue);
+                                                               if (MathUtility::canBeInterpretedAsInteger($explodedValue)) {
+                                                                       $relationTableNameForField = $relationTableName;
+                                                               } else {
+                                                                       list($relationTableNameForField, $explodedValue) = self::splitTable_Uid($explodedValue);
+                                                               }
+
+                                                               $relationRecord = static::getRecordWSOL($relationTableNameForField, $explodedValue);
+                                                               $finalValues[] = static::getRecordTitle($relationTableNameForField, $relationRecord);
                                                        }
 
-                                                       $relationRecord = static::getRecordWSOL($relationTableNameForField, $explodedValue);
-                                                       $finalValues[] = static::getRecordTitle($relationTableNameForField, $relationRecord);
+                                                       $l = implode(', ', $finalValues);
                                                }
-
-                                               $l = implode(', ', $finalValues);
                                        } else {
                                                $l = implode(', ', GeneralUtility::trimExplode(',', $value, TRUE));
                                        }
index c731945..ba1e9fe 100644 (file)
@@ -225,7 +225,7 @@ class BackendUtilityTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                        '      return array(\'title\' => \'Page 1\');' .
                        '    }' .
                        '    if ($called === 2) {' .
-                       '      return array(\'header\' => \'Content 2\');' .
+                       '      return array(\'header\' => \'Configuration 2\');' .
                        '    }' .
                        '  }' .
                        '  static public function getRecordTitle() {' .
@@ -235,29 +235,125 @@ class BackendUtilityTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                        '      return \'Page 1\';' .
                        '    }' .
                        '    if ($called === 2) {' .
-                       '      return \'Content 2\';' .
+                       '      return \'Configuration 2\';' .
                        '    }' .
                        '  }' .
                        '}'
                );
 
                $GLOBALS['TCA'] = array(
-                       'sys_category' => array(
+                       'index_config' => array(
                                'columns' => array(
-                                       'items' => array(
+                                       'indexcfgs' => array(
                                                'config' => array(
-                                                       'allowed' => '*',
+                                                       'type' => 'group',
                                                        'internal_type' => 'db',
+                                                       'allowed' => 'index_config,pages',
+                                                       'size' => 5,
+                                               ),
+                                       ),
+                               ),
+                       ),
+               );
+
+               $this->assertSame('Page 1, Configuration 2', $subject::getProcessedValue('index_config', 'indexcfgs', 'pages_1,index_config_2'));
+       }
+
+       /**
+        * @test
+        */
+       public function getProcessedValueForSelectWithMMRelation() {
+               $GLOBALS['TYPO3_DB'] = $this->getMock(\TYPO3\CMS\Core\Database\DatabaseConnection::class, array(), array(), '', FALSE);
+               $GLOBALS['TYPO3_DB']->expects($this->any())->method('fullQuoteStr')
+                       ->will($this->returnCallback(
+                               function($quoteStr, $table) {
+                                       return "'" . $quoteStr . "'";
+                               }
+                       ));
+               $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTquery')->will($this->returnValue(0));
+               $GLOBALS['TYPO3_DB']->expects($this->any())->method('sql_free_result');
+               $GLOBALS['TYPO3_DB']->expects($this->any())->method('sql_fetch_assoc')
+                       ->will($this->returnCallback(
+                               function($res) {
+                                       static $called = 0;
+                                       ++$called;
+                                       switch ($called) {
+                                               // SELECT * FROM sys_category_record_mm
+                                               case 1:
+                                                       return array(
+                                                               'uid_local' => 1,       // uid of a sys_category record
+                                                               'uid_foreign' => 1,     // uid of a pages record
+                                                       );
+                                               case 2:
+                                                       return array(
+                                                               'uid_local' => 2,       // uid of a sys_category record
+                                                               'uid_foreign' => 1,     // uid of a pages record
+                                                       );
+                                               case 3:
+                                                       return NULL;
+                                               // SELECT * FROM sys_catgory
+                                               case 4:
+                                                       return array(
+                                                               'uid' => 1,
+                                                               'title' => 'Category 1',
+                                                       );
+                                               case 5:
+                                                       return array(
+                                                               'uid' => 2,
+                                                               'title' => 'Category 2',
+                                                       );
+                                               case 6:
+                                                       return NULL;
+                                       }
+                               }
+                       ));
+
+               // Disable getRecordTitle dependency by returning stable results
+               /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Backend\Utility\BackendUtility $subject */
+               $className = $this->getUniqueId('BackendUtility');
+               $subject = __NAMESPACE__ . '\\' . $className;
+               eval(
+                       'namespace ' . __NAMESPACE__ . ';' .
+                       'class ' . $className . ' extends \\TYPO3\\CMS\\Backend\\Utility\\BackendUtility {' .
+                       '  static public function getRecordTitle($table, $row) {' .
+                       '    return $row["title"];' .
+                       '  }' .
+                       '}'
+               );
+
+               $GLOBALS['TCA'] = array(
+                       'pages' => array(
+                               'columns' => array(
+                                       'categories' => array(
+                                               'config' => array(
+                                                       'type' => 'select',
+                                                       'foreign_table' => 'sys_category',
                                                        'MM' => 'sys_category_record_mm',
-                                                       'size' => 10,
-                                                       'type' => 'group',
+                                                       'MM_match_fields' => array(
+                                                               'fieldname' => 'categories',
+                                                               'tablesnames' => 'pages',
+                                                       ),
+                                                       'MM_opposite_field' => 'items',
                                                ),
                                        ),
                                ),
                        ),
+                       'sys_category' => array(
+                               'columns' => array(
+                                       'items' => array(
+                                               'config' => array(
+                                                       'type' => 'group',
+                                                       'internal_type' => 'db',
+                                                       'allowed' => '*',
+                                                       'MM' => 'sys_category_record_mm',
+                                                       'MM_oppositeUsage' => array(),
+                                               )
+                                       )
+                               ),
+                       ),
                );
 
-               $this->assertSame('Page 1, Content 2', $subject::getProcessedValue('sys_category', 'items', 'pages_1,tt_content_2'));
+               $this->assertSame('Category 1; Category 2', $subject::getProcessedValue('pages', 'categories', '2', 0, FALSE, FALSE, 1));
        }
 
        /**