Skip to content

Commit

Permalink
[!!!][FEATURE] Add PSR-14 events for the BackendController
Browse files Browse the repository at this point in the history
This introduces two new events to interact with the backend
controller page generation process. They mirror and replace
the renderPreProcess and renderPostProcess hooks, which are removed.

The vestigial constructorPostProcess hook is also removed entirely.

Resolves: #97451
Releases: main
Change-Id: I58bccf341b478eedc87c9a9dd81fac788bba0a91
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/74797
Tested-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Benni Mack <benni@typo3.org>
  • Loading branch information
Crell authored and bmack committed Jul 7, 2022
1 parent a396dad commit 7ea500a
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 34 deletions.
38 changes: 4 additions & 34 deletions typo3/sysext/backend/Classes/Controller/BackendController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@

namespace TYPO3\CMS\Backend\Controller;

use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Controller\Event\AfterBackendPageRenderEvent;
use TYPO3\CMS\Backend\Module\MenuModule;
use TYPO3\CMS\Backend\Module\ModuleInterface;
use TYPO3\CMS\Backend\Module\ModuleProvider;
Expand Down Expand Up @@ -50,8 +52,6 @@ class BackendController
{
use PageRendererBackendSetupTrait;

protected string $css = '';

/**
* @var ModuleInterface[]
*/
Expand All @@ -65,9 +65,8 @@ public function __construct(
protected readonly ToolbarItemsRegistry $toolbarItemsRegistry,
protected readonly ExtensionConfiguration $extensionConfiguration,
protected readonly BackendViewFactory $viewFactory,
protected readonly EventDispatcherInterface $eventDispatcher,
) {
// @todo: This hook is essentially useless.
$this->executeHook('constructPostProcess');
$this->modules = $this->moduleProvider->getModulesForModuleMenu($this->getBackendUser());
}

Expand All @@ -79,8 +78,6 @@ public function mainAction(ServerRequestInterface $request): ResponseInterface
$backendUser = $this->getBackendUser();
$pageRenderer = $this->pageRenderer;

$this->executeHook('renderPreProcess');

$this->setUpBasicPageRendererForBackend($pageRenderer, $this->extensionConfiguration, $request, $this->getLanguageService());

$javaScriptRenderer = $pageRenderer->getJavaScriptRenderer();
Expand Down Expand Up @@ -131,7 +128,6 @@ public function mainAction(ServerRequestInterface $request): ResponseInterface
$dateFormat = ['DD-MM-Y', 'HH:mm DD-MM-Y'];
// Needed for FormEngine manipulation (date picker)
$pageRenderer->addInlineSetting('DateTimePicker', 'DateFormat', $dateFormat);
$pageRenderer->addCssInlineBlock('BackendInlineCSS', $this->css);
$typo3Version = 'TYPO3 CMS ' . $this->typo3Version->getVersion();
$title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . ' [' . $typo3Version . ']' : $typo3Version;
$pageRenderer->setTitle($title);
Expand All @@ -148,7 +144,7 @@ public function mainAction(ServerRequestInterface $request): ResponseInterface
'sitenameFirstInBackendTitle' => ($backendUser->uc['backendTitleFormat'] ?? '') === 'sitenameFirst',
]);
$content = $view->render('Backend/Main');
$this->executeHook('renderPostProcess', ['content' => &$content]);
$content = $this->eventDispatcher->dispatch(new AfterBackendPageRenderEvent($content, $view))->getContent();
$bodyTag = '<body class="scaffold t3js-scaffold' . (!$moduleMenuCollapsed && $this->modules ? ' scaffold-modulemenu-expanded' : '') . '">';
$pageRenderer->addBodyContent($bodyTag . $content);
return $pageRenderer->renderResponse();
Expand Down Expand Up @@ -177,16 +173,6 @@ public function getTopbar(ServerRequestInterface $request): ResponseInterface
return new JsonResponse(['topbar' => $view->render('Backend/Topbar')]);
}

/**
* Adds a css snippet to the backend. This method is old and its purpose
* seems to be that hooks (see executeHook()) can add css?
* @todo: Candidate for deprecation / removal.
*/
public function addCss(string $css): void
{
$this->css .= $css;
}

/**
* Renders the topbar, containing the backend logo, sitename etc.
*/
Expand Down Expand Up @@ -365,22 +351,6 @@ protected function getModulesInformation(): array
return $modules;
}

/**
* Executes defined hooks functions for the given identifier.
*
* These hook identifiers are valid:
* + constructPostProcess
* + renderPreProcess
* + renderPostProcess
*/
protected function executeHook(string $identifier, array $hookConfiguration = []): void
{
$options = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php'];
foreach ($options[$identifier] ?? [] as $hookFunction) {
GeneralUtility::callUserFunction($hookFunction, $hookConfiguration, $this);
}
}

