Breaking: #96333 - Auto configuration of ContextMenu item providers

See forge#96333

Description

ContextMenu item providers, implementing \TYPO3\CMS\Backend\ContextMenu\ItemProviders\ProviderInterface are now automatically registered by adding the backend.contextmenu.itemprovider tag, if autoconfigure is enabled in Services.yaml. The new \TYPO3\CMS\Backend\ContextMenu\ItemProviders\ItemProvidersRegistry then automatically receives those services and registers them.

All Core item providers extend the AbstractProvider class, which is usually also used by extensions. Due to the auto configuration, the context information (table, record identifier and context) is no longer passed to the __construct(), but instead to the new setContext() method.

The setContext() method is therefore required for all item providers.

Impact

The registration via $GLOBALS['TYPO3_CONF_VARS']['BE']['ContextMenu']['ItemProviders'] isn't evaluated anymore.

The item providers are retrieved from the container and are no longer instantiated while passing context information as constructor arguments. The context information is now passed to setContext().

Affected Installations

All extensions, registering custom ContextMenu item providers.

All extensions, extending AbstractProvider and overwriting the __construct() method.

All extensions, not extending AbstractProvider, but implementing \TYPO3\CMS\Backend\ContextMenu\ItemProviders\ProviderInterface directly.

Migration

Remove $GLOBALS['TYPO3_CONF_VARS']['BE']['ContextMenu']['ItemProviders'] from your ext_localconf.php file. If autoconfigure is not enabled in your Configuration/Services.(yaml|php) file, manually configure your item providers with the backend.contextmenu.itemprovider tag.

If your item providers extend AbstractProvider and overwrite the __construct() method, adjust the signature like shown below:

// Before

class MyItemProvider extends AbstractProvider {

    public function __construct(string $table, string $identifier, string $context = '')
    {
        parent::__construct($table, $identifier, $context);

        // My custom code
    }
}

// After

class MyItemProvider extends AbstractProvider {

    public function __construct()
    {
        parent::__construct();

        // My custom code
    }
}
Copied!

In case you rely on the arguments, previously passed to __construct(), you can override the new setContext() method, which is executed prior to any other action like canHandle().

// Before

class MyItemProvider extends AbstractProvider {

    public function __construct(string $table, string $identifier, string $context = '')
    {
        parent::__construct($table, $identifier, $context);

        if ($table === 'my_table') {
            // Do something
        }
}

// After

class MyItemProvider extends AbstractProvider {

    public function setContext(string $table, string $identifier, string $context = ''): void
    {
        parent::setContext($table, $identifier, $context);

        if ($table === 'my_table') {
            // Do something
        }
    }
}
Copied!

In case your item provider does not extend AbstractProvider, but instead implements the \TYPO3\CMS\Backend\ContextMenu\ItemProviders\ProviderInterface directly, add the new setContext() to the item provider.