Commit 681e71a0 authored by Oliver Bartsch's avatar Oliver Bartsch Committed by Benjamin Franzke
Browse files

[!!!][FEATURE] Add PSR-14 event to modify page module content

This introduces a new PSR-14 event, enabling extension
authors to modify the header and footer content of the
page module in a flexible way, since also reordering
and overwriting is possible now.

This replaces the previously available hooks

- $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook']
- $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawFooterHook']

which are now removed.

Resolves: #96526
Releases: main
Change-Id: I5fb3f3098394b70ecc4e5cc11c804f7125ad2a4a
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/73003

Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
Tested-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
Reviewed-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
Reviewed-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
parent 40ebc6bb
<?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 Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Template\ModuleTemplate;
/**
* Listeners to this Event will be able to modify the header and footer content of the page module
*/
final class ModifyPageLayoutContentEvent
{
private ServerRequestInterface $request;
private ModuleTemplate $moduleTemplate;
private string $headerContent = '';
private string $footerContent = '';
public function __construct(ServerRequestInterface $request, ModuleTemplate $moduleTemplate)
{
$this->request = $request;
$this->moduleTemplate = $moduleTemplate;
}
public function getRequest(): ServerRequestInterface
{
return $this->request;
}
public function getModuleTemplate(): ModuleTemplate
{
return $this->moduleTemplate;
}
/**
* Set content for the header. Can also be used to e.g. reorder existing content.
* IMPORTANT: This overwrites existing content from previous listeners!
*/
public function setHeaderContent(string $content): void
{
$this->headerContent = $content;
}
/**
* Add additional content to the header
*/
public function addHeaderContent(string $content): void
{
$this->headerContent .= $content;
}
public function getHeaderContent(): string
{
return $this->headerContent;
}
/**
* Set content for the footer. Can also be used to e.g. reorder existing content.
* IMPORTANT: This overwrites existing content from previous listeners!
*/
public function setFooterContent(string $content): void
{
$this->footerContent = $content;
}
/**
* Add additional content to the footer
*/
public function addFooterContent(string $content): void
{
$this->footerContent .= $content;
}
public function getFooterContent(): string
{
return $this->footerContent;
}
}
......@@ -20,6 +20,7 @@ namespace TYPO3\CMS\Backend\Controller;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Clipboard\Clipboard;
use TYPO3\CMS\Backend\Controller\Event\ModifyPageLayoutContentEvent;
use TYPO3\CMS\Backend\Domain\Model\Element\ImmediateActionElement;
use TYPO3\CMS\Backend\Module\ModuleLoader;
use TYPO3\CMS\Backend\Routing\PreviewUriBuilder;
......@@ -36,6 +37,7 @@ use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Domain\Repository\PageRepository;
use TYPO3\CMS\Core\EventDispatcher\EventDispatcher;
use TYPO3\CMS\Core\Http\HtmlResponse;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
......@@ -159,19 +161,22 @@ class PageLayoutController
protected UriBuilder $uriBuilder;
protected PageRepository $pageRepository;
protected ModuleTemplateFactory $moduleTemplateFactory;
protected EventDispatcher $eventDispatcher;
public function __construct(
IconFactory $iconFactory,
PageRenderer $pageRenderer,
UriBuilder $uriBuilder,
PageRepository $pageRepository,
ModuleTemplateFactory $moduleTemplateFactory
ModuleTemplateFactory $moduleTemplateFactory,
EventDispatcher $eventDispatcher
) {
$this->iconFactory = $iconFactory;
$this->pageRenderer = $pageRenderer;
$this->uriBuilder = $uriBuilder;
$this->pageRepository = $pageRepository;
$this->moduleTemplateFactory = $moduleTemplateFactory;
$this->eventDispatcher = $eventDispatcher;
}
/**
* Injects the request object for the current request or subrequest
......@@ -723,31 +728,8 @@ class PageLayoutController
</div>';
}
// Init the content
$content = '';
// Additional header content
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook'] ?? [] as $hook) {
$params = ['request' => $request];
$content .= GeneralUtility::callUserFunction($hook, $params, $this);
}
$content .= $tableOutput;
// Additional footer content
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawFooterHook'] ?? [] as $hook) {
$params = ['request' => $request];
$content .= GeneralUtility::callUserFunction($hook, $params, $this);
}
return $content;
}
/**
* Make the ModuleTemplate public accessible for the use in hooks.
*
* @return ModuleTemplate
*/
public function getModuleTemplate(): ModuleTemplate
{
return $this->moduleTemplate;
$event = $this->eventDispatcher->dispatch(new ModifyPageLayoutContentEvent($request, $this->moduleTemplate));
return $event->getHeaderContent() . $tableOutput . $event->getFooterContent();
}
/***************************
......
.. include:: ../../Includes.txt
==================================================================
Breaking: #96526 - Removed hooks for modifying page module content
==================================================================
See :issue:`96526`
Description
===========
The previously available hooks to modify the header
:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook']`
and footer :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawFooterHook']`
content of the page module have been removed in favor of a new PSR-14
Event :php:`TYPO3\CMS\Backend\Controller\Event\ModifyPageLayoutContentEvent`.
The public method :php:`PageLayoutController->getModuleTemplate()` has been
removed as well, since it was only used for the removed hooks.
Impact
======
Registering any of the mentioned hooks does no longer have any
effect in TYPO3 v12.0+. The extension scanner will detect usages
as strong match.
The method :php:`PageLayoutController->getModuleTemplate()` is no longer
available and will therefore lead to PHP errors when called from extension
code. The extension scanner will detect usages as weak match.
Affected Installations
======================
TYPO3 installations using one of the mentioned hooks or calling
:php:`PageLayoutController->getModuleTemplate()` in custom extension
code.
Migration
=========
Replace the hooks with the new PSR-14
:doc:`ModifyPageLayoutContentEvent <../12.0/Feature-96526-PSR-14EventForModifyingPageModuleContent.rst>`.
.. index:: Backend, PHP-API, FullyScanned, ext:backend
.. include:: ../../Includes.txt
================================================================
Feature: #96526 - PSR-14 Event for modifying page module content
================================================================
See :issue:`96526`
Description
===========
A new PSR-14 Event :php:`TYPO3\CMS\Backend\Controller\Event\ModifyPageLayoutContentEvent`
has been introduced which serves as a more powerful and flexible alternative
for the now removed hooks :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook']`
and :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawFooterHook']`.
Next to the :php:`getRequest()` and :php:`getModuleTemplate()` methods does
the event feature the usual getter and setter for the header and footer
content. It is therefore now possible to not just add additional content to
the module, but to also overwrite existing content or to reorder the content.
Example
=======
Registration of the Event in your extensions' :file:`Services.yaml`:
.. code-block:: yaml
MyVendor\MyPackage\Backend\MyEventListener:
tags:
- name: event.listener
identifier: 'my-package/backend/modify-page-module-content'
The corresponding event listener class:
.. code-block:: php
use TYPO3\CMS\Backend\Controller\Event\ModifyPageLayoutContentEvent;
class MyEventListener {
public function __invoke(ModifyPageLayoutContentEvent $event): void
{
$event->addHeaderContent('Additional header content');
$event->setFooterContent('Overwrite footer content');
}
}
In contrast to the removed hooks, the new event does not provide the
:php:`PageLayoutController` as :php:`$parentObject`, since :php:`getModuleTemplate()`
has been the only public method, which is now directly included in the event.
Additionally, there were three public properties :php:`$id`, :php:`$pageInfo`
and :php:`$MOD_SETTINGS`, which however had already been marked as :php:`@internal`
in TYPO3 v9. If needed, the information can be retrieved from the request directly.
An example to get the current :php:`$id`:
.. code-block:: php
public function __invoke(ModifyPageLayoutContentEvent $event): void
{
$id = (int)($event->getRequest()->getQueryParams()['id'] ?? 0);
}
Impact
======
The new PSR-14 event allows to modify the content of the page module
header and footer sections in an efficient and flexible way.
.. index:: Backend, PHP-API, ext:backend
......@@ -571,4 +571,16 @@ return [
'Feature-92508-PSR-14EventForModifyingMenuItems.rst',
],
],
'$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'cms/layout/db_layout.php\'][\'drawHeaderHook\']' => [
'restFiles' => [
'Breaking-96526-RemovedHooksForModifyingPageModuleContent.rst',
'Feature-96526-PSR-14EventForModifyingPageModuleContent.rst',
],
],
'$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'cms/layout/db_layout.php\'][\'drawFooterHook\']' => [
'restFiles' => [
'Breaking-96526-RemovedHooksForModifyingPageModuleContent.rst',
'Feature-96526-PSR-14EventForModifyingPageModuleContent.rst',
],
],
];
......@@ -5105,4 +5105,12 @@ return [
'Deprecation-96500-ContentObjectRenderer-getMailTo.rst',
],
],
'TYPO3\CMS\Backend\Controller\PageLayoutController->getModuleTemplate' => [
'numberOfMandatoryArguments' => 0,
'maximumNumberOfArguments' => 0,
'restFiles' => [
'Breaking-96526-RemovedHooksForModifyingPageModuleContent.rst',
'Feature-96526-PSR-14EventForModifyingPageModuleContent.rst',
],
],
];
......@@ -15,44 +15,35 @@ declare(strict_types=1);
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\SysNote\Hook;
namespace TYPO3\CMS\SysNote\Provider;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Backend\Controller\Event\ModifyPageLayoutContentEvent;
use TYPO3\CMS\SysNote\Controller\NoteController;
use TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository;
/**
* Hook to render notes in the page module.
* Event listener to render notes in the page module.
*
* @internal This is a specific hook implementation and is not considered part of the Public TYPO3 API.
* @internal This is a specific listener implementation and is not considered part of the Public TYPO3 API.
*/
class PageHook
final class PageModuleProvider
{
protected NoteController $noteController;
/**
* Add sys_notes as additional content to the header of the page module
*/
public function renderInHeader(array $params)
public function __construct(NoteController $noteController)
{
/** @var ServerRequestInterface $request */
$request = $params['request'];
$id = (int)($request->getQueryParams()['id'] ?? 0);
$returnUrl = $request->getAttribute('normalizedParams')->getRequestUri();
$controller = GeneralUtility::makeInstance(NoteController::class);
return $controller->listAction($id, SysNoteRepository::SYS_NOTE_POSITION_TOP, $returnUrl);
$this->noteController = $noteController;
}
/**
* Add sys_notes as additional content to the footer of the page module
* Add sys_notes as additional content to the header and footer of the page module
*/
public function renderInFooter(array $params): string
public function __invoke(ModifyPageLayoutContentEvent $event): void
{
/** @var ServerRequestInterface $request */
$request = $params['request'];
$request = $event->getRequest();
$id = (int)($request->getQueryParams()['id'] ?? 0);
$returnUrl = $request->getAttribute('normalizedParams')->getRequestUri();
$controller = GeneralUtility::makeInstance(NoteController::class);
return $controller->listAction($id, SysNoteRepository::SYS_NOTE_POSITION_BOTTOM, $returnUrl);
$event->addHeaderContent($this->noteController->listAction($id, SysNoteRepository::SYS_NOTE_POSITION_TOP, $returnUrl));
$event->addFooterContent($this->noteController->listAction($id, SysNoteRepository::SYS_NOTE_POSITION_BOTTOM, $returnUrl));
}
}
......@@ -10,3 +10,7 @@ services:
tags:
- name: event.listener
identifier: 'note-to-record-list'
TYPO3\CMS\SysNote\Provider\PageModuleProvider:
tags:
- name: event.listener
identifier: 'note-to-page-module'
......@@ -4,13 +4,9 @@ declare(strict_types=1);
use TYPO3\CMS\SysNote\Hook\ButtonBarHook;
use TYPO3\CMS\SysNote\Hook\InfoModuleHook;
use TYPO3\CMS\SysNote\Hook\PageHook;
defined('TYPO3') or die();
// Hook into the page modules
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook']['sys_note'] = PageHook::class . '->renderInHeader';
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawFooterHook']['sys_note'] = PageHook::class . '->renderInFooter';
// Hook into the info module
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/web_info/class.tx_cms_webinfo.php']['drawFooterHook']['sys_note'] = InfoModuleHook::class . '->render';
// Hook into the button bar
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment