Commit 804e29b4 authored by Benni Mack's avatar Benni Mack
Browse files

[FEATURE] Introduce Event for processing actions in File List

A new PSR-14 based event "ProcessFileListActionsEvent"
is introduced in favor of the existing
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['fileList']['editIconsHook']
hook, which is now marked as deprecated,
along with its interface "FileListEditIconHookInterface"

Resolves: #95077
Releases: master
Change-Id: I24ea2a5871530c0e6a7b2316d3b574508e3e1687
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70835


Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: Nikita Hovratov's avatarNikita Hovratov <nikita.h@live.de>
Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Nikita Hovratov's avatarNikita Hovratov <nikita.h@live.de>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent ad17c45c
.. include:: ../../Includes.txt
============================================
Deprecation: #95077 - Filelist editIconsHook
============================================
See :issue:`95077`
Description
===========
The TYPO3 Hook :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['fileList']['editIconsHook']`
which is executed in the :php:`FileList` class to manipulate the icons, used
for the edit control section in the files and folders listing, has been
deprecated.
The accompanied PHP Interface for such hooks
:php:`TYPO3\CMS\Filelist\FileListEditIconHookInterface` has been marked
as deprecated as well.
Impact
======
If a hook is registered in a TYPO3 installation, a PHP deprecation
message is triggered. The extension scanner also detects any usage
of the deprecated interface as strong, and the definition of the
hook as weak match.
Affected Installations
======================
TYPO3 installations with custom extensions using this hook.
Migration
=========
Migrate to the newly introduced `ProcessFileListActionsEvent` PSR-14 event.
.. index:: PHP-API, FullyScanned, ext:filelist
.. include:: ../../Includes.txt
========================================================
Feature: #95077 - New PSR-14 ProcessFileListActionsEvent
========================================================
See :issue:`95077`
Description
===========
A new PSR-14 event `ProcessFileListActionsEvent` has been added to
TYPO3 Core. This event is fired after generating the actions for the
files and folders listing in the :guilabel:`File > Filelist` module.
Registration of the Event in your extensions' `Services.yaml`:
.. code-block:: yaml
MyVendor\MyPackage\FileList\MyEventListener:
tags:
- name: event.listener
identifier: 'my-package/filelist/my-event-listener'
The corresponding event listener class:
.. code-block:: php
use TYPO3\CMS\Filelist\Event\ProcessFileListActionsEvent;
class MyEventListener {
public function __invoke(ProcessFileListActionsEvent $event): void
{
// do your magic
}
}
Impact
======
This event can be used to manipulate the icons, used for the edit control
section in the files and folders listing within the :guilabel:`File > Filelist`
module.
.. index:: PHP-API, ext:filelist
<?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\Filelist\Event;
use TYPO3\CMS\Core\Resource\FileInterface;
use TYPO3\CMS\Core\Resource\ResourceInterface;
/**
* Event fired to modify icons rendered for the file listings
*/
final class ProcessFileListActionsEvent
{
private ResourceInterface $fileOrFolder;
private array $actionItems;
public function __construct(ResourceInterface $fileOrFolder, array $actionItems)
{
$this->fileOrFolder = $fileOrFolder;
$this->actionItems = $actionItems;
}
public function getResource(): ResourceInterface
{
return $this->fileOrFolder;
}
public function isFile(): bool
{
return $this->fileOrFolder instanceof FileInterface;
}
public function getActionItems(): array
{
return $this->actionItems;
}
public function setActionItems(array $actionItems): void
{
$this->actionItems = $actionItems;
}
}
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
namespace TYPO3\CMS\Filelist; namespace TYPO3\CMS\Filelist;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Backend\Avatar\Avatar; use TYPO3\CMS\Backend\Backend\Avatar\Avatar;
use TYPO3\CMS\Backend\Clipboard\Clipboard; use TYPO3\CMS\Backend\Clipboard\Clipboard;
...@@ -43,6 +44,7 @@ use TYPO3\CMS\Core\Resource\Utility\ListUtility; ...@@ -43,6 +44,7 @@ use TYPO3\CMS\Core\Resource\Utility\ListUtility;
use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation; use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility; use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Filelist\Event\ProcessFileListActionsEvent;
/** /**
* Class for rendering of File>Filelist (basically used in FileListController) * Class for rendering of File>Filelist (basically used in FileListController)
...@@ -184,11 +186,14 @@ class FileList ...@@ -184,11 +186,14 @@ class FileList
*/ */
protected array $backendUserCache = []; protected array $backendUserCache = [];
protected EventDispatcherInterface $eventDispatcher;
public function __construct(?ServerRequestInterface $request = null) public function __construct(?ServerRequestInterface $request = null)
{ {
// Setting the maximum length of the filenames to the user's settings or minimum 30 (= $this->fixedL) // Setting the maximum length of the filenames to the user's settings or minimum 30 (= $this->fixedL)
$this->fixedL = max($this->fixedL, $this->getBackendUser()->uc['titleLen'] ?? 1); $this->fixedL = max($this->fixedL, $this->getBackendUser()->uc['titleLen'] ?? 1);
$this->iconFactory = GeneralUtility::makeInstance(IconFactory::class); $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
$this->eventDispatcher = GeneralUtility::getContainer()->get(EventDispatcherInterface::class);
$this->translateTools = GeneralUtility::makeInstance(TranslationConfigurationProvider::class); $this->translateTools = GeneralUtility::makeInstance(TranslationConfigurationProvider::class);
$this->iLimit = MathUtility::forceIntegerInRange( $this->iLimit = MathUtility::forceIntegerInRange(
$this->getBackendUser()->getTSConfig()['options.']['file_list.']['filesPerPage'] ?? $this->iLimit, $this->getBackendUser()->getTSConfig()['options.']['file_list.']['filesPerPage'] ?? $this->iLimit,
...@@ -1055,6 +1060,7 @@ class FileList ...@@ -1055,6 +1060,7 @@ class FileList
} }
// Hook for manipulating edit icons. // Hook for manipulating edit icons.
// @deprecated will be removed in TYPO3 v12.0.
$cells['__fileOrFolderObject'] = $fileOrFolderObject; $cells['__fileOrFolderObject'] = $fileOrFolderObject;
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['fileList']['editIconsHook'] ?? [] as $className) { foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['fileList']['editIconsHook'] ?? [] as $className) {
$hookObject = GeneralUtility::makeInstance($className); $hookObject = GeneralUtility::makeInstance($className);
...@@ -1066,6 +1072,10 @@ class FileList ...@@ -1066,6 +1072,10 @@ class FileList
} }
$hookObject->manipulateEditIcons($cells, $this); $hookObject->manipulateEditIcons($cells, $this);
} }
if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['fileList']['editIconsHook'])) {
trigger_error('Using the hook $TYPO3_CONF_VARS[SC_OPTIONS][fileList][editIconsHook] will not work in TYPO3 v12.0 anymore. Use the PSR-14 based ProcessFileListActionsEvent instead.', E_USER_DEPRECATED);
}
unset($cells['__fileOrFolderObject']); unset($cells['__fileOrFolderObject']);
// Get clipboard actions // Get clipboard actions
...@@ -1077,6 +1087,10 @@ class FileList ...@@ -1077,6 +1087,10 @@ class FileList
// Merge the clipboard actions into the existing cells // Merge the clipboard actions into the existing cells
$cells = array_merge($cells, $clipboardActions); $cells = array_merge($cells, $clipboardActions);
$event = new ProcessFileListActionsEvent($fileOrFolderObject, $cells);
$event = $this->eventDispatcher->dispatch($event);
$cells = $event->getActionItems();
// Compile items into a dropdown // Compile items into a dropdown
$cellOutput = ''; $cellOutput = '';
$output = ''; $output = '';
...@@ -1085,7 +1099,7 @@ class FileList ...@@ -1085,7 +1099,7 @@ class FileList
$output .= $action; $output .= $action;
continue; continue;
} }
if ($action === $this->spaceIcon) { if ($action === $this->spaceIcon || $action === null) {
continue; continue;
} }
// This is a backwards-compat layer for the existing hook items, which will be removed in TYPO3 v12. // This is a backwards-compat layer for the existing hook items, which will be removed in TYPO3 v12.
......
...@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Filelist; ...@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Filelist;
/** /**
* Interface for classes which hook into filelist module and manipulated edit icon array * Interface for classes which hook into filelist module and manipulated edit icon array
* @deprecated will be removed in TYPO3 v12.0, Use the PSR-14 based ProcessFileListActionsEvent instead.
*/ */
interface FileListEditIconHookInterface interface FileListEditIconHookInterface
{ {
......
...@@ -15,40 +15,35 @@ declare(strict_types=1); ...@@ -15,40 +15,35 @@ declare(strict_types=1);
* The TYPO3 project - inspiring people to share! * The TYPO3 project - inspiring people to share!
*/ */
namespace TYPO3\CMS\Form\Hooks; namespace TYPO3\CMS\Form\EventListener;
use TYPO3\CMS\Core\Utility\StringUtility; use TYPO3\CMS\Filelist\Event\ProcessFileListActionsEvent;
use TYPO3\CMS\Filelist\FileList;
use TYPO3\CMS\Filelist\FileListEditIconHookInterface;
use TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager; use TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager;
/** /**
* Event listener to disable certain actions when checking for form.yaml files.
* @internal * @internal
*/ */
class FileListEditIconsHook implements FileListEditIconHookInterface class ProcessFileListActionsEventListener
{ {
protected const DISABLED_ACTIONS = ['edit', 'view', 'replace', 'rename', 'download'];
/** public function __invoke(ProcessFileListActionsEvent $event): void
* Modifies edit icon array
*
* @param array $cells
* @param FileList $parentObject
*/
public function manipulateEditIcons(&$cells, &$parentObject)
{ {
$fileOrFolderObject = $cells['__fileOrFolderObject']; if (!$event->isFile()) {
$fullIdentifier = $fileOrFolderObject->getCombinedIdentifier(); return;
$isFormDefinition = StringUtility::endsWith($fullIdentifier, FormPersistenceManager::FORM_DEFINITION_FILE_EXTENSION); }
$fullIdentifier = $event->getResource()->getCombinedIdentifier();
if (!$isFormDefinition) { if (!str_ends_with($fullIdentifier, FormPersistenceManager::FORM_DEFINITION_FILE_EXTENSION)) {
return; return;
} }
$disableIconNames = ['edit', 'view', 'replace', 'rename']; $actionItems = $event->getActionItems();
foreach ($disableIconNames as $disableIconName) { foreach (self::DISABLED_ACTIONS as $disableIconName) {
if (!empty($cells[$disableIconName])) { if (!empty($actionItems[$disableIconName])) {
$cells[$disableIconName] = $parentObject->spaceIcon; $actionItems[$disableIconName] = null;
} }
} }
$event->setActionItems($actionItems);
} }
} }
...@@ -62,6 +62,11 @@ services: ...@@ -62,6 +62,11 @@ services:
identifier: 'form-framework/update-content' identifier: 'form-framework/update-content'
method: 'onPreFileSetContents' method: 'onPreFileSetContents'
TYPO3\CMS\Form\EventListener\ProcessFileListActionsEventListener:
tags:
- name: event.listener
identifier: 'form-framework/form-definition-files'
lowlevel.configuration.module.provider.formyamlconfiguration: lowlevel.configuration.module.provider.formyamlconfiguration:
class: 'TYPO3\CMS\Form\ConfigurationModuleProvider\FormYamlProvider' class: 'TYPO3\CMS\Form\ConfigurationModuleProvider\FormYamlProvider'
tags: tags:
......
...@@ -9,10 +9,6 @@ call_user_func(function () { ...@@ -9,10 +9,6 @@ call_user_func(function () {
// Context menu item handling for form files // Context menu item handling for form files
$GLOBALS['TYPO3_CONF_VARS']['BE']['ContextMenu']['ItemProviders'][1530637161] $GLOBALS['TYPO3_CONF_VARS']['BE']['ContextMenu']['ItemProviders'][1530637161]
= \TYPO3\CMS\Form\Hooks\FormFileProvider::class; = \TYPO3\CMS\Form\Hooks\FormFileProvider::class;
// File list edit icons
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['fileList']['editIconsHook'][1530637161]
= \TYPO3\CMS\Form\Hooks\FileListEditIconsHook::class;
} }
if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('impexp')) { if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('impexp')) {
......
...@@ -502,4 +502,9 @@ return [ ...@@ -502,4 +502,9 @@ return [
'Deprecation-95065-HookExtTablesInclusion-PostProcessing.rst', 'Deprecation-95065-HookExtTablesInclusion-PostProcessing.rst',
], ],
], ],
'$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'fileList\'][\'editIconsHook\']' => [
'restFiles' => [
'Deprecation-95077-FilelistEditIconsHook.rst',
],
],
]; ];
...@@ -1789,4 +1789,9 @@ return [ ...@@ -1789,4 +1789,9 @@ return [
'Deprecation-95065-HookExtTablesInclusion-PostProcessing.rst', 'Deprecation-95065-HookExtTablesInclusion-PostProcessing.rst',
], ],
], ],
'TYPO3\CMS\Filelist\FileListEditIconHookInterface' => [
'restFiles' => [
'Deprecation-95077-FilelistEditIconsHook.rst',
],
],
]; ];
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