protected function getCollapseStateOfMenu(): bool
{
$backendUser = $this->getBackendUser();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

namespace TYPO3\CMS\Backend\Controller\Event;

use TYPO3\CMS\Core\View\ViewInterface;

/**
* This event triggers after a page has been rendered.
*
* Listeners may update the page content string with a modified
* version if appropriate.
*/
final class AfterBackendPageRenderEvent
{
public function __construct(private string $content, private readonly ViewInterface $view)
{
}

public function getContent(): string
{
return $this->content;
}

public function setContent(string $content): void
{
$this->content = $content;
}

public function getView(): ViewInterface
{
return $this->view;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

namespace TYPO3\CMS\Backend\Tests\Functional\Controller;

use Symfony\Component\DependencyInjection\Container;
use TYPO3\CMS\Backend\Controller\BackendController;
use TYPO3\CMS\Backend\Controller\Event\AfterBackendPageRenderEvent;
use TYPO3\CMS\Backend\Routing\Route;
use TYPO3\CMS\Core\Core\Bootstrap;
use TYPO3\CMS\Core\Core\SystemEnvironmentBuilder;
use TYPO3\CMS\Core\EventDispatcher\ListenerProvider;
use TYPO3\CMS\Core\Http\ServerRequest;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;

class BackendControllerTest extends FunctionalTestCase
{
public function setUp(): void
{
parent::setUp();
$this->setUpBackendUserFromFixture(1);
Bootstrap::initializeLanguageObject();
}

/**
* @test
*/
public function backendPageRenderEventIsTriggered(): void
{
/** @var Container $container */
$container = $this->getContainer();

$state = [
'after-backend-page-render-listener' => null,
];

// Dummy listeners that just record that the event existed.
$container->set(
'after-backend-page-render-listener',
static function (AfterBackendPageRenderEvent $event) use (&$state) {
$state['after-backend-page-render-listener'] = $event;
}
);

$eventListener = GeneralUtility::makeInstance(ListenerProvider::class);
$eventListener->addListener(AfterBackendPageRenderEvent::class, 'after-backend-page-render-listener');

$request = (new ServerRequest())
->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_BE)
->withAttribute('route', new Route('/main', ['packageName' => 'typo3/cms-backend', '_identifier' => 'main']));

$subject = $this->get(BackendController::class);
$subject->mainAction($request);

self::assertInstanceOf(AfterBackendPageRenderEvent::class, $state['after-backend-page-render-listener']);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.. include:: /Includes.rst.txt

=======================================================
Breaking: #97451 - Removed BackendController page hooks
=======================================================

See :issue:`97451`

Description
===========

The hooks :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['constructorPostProcess']`,
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['renderPreProcess']`, and
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['renderPostProcess']` have
been removed in favor of a new PSR-14 Event :php:`\TYPO3\CMS\Backend\Controller\Event\AfterBackendPageRenderEvent`.

Additionally, the :php:`BackendController->addCss()` method has been removed without replacement,
as it is no longer used.

Impact
======

Any hook implementation registered is not executed anymore in
TYPO3 v12.0+. The extension scanner will report possible usages.

Affected Installations
======================

All TYPO3 installations using this hook in custom extension code.

Migration
=========

The hooks are removed without deprecation in order to allow extensions
to work with TYPO3 v11 (using the hook) and v12+ (using the new Event)
when implementing the Event as well without any further deprecations.
Use the :doc:`PSR-14 Event <../12.0/Feature-97451-PSR-14EventsForBackendPageController>`
as an improved replacement.

.. index:: Backend, PHP-API, FullyScanned, ext:backend
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
.. include:: /Includes.rst.txt

==================================================================
Feature: #97451 - PSR-14 Events for modifying backend page content
==================================================================

See :issue:`97451`

Description
===========
A new PSR-14 Event :php:`\TYPO3\CMS\Backend\Controller\Event\AfterBackendPageRenderEvent` has
been introduced which serves as a direct replacement for the now removed
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['constructorPostProcess']`,
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['renderPreProcess']`, and
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['renderPostProcess']`
:doc:`hooks <../12.0/Breaking-97451-RemoveBackendControllerPageHooks>`.

The new Event triggers after the page is rendered and includes
the rendered page body. Listeners may overwrite the page string if desired.

Example
=======

Registration of the Event in your extension's :file:`Services.yaml`:

.. code-block:: yaml
MyVendor\MyPackage\MyEventListener:
tags:
- name: event.listener
identifier: 'my-package/backend/after-backend-controller-render'
The corresponding event listener class:

.. code-block:: php
use TYPO3\CMS\Backend\Controller\Event\AfterBackendPageRenderEvent;
final class MyEventListener
{
public function __invoke(AfterBackendPageRenderEvent $event): void
{
$content = $event->getContent() . ' I was here';
$event->setContent($content);
}
}
Impact
======

It's now possible to modify the backend page using the new PSR-14 :php:`AfterBackendPageRenderEvent`.

.. index:: Backend, PHP-API, ext:backend
Original file line number Diff line number Diff line change
Expand Up @@ -784,4 +784,22 @@
'Feature-97862-NewPSR-14EventsForManipulatingFrontendPageGenerationAndCacheBehaviour.rst',
],
],
'$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'typo3/backend.php\'][\'constructorPostProcess\']' => [
'restFiles' => [
'Breaking-97451-RemoveBackendControllerPageHooks.rst',
'Feature-97451-PSR-14EventsForBackendPageController.rst',
],
],
'$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'typo3/backend.php\'][\'renderPreProcess\']' => [
'restFiles' => [
'Breaking-97451-RemoveBackendControllerPageHooks.rst',
'Feature-97451-PSR-14EventsForBackendPageController.rst',
],
],
'$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'typo3/backend.php\'][\'renderPostProcess\']' => [
'restFiles' => [
'Breaking-97451-RemoveBackendControllerPageHooks.rst',
'Feature-97451-PSR-14EventsForBackendPageController.rst',
],
],
];
Original file line number Diff line number Diff line change
Expand Up @@ -5323,4 +5323,11 @@
'Deprecation-97531-ContextRelatedMethodsWithinTSFE.rst',
],
],
'TYPO3\CMS\Backend\Controller\BackendController->addCss' => [
'numberOfMandatoryArguments' => 0,
'maximumNumberOfArguments' => 0,
'restFiles' => [
'Breaking-97451-RemoveBackendControllerPageHooks.rst',
],
],
];

0 comments on commit 7ea500a

Please sign in to comment.