Deprecation: #107823 - ButtonBar, Menu, and MenuRegistry make* methods deprecated 

See forge#107823

Description 

The factory methods in \TYPO3\CMS\Backend\Template\Components\ButtonBar for creating button instances, in \TYPO3\CMS\Backend\Template\Components\Menu for creating menu item instances, and in \TYPO3\CMS\Backend\Template\Components\MenuRegistry for creating menu instances have been deprecated in favor of using the new \TYPO3\CMS\Backend\Template\Components\ComponentFactory class directly.

The following methods are now deprecated:

  • ButtonBar::makeGenericButton()
  • ButtonBar::makeInputButton()
  • ButtonBar::makeSplitButton()
  • ButtonBar::makeDropDownButton()
  • ButtonBar::makeLinkButton()
  • ButtonBar::makeFullyRenderedButton()
  • ButtonBar::makeShortcutButton()
  • ButtonBar::makeButton()
  • Menu::makeMenuItem()
  • MenuRegistry::makeMenu()

Impact 

Calling any of the deprecated make*() methods on ButtonBar , \Menu, or MenuRegistry will trigger a PHP deprecation notice.

The methods continue to work in TYPO3 v14 but will be removed in TYPO3 v15.

Affected installations 

All extensions using ButtonBar::make*() methods to create buttons, Menu::makeMenuItem() to create menu items, or MenuRegistry::makeMenu() to create menus are affected. The extension scanner will report any usages.

Migration 

Inject \TYPO3\CMS\Backend\Template\Components\ComponentFactory in your controller and use its create*() methods instead of ButtonBar::make*().

Before:

Example (before)
use Psr\Http\Message\ResponseInterface;

public function myAction(): ResponseInterface
{
    $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();

    $linkButton = $buttonBar->makeLinkButton()
        ->setHref($url)
        ->setTitle('My Link')
        ->setIcon($icon);

    $buttonBar->addButton($linkButton);
    // ...
}
Copied!

After:

Example (after)
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Backend\Template\Components\ComponentFactory;

public function __construct(
    protected readonly ComponentFactory $componentFactory,
) {}

public function myAction(): ResponseInterface
{
    $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();

    $linkButton = $this->componentFactory->createLinkButton()
        ->setHref($url)
        ->setTitle('My Link')
        ->setIcon($icon);

    $buttonBar->addButton($linkButton);
    // ...
}
Copied!

Additionally, consider using the preconfigured button creation methods like createBackButton(), createCloseButton(), createSaveButton(), createReloadButton(), and createViewButton() for common button patterns.

For the low-level makeButton(string $className) method, use GeneralUtility::makeInstance() directly or the appropriate ComponentFactory::create*() method:

Example (button instantiation)
use TYPO3\CMS\Core\Utility\GeneralUtility;

// Before:
$button = $buttonBar->makeButton(MyCustomButton::class);

// After (option 1 - direct instantiation):
$button = GeneralUtility::makeInstance(MyCustomButton::class);

// After (option 2 - via factory if it's a standard button):
$button = $this->componentFactory->createLinkButton();
Copied!

For Menu::makeMenuItem(), use ComponentFactory::createMenuItem():

Example (menu items)
use TYPO3\CMS\Backend\Template\Components\ComponentFactory;

// Before:
$menu = $menuRegistry->makeMenu();
$menuItem = $menu->makeMenuItem()
    ->setTitle('My View')
    ->setHref($url);
$menu->addMenuItem($menuItem);

// After:
public function __construct(
    protected readonly ComponentFactory $componentFactory,
) {}

$menu = $this->componentFactory->createMenu();
$menuItem = $this->componentFactory->createMenuItem()
    ->setTitle('My View')
    ->setHref($url);
$menu->addMenuItem($menuItem);
Copied!

For MenuRegistry::makeMenu(), use ComponentFactory::createMenu():

Example (menus)
use TYPO3\CMS\Backend\Template\Components\ComponentFactory;

// Before:
$menuRegistry = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry();
$menu = $menuRegistry->makeMenu();
$menu->setIdentifier('viewSelector')->setLabel('View');

// After:
public function __construct(
    protected readonly ComponentFactory $componentFactory,
) {}

$menuRegistry = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry();
$menu = $this->componentFactory->createMenu();
$menu->setIdentifier('viewSelector')->setLabel('View');
Copied!

Additionally, note that Menu::addMenuItem() now returns static to support fluent interface patterns:

Example (fluent chaining)
// Now possible with fluent interface:
$menu->addMenuItem($menuItem1)
    ->addMenuItem($menuItem2)
    ->addMenuItem($menuItem3);
Copied!