[FEATURE] Allow re-initialization of tt_content categories 34/40834/12
authorAlexander Stehlik <alexander.stehlik@gmail.com>
Mon, 14 Sep 2015 14:36:20 +0000 (16:36 +0200)
committerBenni Mack <benni@typo3.org>
Tue, 15 Sep 2015 19:05:03 +0000 (21:05 +0200)
The categories field for the tt_content table is re-initialized in
the TCA overrides file of css_styled_content.

For this to work a new method is added to the category registry
that allows overriding an existing registry entry.

Resolves: #67875
Releases: master
Change-Id: I1a9ba30982216402d3fe8e2d3e48ed27a8807df2
Reviewed-on: http://review.typo3.org/40834
Reviewed-by: Nicole Cordes <typo3@cordes.co>
Tested-by: Nicole Cordes <typo3@cordes.co>
Reviewed-by: Daniel Goerz <ervaude@gmail.com>
Tested-by: Daniel Goerz <ervaude@gmail.com>
Reviewed-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Tested-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
typo3/sysext/core/Classes/Category/CategoryRegistry.php
typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php
typo3/sysext/core/Documentation/Changelog/master/Feature-67875-OverrideCategoryRegistryEntry.rst [new file with mode: 0644]
typo3/sysext/core/Tests/Unit/Category/CategoryRegistryTest.php
typo3/sysext/css_styled_content/Configuration/TCA/Overrides/tt_content.php

