[TASK] Improve method makeCategorizable to be used everywhere 12/12812/11
authorFabien Udriot <fabien.udriot@ecodev.ch>
Sun, 15 Jul 2012 23:25:22 +0000 (01:25 +0200)
committerPhilipp Gampe <philipp.gampe@typo3.org>
Mon, 13 May 2013 22:18:32 +0000 (00:18 +0200)
Method makeCategorizable registers a table to be categorizable in the
BE. The current implementation has the drawback to force the call of this
method after the TCA of the table. If called before, the "categorization"
wouldn't be applied because of timing issue. The patch improve the
situation by postponing the application of the TCA responsible for
categorization.

For more details about the method refer to
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::makeCategorizable.

Change-Id: I966cc65e50e0d6a81cfafb1238f253ed802349c6
Resolves: #38972
Releases: 6.2, 6.1
Reviewed-on: https://review.typo3.org/12812
Reviewed-by: Francois Suter
Tested-by: Francois Suter
Reviewed-by: Fabien Udriot
Tested-by: Fabien Udriot
Reviewed-by: Philipp Gampe
Tested-by: Philipp Gampe
typo3/sysext/core/Classes/Category/CategoryRegistry.php
typo3/sysext/core/Classes/Core/Bootstrap.php
typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php
typo3/sysext/core/Tests/Unit/Category/CategoryRegistryTest.php
typo3/sysext/core/Tests/Unit/Utility/ExtensionMangementUtilityTest.php

