Commit ff67726f authored by Daniel Windloff's avatar Daniel Windloff Committed by Anja Leichsenring
Browse files

[TASK] Migrate RecordListController hooks to an PSR-14 event

The following hooks in the RecordListController are used to add
additional content above or below the main controller content:

*  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']
   ['recordlist/Modules/Recordlist/index.php']['drawHeaderHook']
*  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']
   ['recordlist/Modules/Recordlist/index.php']['drawFooterHook']

As this functionality could be useful, it should be migrated to a
PSR-14 event. Both hook implementations use a meaningful parameter
set (the request object) and return the additional content as string.
As there is no dependency to the parent object (the class instance of
the class where the hooks are placed), they could be migrated to a
psr-14 event without a breaking change.
Therefore, a PSR-14 event has been implemented to replace the hook
functionality. An event listener has been created to provide a
compatibility layer for both hooks. This allows a proper deprecation
without breaking the hooks.
The event listener (compatibility layer) could be removed in later
versions without any changes in the controller class.

Releases: master
Resolves: #92062
Change-Id: I50e4897bae256ec165861bccd8356db107c78962
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/65401


Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
parent 52dd6d09
.. include:: ../../Includes.txt
===========================================================================
Deprecation: #92062 - Migrate RecordListController hooks to an PSR-14 event
===========================================================================
See :issue:`92062`
Description
===========
The following hooks have been marked as deprecated:
* :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawHeaderHook']`
* :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawFooterHook']`
Both hooks could be used to add content before or after the main content of the list module.
Impact
======
Using the hooks still works as before, but a deprecation message is triggered.
The hooks will be removed and stop working in TYPO3 v12.0.
Please migrate to the PSR-14 event: :php:`TYPO3\CMS\Recordlist\Event\RenderAdditionalContentToRecordListEvent`.
Affected Installations
======================
TYPO3 installations with extensions that hook into the RecordListController.
Migration
=========
The functionality of both hooks has been migrated to the following PSR-14 event:
:php:`TYPO3\CMS\Recordlist\Event\RenderAdditionalContentToRecordListEvent`.
The event class contains the following relevant public methods:
* :php:`getRequest`
Returns the request object from the list module request.
* :php:`addContentAbove`
Add additional content as string as it is to be shown above the main content.
* :php:`addContentBelow`
Add additional content as string as it is to be shown below the main content.
The event object is used as parameter for the event listener method (default is :php:`__invoke`).
The listener needs to be registered in the extension: :file:`EXT:myext/Configuration/Services.yaml`.
Example:
.. codeblock:: yaml
My\Extension\Provider\MyAdditionalContentProvider:
tags:
- name: event.listener
identifier: 'my-additional-content'
event: TYPO3\CMS\Recordlist\Event\RenderAdditionalContentToRecordListEvent
Please have a look at :php:`TYPO3\CMS\SysNote\Provider\RecordListProvider` as an example for the
listener implementation.
.. index:: Backend, PHP-API, FullyScanned, ext:recordlist
......@@ -445,4 +445,14 @@ return [
'Breaking-92128-DatabaseRecordListDropHookToModifySearchFields.rst'
],
],
'$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'recordlist/Modules/Recordlist/index.php\'][\'drawHeaderHook\']' => [
'restFiles' => [
'Deprecation-92062-MigrateRecordListControllerHooksToAnPSR-14Event.rst',
],
],
'$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'recordlist/Modules/Recordlist/index.php\'][\'drawFooterHook\']' => [
'restFiles' => [
'Deprecation-92062-MigrateRecordListControllerHooksToAnPSR-14Event.rst',
],
],
];
......@@ -15,6 +15,7 @@
namespace TYPO3\CMS\Recordlist\Controller;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Clipboard\Clipboard;
......@@ -38,6 +39,7 @@ use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\TypoScript\TypoScriptService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Recordlist\Event\RenderAdditionalContentToRecordListEvent;
use TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList;
/**
......@@ -173,17 +175,23 @@ class RecordListController
*/
protected $siteLanguages = [];
/**
* @var EventDispatcherInterface
*/
protected $eventDispatcher;
/**
* Constructor
*/
public function __construct()
public function __construct(IconFactory $iconFactory, ModuleTemplate $moduleTemplate, EventDispatcherInterface $eventDispatcher)
{
$this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
$this->moduleTemplate = $moduleTemplate;
$this->getLanguageService()->includeLLFile('EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf');
$this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Recordlist/FieldSelectBox');
$this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Recordlist/Recordlist');
$this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Recordlist/ClearCache');
$this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
$this->iconFactory = $iconFactory;
$this->eventDispatcher = $eventDispatcher;
}
/**
......@@ -383,14 +391,9 @@ class RecordListController
$this->body = $this->moduleTemplate->header($title);
// Additional header content
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawHeaderHook'] ?? [] as $hook) {
$params = [
'request' => $request,
];
$null = null;
$this->body .= GeneralUtility::callUserFunction($hook, $params, $null);
}
/** @var RenderAdditionalContentToRecordListEvent $additionalRecordListEvent */
$additionalRecordListEvent = $this->eventDispatcher->dispatch(new RenderAdditionalContentToRecordListEvent($request));
$this->body .= $additionalRecordListEvent->getAdditionalContentAbove();
$this->moduleTemplate->setTitle($title);
$output = '';
......@@ -483,13 +486,7 @@ class RecordListController
$this->body .= '<div class="db_list-dashboard">' . $dblist->clipObj->printClipboard() . '</div>';
}
// Additional footer content
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawFooterHook'] ?? [] as $hook) {
$params = [
'request' => $request,
];
$null = null;
$this->body .= GeneralUtility::callUserFunction($hook, $params, $null);
}
$this->body .= $additionalRecordListEvent->getAdditionalContentBelow();
// Setting up the buttons for docheader
$dblist->getDocHeaderButtons($this->moduleTemplate);
// search box toolbar
......
<?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\Recordlist\Event;
use Psr\Http\Message\ServerRequestInterface;
/**
* Class AddToRecordListEvent
*
* Add content above or below the main content of the record list
*/
final class RenderAdditionalContentToRecordListEvent
{
private $contentAbove = '';
private $contentBelow = '';
private $request;
public function __construct(ServerRequestInterface $request)
{
$this->request = $request;
}
public function getRequest(): ServerRequestInterface
{
return $this->request;
}
public function addContentAbove(string $contentAbove): void
{
$this->contentAbove .= $contentAbove;
}
public function addContentBelow(string $contentBelow): void
{
$this->contentBelow .= $contentBelow;
}
public function getAdditionalContentAbove(): string
{
return $this->contentAbove;
}
public function getAdditionalContentBelow(): string
{
return $this->contentBelow;
}
}
<?php
/*
* 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\Recordlist\HookProvider;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Recordlist\Event\RenderAdditionalContentToRecordListEvent;
/**
* This class provides a replacement for the existing hooks of the RecordListController.
*
* @internal Please note that this class will likely be removed in TYPO3 v12 and Extension Authors should
* switch to PSR-14 event listeners.
*/
class AddToRecordListHookProvider
{
public function __invoke(RenderAdditionalContentToRecordListEvent $event)
{
if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawHeaderHook']) && count($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawHeaderHook']) > 0) {
trigger_error('The hook "recordlist/Modules/Recordlist/index.php" "drawHeaderHook" has been marked as deprecated. Use PSR-14 event RenderAdditionalContentToRecordListEvent insted. ', E_USER_DEPRECATED);
}
if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawFooterHook']) && count($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawFooterHook']) > 0) {
trigger_error('The hook "recordlist/Modules/Recordlist/index.php" "drawFooterHook" has been marked as deprecated. Use PSR-14 event RenderAdditionalContentToRecordListEvent insted. ', E_USER_DEPRECATED);
}
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawHeaderHook'] ?? [] as $hook) {
$params = [
'request' => $event->getRequest(),
];
$null = null;
$event->addContentAbove(GeneralUtility::callUserFunction($hook, $params, $null));
}
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawFooterHook'] ?? [] as $hook) {
$params = [
'request' => $event->getRequest(),
];
$null = null;
$event->addContentBelow(GeneralUtility::callUserFunction($hook, $params, $null));
}
}
}
......@@ -6,3 +6,10 @@ services:
TYPO3\CMS\Recordlist\:
resource: '../Classes/*'
TYPO3\CMS\Recordlist\Controller\RecordListController:
tags: ['backend.controller']
TYPO3\CMS\Recordlist\HookProvider\AddToRecordListHookProvider:
tags:
- name: event.listener
identifier: 'record-list-content-legacy-hook'
event: TYPO3\CMS\Recordlist\Event\RenderAdditionalContentToRecordListEvent
\ No newline at end of file
......@@ -15,46 +15,29 @@ 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\Recordlist\Event\RenderAdditionalContentToRecordListEvent;
use TYPO3\CMS\SysNote\Controller\NoteController;
use TYPO3\CMS\SysNote\Domain\Repository\SysNoteRepository;
/**
* Hook for the list module
* @internal This is a specific hook implementation and is not considered part of the Public TYPO3 API.
* Class RecordListProvider
* @internal
*/
class RecordListHook
class RecordListProvider
{
/**
* Add sys_notes as additional content to the header of the list module
*
* @param array $params
* @return string
*/
public function renderInHeader(array $params): string
protected $noteController;
public function __construct(NoteController $noteController)
{
/** @var ServerRequestInterface $request */
$request = $params['request'];
$id = (int)($request->getParsedBody()['id'] ?? $request->getQueryParams()['id'] ?? 0);
$controller = GeneralUtility::makeInstance(NoteController::class);
return $controller->listAction($id, SysNoteRepository::SYS_NOTE_POSITION_TOP);
$this->noteController = $noteController;
}
/**
* Add sys_notes as additional content to the footer of the list module
*
* @param array $params
* @return string
*/
public function renderInFooter(array $params): string
public function __invoke(RenderAdditionalContentToRecordListEvent $event): void
{
/** @var ServerRequestInterface $request */
$request = $params['request'];
$id = (int)($request->getParsedBody()['id'] ?? $request->getQueryParams()['id'] ?? 0);
$controller = GeneralUtility::makeInstance(NoteController::class);
return $controller->listAction($id, SysNoteRepository::SYS_NOTE_POSITION_BOTTOM);
$id = (int)($event->getRequest()->getParsedBody()['id'] ?? $event->getRequest()->getQueryParams()['id'] ?? 0);
$event->addContentAbove($this->noteController->listAction($id, SysNoteRepository::SYS_NOTE_POSITION_TOP));
$event->addContentBelow($this->noteController->listAction($id, SysNoteRepository::SYS_NOTE_POSITION_BOTTOM));
}
}
......@@ -6,3 +6,8 @@ services:
TYPO3\CMS\SysNote\:
resource: '../Classes/*'
TYPO3\CMS\SysNote\Provider\RecordListProvider:
tags:
- name: event.listener
identifier: 'note-to-record-list'
event: TYPO3\CMS\Recordlist\Event\RenderAdditionalContentToRecordListEvent
\ No newline at end of file
......@@ -2,9 +2,6 @@
defined('TYPO3_MODE') or die();
// Hook into the list module
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawHeaderHook']['sys_note'] = \TYPO3\CMS\SysNote\Hook\RecordListHook::class . '->renderInHeader';
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['recordlist/Modules/Recordlist/index.php']['drawFooterHook']['sys_note'] = \TYPO3\CMS\SysNote\Hook\RecordListHook::class . '->renderInFooter';
// Hook into the page modules
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook']['sys_note'] = \TYPO3\CMS\SysNote\Hook\PageHook::class . '->renderInHeader';
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawFooterHook']['sys_note'] = \TYPO3\CMS\SysNote\Hook\PageHook::class . '->renderInFooter';
......
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