index 3bf2e2e..67ad67b 100644 (file)
@@ -75,11 +75,12 @@ class CategoryRegistry implements SingletonInterface {
         *              + position: insert position of the categories field
         *              + label: backend label of the categories field
         *              + fieldConfiguration: TCA field config array to override defaults
+        * @param bool $override If TRUE, any category configuration for the same table / field is removed before the new configuration is added
         * @return bool
         * @throws \InvalidArgumentException
         * @throws \RuntimeException
         */
-       public function add($extensionKey, $tableName, $fieldName = 'categories', array $options = array()) {
+       public function add($extensionKey, $tableName, $fieldName = 'categories', array $options = array(), $override = FALSE) {
                $didRegister = FALSE;
                if (empty($tableName) || !is_string($tableName)) {
                        throw new \InvalidArgumentException('No or invalid table name "' . $tableName . '" given.', 1369122038);
@@ -88,6 +89,10 @@ class CategoryRegistry implements SingletonInterface {
                        throw new \InvalidArgumentException('No or invalid extension key "' . $extensionKey . '" given.', 1397836158);
                }
 
+               if ($override) {
+                       $this->remove($tableName, $fieldName);
+               }
+
                if (!$this->isRegistered($tableName, $fieldName)) {
                        $this->registry[$tableName][$fieldName] = $options;
                        $this->extensions[$extensionKey][$tableName][$fieldName] = $fieldName;
@@ -277,7 +282,6 @@ class CategoryRegistry implements SingletonInterface {
 
                        // Makes the new "categories" field to be visible in TSFE.
                        ExtensionManagementUtility::addToAllTCAtypes($tableName, $fieldList, $typesList, $position);
-
                }
        }
 
@@ -291,9 +295,9 @@ class CategoryRegistry implements SingletonInterface {
         */
        protected function addCategoryTab($tableName, $fieldName) {
                $fieldList = '';
-               if (!in_array($tableName, $this->addedCategoryTabs)) {
+               if (!isset($this->addedCategoryTabs[$tableName])) {
                        $fieldList .= '--div--;LLL:EXT:lang/locallang_tca.xlf:sys_category.tabs.category, ';
-                       $this->addedCategoryTabs[] = $tableName;
+                       $this->addedCategoryTabs[$tableName] = $tableName;
                }
                $fieldList .= $fieldName;
                return $fieldList;
@@ -447,4 +451,31 @@ class CategoryRegistry implements SingletonInterface {
                return $GLOBALS['LANG'];
        }
 
+       /**
+        * Removes the given field in the given table from the registry if it is found.
+        *
+        * @param string $tableName The name of the table for which the registration should be removed.
+        * @param string $fieldName The name of the field for which the registration should be removed.
+        */
+       protected function remove($tableName, $fieldName) {
+               if (!$this->isRegistered($tableName, $fieldName)) {
+                       return;
+               }
+
+               unset($this->registry[$tableName][$fieldName]);
+
+               foreach ($this->extensions as $extensionKey => $tableFieldConfig) {
+                       foreach ($tableFieldConfig as $extTableName => $fieldNameArray) {
+                               if ($extTableName === $tableName && isset($fieldNameArray[$fieldName])) {
+                                       unset($this->extensions[$extensionKey][$tableName][$fieldName]);
+                                       break;
+                               }
+                       }
+               }
+
+               // If no more fields are configured we unregister the categories tab.
+               if (empty($this->registry[$tableName]) && isset($this->addedCategoryTabs[$tableName])) {
+                       unset($this->addedCategoryTabs[$tableName]);
+               }
+       }
 }
index 7a2f0b4..c82109f 100644 (file)
@@ -1994,12 +1994,13 @@ tt_content.' . $key . $suffix . ' {
         * @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
+        * @param bool $override If TRUE, any category configuration for the same table / field is removed before the new configuration is added
         * @see addTCAcolumns
         * @see addToAllTCAtypes
         */
-       static public function makeCategorizable($extensionKey, $tableName, $fieldName = 'categories', array $options = array()) {
+       static public function makeCategorizable($extensionKey, $tableName, $fieldName = 'categories', array $options = array(), $override = FALSE) {
                // Update the category registry
-               $result = CategoryRegistry::getInstance()->add($extensionKey, $tableName, $fieldName, $options);
+               $result = CategoryRegistry::getInstance()->add($extensionKey, $tableName, $fieldName, $options, $override);
                if ($result === FALSE) {
                        $message = CategoryRegistry::class . ': no category registered for table "%s". Key was already registered.';
                        /** @var $logger \TYPO3\CMS\Core\Log\Logger */
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-67875-OverrideCategoryRegistryEntry.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-67875-OverrideCategoryRegistryEntry.rst
new file mode 100644 (file)
index 0000000..e09bb36
--- /dev/null
@@ -0,0 +1,40 @@
+===================================================
+Feature: #67875 - Override CategoryRegistry entries
+===================================================
+
+Description
+===========
+
+The ``makeCategorizable`` method of the  ``\TYPO3\CMS\Core\Utility\ExtensionManagementUtility``
+class was extended with a new parameter ``override`` to set a new category configuration for
+an already registered table / field combination.
+
+If the parameter is set to true, previously defined registry entries are cleared for the
+current table / field combination before adding the new configuration.
+
+The intended usecase for this method is to add additional TCA types for a previously registered table.
+
+A good example is the ``tt_content`` table:
+
+1. The basic TCA is defined in the ``frontend`` Extension.
+2. After the processing of the normal TCA definition, the default categorized tables (from the install
+   tool setting ``SYS/defaultCategorizedTables``) are initialized and the categories tab is added to the
+   ``showitem`` configuration for all TCA types that exist so far.
+3. Now the TCA overrides are processed. The ``css_styled_content`` Extension defines additional TCA
+   types. After the types are defined the ``addOrOverride()`` method is called to add the category
+   tab to them.
+
+
+Impact
+======
+
+The current behavior of the existing functionality is not changed. Only new functionality is added.
+
+
+Example
+=======
+
+.. code-block:: php
+
+       // This example is from the tt_content TCA overrides file from the css_styled_content Extension.
+       \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::makeCategorizable('css_styled_content', 'tt_content', 'categories', array(), TRUE);
index 4992700..8598048 100644 (file)
@@ -260,7 +260,36 @@ class CategoryRegistryTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                                1, substr_count($typeConfig['showitem'], '--div--;LLL:EXT:lang/locallang_tca.xlf:sys_category.tabs.category')
                        );
                }
+       }
 
+       /**
+        * @test
+        */
+       public function addAllowsSettingOfTheSameTableFieldTwice() {
+               $this->subject->add('text_extension_a', $this->tables['first'], 'categories1');
+               $result = $this->subject->add('text_extension_a', $this->tables['first'], 'categories1', array(), TRUE);
+               $this->assertTrue($result);
        }
 
+       /**
+        * @test
+        */
+       public function addInitializesMissingTypes() {
+               $this->subject->add('text_extension_a', $this->tables['first'], 'categories1');
+               $GLOBALS['TCA'][$this->tables['first']]['types']['newtypeafterfirstadd'] = array('showitem' => '');
+               $this->subject->add('text_extension_a', $this->tables['first'], 'categories1', array(), TRUE);
+               $this->assertSame(
+                       1, substr_count($GLOBALS['TCA'][$this->tables['first']]['types']['newtypeafterfirstadd']['showitem'], '--div--;LLL:EXT:lang/locallang_tca.xlf:sys_category.tabs.category')
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function addAddsOnlyOneSqlString() {
+               $this->subject->add('text_extension_a', $this->tables['first'], 'categories1');
+               $this->subject->add('text_extension_b', $this->tables['first'], 'categories1', array(), TRUE);
+               $sqlData = $this->subject->addExtensionCategoryDatabaseSchemaToTablesDefinition(array(), 'text_extension_a');
+               $this->assertEmpty($sqlData['sqlString'][0]);
+       }
 }
index 0b823f2..ee7f2ab 100644 (file)
@@ -677,3 +677,5 @@ $GLOBALS['TCA']['tt_content']['columns']['section_frame']['config']['items'][9]
 
 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile('css_styled_content', 'static/', 'CSS Styled Content');
 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile('css_styled_content', 'static/v6.2/', 'CSS Styled Content TYPO3 v6.2');
+
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::makeCategorizable('css_styled_content', 'tt_content', 'categories', array(), TRUE);