index 09ac41c..d710e2f 100644 (file)
@@ -66,15 +66,22 @@ class CategoryRegistry implements \TYPO3\CMS\Core\SingletonInterface {
         * @param string $extensionKey Extension key to be used
         * @param string $tableName Name of the table to be registered
         * @param string $fieldName Name of the field to be registered
-        * @return boolean Whether fieldName of tableName is registered
+        * @param array $options Additional configuration options
+        *              + fieldList: field configuration to be added to showitems
+        *              + typesList: list of types that shall visualize the categories field
+        *              + position: insert position of the categories field
+        *              + fieldConfiguration: TCA field config array to override defaults
+        * @return bool
         */
-       public function add($extensionKey, $tableName, $fieldName) {
+       public function add($extensionKey, $tableName, $fieldName = 'categories', $options = array()) {
                $result = FALSE;
-               // Makes sure there is an existing table configuration and nothing registered yet:
-               if (!empty($GLOBALS['TCA'][$tableName])) {
-                       if (!$this->isRegistered($tableName, $fieldName)) {
-                               $this->registry[$extensionKey][$tableName] = $fieldName;
-                       }
+
+                       // Makes sure there is an existing table configuration and nothing registered yet:
+               if (!$this->isRegistered($tableName, $fieldName)) {
+                       $this->registry[$extensionKey][$tableName] = array (
+                               'fieldName' => $fieldName,
+                               'options' => $options,
+                       );
                        $result = TRUE;
                }
                return $result;
@@ -99,16 +106,31 @@ class CategoryRegistry implements \TYPO3\CMS\Core\SingletonInterface {
        }
 
        /**
+        * Gets all categorized tables
+        *
+        * @return array
+        */
+       public function getCategorizedTables() {
+               $categorizedTables = array();
+
+               foreach ($this->registry as $registry) {
+                       $categorizedTables = array_merge($categorizedTables, array_keys($registry));
+               }
+
+               return $categorizedTables;
+       }
+
+       /**
         * Tells whether a table has a category configuration in the registry.
         *
         * @param string $tableName Name of the table to be looked up
         * @param string $fieldName Name of the field to be looked up
         * @return boolean
         */
-       public function isRegistered($tableName, $fieldName) {
+       public function isRegistered($tableName, $fieldName = 'categories') {
                $isRegistered = FALSE;
                foreach ($this->registry as $configuration) {
-                       if (!empty($configuration[$tableName]) && $configuration[$tableName] === $fieldName) {
+                       if (!empty($configuration[$tableName]['fieldName']) && $configuration[$tableName]['fieldName'] === $fieldName) {
                                $isRegistered = TRUE;
                                break;
                        }
@@ -140,13 +162,159 @@ class CategoryRegistry implements \TYPO3\CMS\Core\SingletonInterface {
                        return '';
                }
                $sql = '';
-               foreach ($this->registry[$extensionKey] as $tableName => $fieldName) {
-                       $sql .= sprintf($this->template, $tableName, $fieldName);
+
+               foreach ($this->registry[$extensionKey] as $tableName => $tableInfo) {
+                       $sql .= sprintf($this->template, $tableName, $tableInfo['fieldName']);
                }
                return $sql;
        }
 
-}
+       /**
+        * Apply TCA to all registered tables
+        *
+        * @return void
+        */
+       public function applyTca() {
+
+               $this->registerDefaultCategorizedTables();
+
+               foreach ($this->registry as $registry) {
+                       foreach ($registry as $tableName => $tableInfo) {
+                               $this->addTcaColumn($tableName, $tableInfo['fieldName'], $tableInfo['options']);
+                               $this->addToAllTCAtypes($tableName, $tableInfo['fieldName'], $tableInfo['options']);
+                       }
+               }
+       }
+
+       /**
+        * Add default categorized tables to the registry
+        *
+        * @return void
+        */
+       protected function registerDefaultCategorizedTables() {
+
+               $defaultCategorizedTables = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['SYS']['defaultCategorizedTables']);
+               foreach ($defaultCategorizedTables as $defaultCategorizedTable) {
+                       if (!$this->isRegistered($defaultCategorizedTable)) {
+                               $this->add('core', $defaultCategorizedTable, 'categories');
+                       }
+               }
+       }
+
+       /**
+        * Add a new field into the TCA types -> showitem
+        *
+        * @param string $tableName Name of the table to be categorized
+        * @param string $fieldName Name of the field to be used to store categories
+        * @param array $options Additional configuration options
+        *              + fieldList: field configuration to be added to showitems
+        *              + typesList: list of types that shall visualize the categories field
+        *              + position: insert position of the categories field
+        * @return void
+        */
+       protected function addToAllTCAtypes($tableName, $fieldName, $options) {
+
+               // Makes sure to add more TCA to an existing structure
+               if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
+
+                       $fieldList = '--div--;LLL:EXT:lang/locallang_tca.xlf:sys_category.tabs.category, ' . $fieldName;
+                       if (!empty($options['fieldList'])) {
+                               $fieldList = $options['fieldList'];
+                       }
+
+                       $typesList = '';
+                       if (!empty($options['typesList'])) {
+                               $typesList = $options['typesList'];
+                       }
+
+                       $position = '';
+                       if (!empty($options['position'])) {
+                               $position = $options['position'];
+                       }
+
+                       // Makes the new "categories" field to be visible in TSFE.
+                       \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes($tableName, $fieldList, $typesList, $position);
+
+               }
+       }
+
+       /**
+        * Add a new TCA Column
+        *
+        * @param string $tableName Name of the table to be categorized
+        * @param string $fieldName Name of the field to be used to store categories
+        * @param array $options Additional configuration options
+        *              + fieldConfiguration: TCA field config array to override defaults
+        * @return void
+        */
+       protected function addTcaColumn($tableName, $fieldName, $options) {
+
+               // Makes sure to add more TCA to an existing structure
+               if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
 
+                       // Forges a new field, default name is "categories"
+                       $fieldConfiguration = array(
+                               'type' => 'select',
+                               'foreign_table' => 'sys_category',
+                               'foreign_table_where' => ' ORDER BY sys_category.title ASC',
+                               'MM' => 'sys_category_record_mm',
+                               'MM_opposite_field' => 'items',
+                               'MM_match_fields' => array('tablenames' => $tableName),
+                               'size' => 10,
+                               'autoSizeMax' => 50,
+                               'maxitems' => 9999,
+                               'renderMode' => 'tree',
+                               'treeConfig' => array(
+                                       'parentField' => 'parent',
+                                       'appearance' => array(
+                                               'expandAll' => TRUE,
+                                               'showHeader' => TRUE,
+                                       ),
+                               ),
+                               'wizards' => array(
+                                       '_PADDING' => 1,
+                                       '_VERTICAL' => 1,
+                                       'edit' => array(
+                                               'type' => 'popup',
+                                               'title' => 'Edit',
+                                               'script' => 'wizard_edit.php',
+                                               'icon' => 'edit2.gif',
+                                               'popup_onlyOpenIfSelected' => 1,
+                                               'JSopenParams' => 'height=350,width=580,status=0,menubar=0,scrollbars=1',
+                                       ),
+                                       'add' => Array(
+                                               'type' => 'script',
+                                               'title' => 'Create new',
+                                               'icon' => 'add.gif',
+                                               'params' => array(
+                                                       'table' => 'sys_category',
+                                                       'pid' => '###CURRENT_PID###',
+                                                       'setValue' => 'prepend'
+                                               ),
+                                               'script' => 'wizard_add.php',
+                                       ),
+                               ),
+                       );
+
+                       if (!empty($options['fieldConfiguration'])) {
+                               $fieldConfiguration = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule(
+                                       $fieldConfiguration,
+                                       $options['fieldConfiguration']
+                               );
+                       }
+
+                       $columns = array(
+                               $fieldName => array(
+                                       'exclude' => 0,
+                                       'label' => 'LLL:EXT:lang/locallang_tca.xlf:sys_category.categories',
+                                       'config' => $fieldConfiguration,
+                               ),
+                       );
+
+                       // Adding fields to an existing table definition
+                       \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns($tableName, $columns);
+               }
+       }
+}
 
 ?>
\ No newline at end of file
index 7bf89e7..7d59ce5 100644 (file)
@@ -894,6 +894,9 @@ class Bootstrap {
                if (file_exists($extTablesFile) && is_file($extTablesFile)) {
                        include $extTablesFile;
                }
+
+               // Apply TCA onto tables to be categorized
+               \TYPO3\CMS\Core\Category\CategoryRegistry::getInstance()->applyTca();
        }
 
        /**
@@ -1050,4 +1053,4 @@ class Bootstrap {
 }
 
 
-?>
\ No newline at end of file
+?>
index d66069f..e5eb01d 100644 (file)
@@ -1959,10 +1959,10 @@ tt_content.' . $key . $prefix . ' {
        }
 
        /**
-        * Makes a table categorizable by extending its TCA.
+        * Makes a table categorizable by adding value into the category registry.
         *
         * @param string $extensionKey Extension key to be used
-        * @param string $tableName Name of the table to be categoriezed
+        * @param string $tableName Name of the table to be categorized
         * @param string $fieldName Name of the field to be used to store categories
         * @param array $options Additional configuration options
         * @see addTCAcolumns
@@ -1970,82 +1970,14 @@ tt_content.' . $key . $prefix . ' {
         */
        static public function makeCategorizable($extensionKey, $tableName, $fieldName = 'categories', array $options = array()) {
                // Update the category registry
-               $result = \TYPO3\CMS\Core\Category\CategoryRegistry::getInstance()->add($extensionKey, $tableName, $fieldName);
+               $result = \TYPO3\CMS\Core\Category\CategoryRegistry::getInstance()->add($extensionKey, $tableName, $fieldName, $options);
                if ($result === FALSE) {
-                       $message = '\TYPO3\CMS\Core\Category\CategoryRegistry: no category registered for table "%s". Double check if there is a TCA configured';
-                       \TYPO3\CMS\Core\Utility\GeneralUtility::devLog(sprintf($message, $tableName), 'Core', 2);
-               }
-               // Makes sure to add more TCA to an existing structure
-               if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
-                       // Forges a new field, default name is "categories"
-                       $fieldConfiguration = array(
-                               'type' => 'select',
-                               'foreign_table' => 'sys_category',
-                               'foreign_table_where' => ' ORDER BY sys_category.title ASC',
-                               'MM' => 'sys_category_record_mm',
-                               'MM_opposite_field' => 'items',
-                               'MM_match_fields' => array('tablenames' => $tableName),
-                               'size' => 10,
-                               'autoSizeMax' => 50,
-                               'maxitems' => 9999,
-                               'renderMode' => 'tree',
-                               'treeConfig' => array(
-                                       'parentField' => 'parent',
-                                       'appearance' => array(
-                                               'expandAll' => TRUE,
-                                               'showHeader' => TRUE
-                                       )
-                               ),
-                               'wizards' => array(
-                                       '_PADDING' => 1,
-                                       '_VERTICAL' => 1,
-                                       'edit' => array(
-                                               'type' => 'popup',
-                                               'title' => 'Edit',
-                                               'script' => 'wizard_edit.php',
-                                               'icon' => 'edit2.gif',
-                                               'popup_onlyOpenIfSelected' => 1,
-                                               'JSopenParams' => 'height=350,width=580,status=0,menubar=0,scrollbars=1'
-                                       ),
-                                       'add' => array(
-                                               'type' => 'script',
-                                               'title' => 'Create new',
-                                               'icon' => 'add.gif',
-                                               'params' => array(
-                                                       'table' => 'sys_category',
-                                                       'pid' => '###CURRENT_PID###',
-                                                       'setValue' => 'prepend'
-                                               ),
-                                               'script' => 'wizard_add.php'
-                                       )
-                               )
+                       $message = '\TYPO3\CMS\Core\Category\CategoryRegistry: no category registered for table "%s". Key was already registered.';
+                       /** @var $logger \TYPO3\CMS\Core\Log\Logger */
+                       $logger = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger(__CLASS__);
+                       $logger->warning(
+                               sprintf($message, $tableName)
                        );
-                       if (!empty($options['fieldConfiguration'])) {
-                               $fieldConfiguration = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule($fieldConfiguration, $options['fieldConfiguration']);
-                       }
-                       $columns = array(
-                               $fieldName => array(
-                                       'exclude' => 0,
-                                       'label' => 'LLL:EXT:lang/locallang_tca.xlf:sys_category.categories',
-                                       'config' => $fieldConfiguration
-                               )
-                       );
-                       // Adding fields to an existing table definition
-                       self::addTCAcolumns($tableName, $columns);
-                       $fieldList = '--div--;LLL:EXT:lang/locallang_tca.xlf:sys_category.tabs.category, ' . $fieldName;
-                       if (!empty($options['fieldList'])) {
-                               $fieldList = $options['fieldList'];
-                       }
-                       $typesList = '';
-                       if (!empty($options['typesList'])) {
-                               $typesList = $options['typesList'];
-                       }
-                       $position = '';
-                       if (!empty($options['position'])) {
-                               $position = $options['position'];
-                       }
-                       // Makes the new "categories" field to be visible in TSFE.
-                       self::addToAllTCAtypes($tableName, $fieldList, $typesList, $position);
                }
        }
 
index dac5f40..0f248ee 100644 (file)
@@ -28,6 +28,7 @@ namespace TYPO3\CMS\Core\Tests\Unit\Category;
  * Testcase for CategoryRegistry
  *
  * @author Oliver Hader <oliver.hader@typo3.org>
+ * @author Fabien Udriot <fabien.udriot@typo3.org>
  */
 class CategoryRegistryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
@@ -51,7 +52,7 @@ class CategoryRegistryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                        'second' => uniqid('second')
                );
                foreach ($this->tables as $tableName) {
-                       $GLOBALS['TCA'][$tableName] = array('ctrl' => array());
+                       $GLOBALS['TCA'][$tableName] = array('ctrl' => array(), 'columns' => array());
                }
        }
 
@@ -81,7 +82,11 @@ class CategoryRegistryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * @test
         */
        public function doesAddReturnFalseOnUndefinedTable() {
-               $this->assertFalse($this->fixture->add('test_extension_a', uniqid('undefined'), 'categories'));
+               $this->fixture->add('test_extension_a', $this->tables['first'], 'categories');
+
+               $this->assertFalse(
+                       $this->fixture->add('test_extension_a', $this->tables['first'], 'categories')
+               );
        }
 
        /**
@@ -92,8 +97,16 @@ class CategoryRegistryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                $this->fixture->add('test_extension_b', $this->tables['second'], 'categories');
                $registry = $this->fixture->get();
                ob_flush();
-               $this->assertEquals('categories', $registry['test_extension_a'][$this->tables['first']]);
-               $this->assertEquals('categories', $registry['test_extension_b'][$this->tables['second']]);
+
+               $this->assertEquals(
+                       'categories',
+                       $registry['test_extension_a'][$this->tables['first']]['fieldName']
+               );
+
+               $this->assertEquals(
+                       'categories',
+                       $registry['test_extension_b'][$this->tables['second']]['fieldName']
+               );
        }
 
        /**
@@ -103,8 +116,16 @@ class CategoryRegistryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                $this->fixture->add('test_extension_a', $this->tables['first'], 'categories');
                $this->fixture->add('test_extension_b', $this->tables['second'], 'categories');
                $registry = $this->fixture->get();
-               $this->assertEquals('categories', $registry['test_extension_a'][$this->tables['first']]);
-               $this->assertEquals('categories', $registry['test_extension_b'][$this->tables['second']]);
+
+               $this->assertEquals(
+                       'categories',
+                       $registry['test_extension_a'][$this->tables['first']]['fieldName']
+               );
+
+               $this->assertEquals(
+                       'categories',
+                       $registry['test_extension_b'][$this->tables['second']]['fieldName']
+               );
        }
 
        /**
@@ -114,7 +135,11 @@ class CategoryRegistryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                $this->fixture->add('test_extension_a', $this->tables['first'], $this->tables['first']);
                $this->fixture->add('test_extension_b', $this->tables['second'], $this->tables['second']);
                $registry = $this->fixture->get();
-               $this->assertEquals($this->tables['first'], $registry['test_extension_a'][$this->tables['first']]);
+
+               $this->assertEquals(
+                       $this->tables['first'],
+                       $registry['test_extension_a'][$this->tables['first']]['fieldName']
+               );
        }
 
        /**
@@ -148,6 +173,29 @@ class CategoryRegistryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                $this->assertEquals($matches[2][0], 'categories');
        }
 
+       /**
+        * @test
+        */
+       public function areDefaultCategorizedTabledLoaded() {
+               $GLOBALS['TYPO3_CONF_VARS']['SYS']['defaultCategorizedTables'] = $this->tables['first'] . ',' . $this->tables['second'];
+               $this->fixture->applyTca();
+
+               $registry = $this->fixture->get();
+               $this->assertCount(2, $registry['core']);
+               $this->assertSame(key($registry['core']), $this->tables['first']);
+       }
+
+       /**
+        * @test
+        */
+       public function canApplyTca() {
+               $this->fixture->add('test_extension_a', $this->tables['first'], 'categories');
+               $this->fixture->add('test_extension_b', $this->tables['second'], 'categories');
+               $this->fixture->applyTca();
+               foreach ($this->tables as $table) {
+                       $this->assertNotEmpty($GLOBALS['TCA'][$table]['columns']['categories']);
+               }
+       }
 }
 
 ?>
