Migration: list_type plugins to CType

Deprecated since version 13.4

The plugin content element (list) and the plugin sub types field (list_type) have been marked as deprecated in TYPO3 v13.4 and will be removed in TYPO3 v14.0.

Several steps are important in the migration from list_type plugins to CType plugins:

  • Register plugins using the CType record type
  • Create update wizard which extends \TYPO3\CMS\Install\Updates\AbstractListTypeToCTypeUpdate and add list_type to CType mapping for each plugin to migrate.
  • Migrate possible FlexForm registration and add dedicated showitem TCA configuration
  • Migrate possible PreviewRenderer registration in TCA
  • Adapt possible content element wizard items in page TSconfig, where list_type is used
  • Adapt possible content element restrictions in backend layouts or container elements defined by third-party extensions like EXT:content_defender

Migration example: Extbase plugin

1. Adjust the Extbase plugin configuration

Extbase plugins are usually registered using the utility method \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin() in file EXT:my_extension/ext_localconf.php.

Add value ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT as fifth parameter, $pluginType, to the method ExtensionUtility::configurePlugin():

EXT:examples/ext_localconf.php (difference)
 use T3docs\Examples\Controller\FalExampleController;
 use TYPO3\CMS\Extbase\Utility\ExtensionUtility;

 ExtensionUtility::configurePlugin(
     'Examples',
     'HtmlParser',
     [
         HtmlParserController::class => 'index',
     ],
+    [],
+    ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT,
 );
Copied!

If the fourth parameter, $nonCacheableControllerActions was missing you can set it to an empty array, the default value.

It is theoretically possible that the extension author did not use this utility method. In that case you have to change the TypoScript used to display your plugin manually. This step is similar to adjusting the TypoScript of a Core-based plugin.

2. Adjust the registration of FlexForms and additional fields

EXT:examples/Configuration/TCA/Overrides/tt_content.php (difference)
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Extbase\Utility\ExtensionUtility;

 $extensionKey = 'Examples';
 $pluginName = 'HtmlParser';
 $pluginTitle = 'LLL:EXT:examples/Resources/Private/Language/locallang.xlf:htmlparser_plugin_title';

 // Register the HTML Parser plugin
 $pluginSignature = ExtensionUtility::registerPlugin(
     $extensionKey,
     $pluginName,
     $pluginTitle,
 );

-$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_excludelist'][$pluginSignature]
-    = 'layout,select_key,pages';
-$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist'][$pluginSignature]
-    = 'pi_flexform';
-
-ExtensionManagementUtility::addPiFlexFormValue(
-    $pluginSignature,
-    'FILE:EXT:examples/Configuration/Flexforms/HtmlParser.xml',
-);

+ExtensionManagementUtility::addToAllTCAtypes(
+    'tt_content',
+    '--div--;Configuration,pi_flexform,',
+    $pluginSignature,
+    'after:subheader',
+);
+
+ExtensionManagementUtility::addPiFlexFormValue(
+    '*',
+    'FILE:EXT:examples/Configuration/Flexforms/HtmlParser.xml',
+    $pluginSignature,
+);
Copied!

The CType based plugin does not inherit the default fields provided by the TCA of the content element "List". These where in many cases removed by using subtypes_excludelist.

As these fields are not displayed automatically anymore you can remove this definition without replacement: Line 15 in the diff. If they have not been removed and are still needed, you will need to manually add them to your plugin type.

The subtypes_addlist was used to display the field containing the FlexForm, an possibly other fields in the list_type plugin. We remove this definition (Line 17) and replace it by using the utility method \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes() (Line 25-30).

The utility method ExtensionManagementUtility::addPiFlexFormValue() needs to be changed from using the first parameter for the $pluginSignature to using the third parameter. The first parameter requires a certain list_type setting it to the wildcard * allows all list types. The third parameter limits it to the CType.

3. Provide an upgrade wizard

New in version 13.4

You can extend class AbstractListTypeToCTypeUpdate to provide a custom upgrade wizard that moves existing plugins from the list_type definition to the CType definition. The resulting upgrade wizard will even adjust backend user permissions for the defined plugins:

Class T3docs\Examples\Upgrades\ExtbasePluginListTypeToCTypeUpdate
final class ExtbasePluginListTypeToCTypeUpdate extends AbstractListTypeToCTypeUpdate
{

}
Copied!

4. Search your code and replace any mentioning of list_type

Search your code. If you used the list_type of you plugin in any custom database statement or referred to the according

Search your TCA definitions for any use of the now outdated configuration options

Migration example: Core-based plugin

1. Adjust the plugin registration

EXT:my_extension/Configuration/TCA/tt_content.php (diff)
 $pluginSignature = 'examples_pi1';
 $pluginTitle = 'LLL:EXT:examples/Resources/Private/Language/locallang_db.xlf:tt_content.examples_pi1.title';
 $extensionKey = 'examples';
 $flexFormPath = 'FILE:EXT:examples/Configuration/Flexforms/flexform_ds1.xml';

 // Add the plugins to the list of plugins
 ExtensionManagementUtility::addPlugin(
     [$pluginTitle, $pluginSignature, '', 'plugin'],
-    'list_type',
-    $extensionKey,
 );

-// Disable the display of layout and select_key fields for the plugin
-$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_excludelist'][$pluginSignature]
-    = 'layout,select_key,pages';
-
-// Activate the display of the plug-in flexform field and set FlexForm definition
-$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist'][$pluginSignature] = 'pi_flexform';

+// Activate the display of the FlexForm field
+ExtensionManagementUtility::addToAllTCAtypes(
+    'tt_content',
+    '--div--;Configuration,pi_flexform,',
+    $pluginSignature,
+    'after:subheader',
+);

 ExtensionManagementUtility::addPiFlexFormValue(
-    $pluginSignature,
+    '*',
     $flexFormPath,
+    $pluginSignature,
 );
Copied!

2. Adjust the TypoScript of the plugin

If your plugin was rendered using typo3/cms-fluid-styled-content you are probably using the top level TypoScript object tt_content to render the plugin. The path to the plugin rendering needs to be adjusted as you cannot use the deprecated content element "list" anymore:

EXT:my_extension/Configuration/Sets/MyPluginSet/setup.typoscript (diff)
-tt_content.list.20.examples_pi1 = USER
-tt_content.list.20.examples_pi1 {
+tt_content.examples_pi1 = USER
+tt_content.examples_pi1 {
     userFunc = MyVendor\Examples\Controller\ExampleController->example
     settings {
         singlePid = 42
         listPid = 55
     }
     view {
         templateRootPath = {$templateRootPath}
         partialRootPath = {$partialRootPath}
         layoutRootPath = {$layoutRootPath}
     }
 }

 # Or if you used the plugin top level object:

-tt_content.list.20.examples_pi1 < plugin.tx_examples_pi1
+tt_content.examples_pi1 < plugin.tx_examples_pi1
Copied!

3. Provide an upgrade wizard for automatic content migration for TYPO3 v13.4 and v12.4

If your extension only supports TYPO3 v13 and above you can extend the Core class \TYPO3\CMS\Install\Updates\AbstractListTypeToCTypeUpdate .

If your extension also supports TYPO3 v12 and maybe even TYPO3 v11 you can use class \Linawolf\ListTypeMigration\Upgrades\AbstractListTypeToCTypeUpdate instead. Require via composer: linawolf/list-type-migration or copy the file into your extension using your own namespaces:

EXT:my_extension/Classes/Upgrades/PluginListTypeToCTypeUpdate.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Upgrades;

// composer req linawolf/list-type-migration
use Linawolf\ListTypeMigration\Upgrades\AbstractListTypeToCTypeUpdate;
use TYPO3\CMS\Install\Attribute\UpgradeWizard;

#[UpgradeWizard('myExtensionPluginListTypeToCTypeUpdate')]
final class PluginListTypeToCTypeUpdate extends AbstractListTypeToCTypeUpdate
{
    protected function getListTypeToCTypeMapping(): array
    {
        return [
            'my_extension_pi1' => 'my_extension_pi1',
            'my_extension_pi2' => 'my_extension_newpluginname',
        ];
    }

    public function getTitle(): string
    {
        return 'Migrates my_extension plugins';
    }

    public function getDescription(): string
    {
        return 'Migrates my_extension_pi1, my_extension_pi2  from list_type to CType. ';
    }
}
Copied!

If you also have to be compatible with TYPO3 v11, register the upgrade wizard manually: Registering wizards for TYPO3 v11.