\ No newline at end of file
index cb0d2d3..2d0e66e 100644 (file)
@@ -1416,10 +1416,10 @@ class ExtensionManagementUtilityTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
                        'ctrl' => array(),
                        'columns' => array()
                );
-               $registryMock = $this->getMock('TYPO3\\CMS\\Core\\Category\\CategoryRegistry', array('add'));
-               $registryMock->expects($this->once())->method('add')->with($extensionKey, $tableName, 'categories');
+               $registryMock = $this->getMock('TYPO3\\CMS\\Core\\Category\\CategoryRegistry', array('dummy'));
                \TYPO3\CMS\Core\Utility\GeneralUtility::setSingletonInstance('TYPO3\\CMS\\Core\\Category\\CategoryRegistry', $registryMock);
                \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::makeCategorizable($extensionKey, $tableName);
+               $registryMock->applyTca();
                $this->assertNotEmpty($GLOBALS['TCA'][$tableName]['columns']['categories']);
        }
 
@@ -1434,10 +1434,10 @@ class ExtensionManagementUtilityTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
                        'ctrl' => array(),
                        'columns' => array()
                );
-               $registryMock = $this->getMock('TYPO3\\CMS\\Core\\Category\\CategoryRegistry', array('add'));
-               $registryMock->expects($this->once())->method('add')->with($extensionKey, $tableName, $fieldName);
+               $registryMock = $this->getMock('TYPO3\\CMS\\Core\\Category\\CategoryRegistry', array('dummy'));
                \TYPO3\CMS\Core\Utility\GeneralUtility::setSingletonInstance('TYPO3\\CMS\\Core\\Category\\CategoryRegistry', $registryMock);
                \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::makeCategorizable($extensionKey, $tableName, $fieldName);
+               $registryMock->applyTca();
                $this->assertNotEmpty($GLOBALS['TCA'][$tableName]['columns'][$fieldName]);
        }