Commit 412df9f4 authored by Oliver Bartsch's avatar Oliver Bartsch
Browse files

[FEATURE] Introduce AfterFileCommandProcessedEvent

A new PSR-14 based event "AfterFileCommandProcessedEvent"
is introduced in favour of the existing
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_extfilefunc.php']['processData']
hook, which is now marked as deprecated, along with
its interface "ExtendedFileUtilityProcessDataHookInterface".

The new event features the same data, however
the way they can be accessed is improved.

The previous `$action` and `$cmdArr` arguments
are now available within the `getCommand()` method,
while the action is the array key and the command
data ($cmdArr) is the value. This is more in line
with the actual request.

The hooks `$result` argument always contained all
results of previous operations, making it unnecessary
complicated to find out the actual result for the
current operation. This is now resolved. The new
`getResult()` method only returns the result for
the currently executed operation.

Finally the "getConflictMode()" method just returns
the conflict mode, used for the current operation.

Resolves: #95089
Releases: master
Change-Id: I9991eb73aed873da5987f88d2d0255764274e143
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70874

Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Tested-by: Jochen's avatarJochen <rothjochen@gmail.com>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Jochen's avatarJochen <rothjochen@gmail.com>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
parent 847f2dd9
<?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\Core\Resource\Event;
/**
* Event that is triggered after a file command has been processed. Can be used
* to perform additional tasks for specific commands. For example, trigger a
* custom indexer after a file has been uploaded.
*/
final class AfterFileCommandProcessedEvent
{
private array $command;
private $result;
private string $conflictMode;
public function __construct(array $command, $result, string $conflictMode)
{
$this->command = $command;
$this->result = $result;
$this->conflictMode = $conflictMode;
}
/**
* A single command, e.g.:
*
* 'upload' => [
* 'target' => '1:/some/folder/'
* 'data' => '1'
* ]
*
* @return array<string, array<string, mixed>>
*/
public function getCommand(): array
{
return $this->command;
}
/**
* @return mixed The result - Depending on the performed action,
* this could e.g. be a File or just a boolean.
*/
public function getResult()
{
return $this->result;
}
/**
* @return string The current conflict mode
* @see DuplicationBehavior
*/
public function getConflictMode(): string
{
return $this->conflictMode;
}
}
......@@ -15,6 +15,7 @@
namespace TYPO3\CMS\Core\Utility\File;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Database\Connection;
......@@ -24,6 +25,7 @@ use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Messaging\FlashMessageService;
use TYPO3\CMS\Core\Resource\DuplicationBehavior;
use TYPO3\CMS\Core\Resource\Event\AfterFileCommandProcessedEvent;
use TYPO3\CMS\Core\Resource\Exception;
use TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException;
use TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException;
......@@ -243,40 +245,51 @@ class ExtendedFileUtility extends BasicFileUtility
// Traverse all action data. More than one file might be affected at the same time.
if (is_array($actionData)) {
$result[$action] = [];
foreach ($actionData as $cmdArr) {
// We reset the array keys of $actionData to keep track of the corresponding
// result, while not changing the previous behaviour of $result[$action][].
foreach (array_values($actionData) as $key => $cmdArr) {
// Clear file stats
clearstatcache();
// Branch out based on command:
switch ($action) {
case 'delete':
$result[$action][] = $this->func_delete($cmdArr);
$result[$action][$key] = $this->func_delete($cmdArr);
break;
case 'copy':
$result[$action][] = $this->func_copy($cmdArr);
$result[$action][$key] = $this->func_copy($cmdArr);
break;
case 'move':
$result[$action][] = $this->func_move($cmdArr);
$result[$action][$key] = $this->func_move($cmdArr);
break;
case 'rename':
$result[$action][] = $this->func_rename($cmdArr);
$result[$action][$key] = $this->func_rename($cmdArr);
break;
case 'newfolder':
$result[$action][] = $this->func_newfolder($cmdArr);
$result[$action][$key] = $this->func_newfolder($cmdArr);
break;
case 'newfile':
$result[$action][] = $this->func_newfile($cmdArr);
$result[$action][$key] = $this->func_newfile($cmdArr);
break;
case 'editfile':
$result[$action][] = $this->func_edit($cmdArr);
$result[$action][$key] = $this->func_edit($cmdArr);
break;
case 'upload':
$result[$action][] = $this->func_upload($cmdArr);
$result[$action][$key] = $this->func_upload($cmdArr);
break;
case 'replace':
$result[$action][] = $this->replaceFile($cmdArr);
$result[$action][$key] = $this->replaceFile($cmdArr);
break;
}
if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_extfilefunc.php']['processData'])) {
trigger_error(
'The hook $TYPO3_CONF_VARS[SC_OPTIONS][t3lib/class.t3lib_extfilefunc.php][processData] is deprecated and will stop working in TYPO3 v12.0. Use the AfterFileCommandProcessedEvent instead.',
E_USER_DEPRECATED
);
}
// Hook for post-processing the action
// @deprecated will be removed in TYPO3 v12.0.
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_extfilefunc.php']['processData'] ?? [] as $className) {
$hookObject = GeneralUtility::makeInstance($className);
if (!$hookObject instanceof ExtendedFileUtilityProcessDataHookInterface) {
......@@ -284,6 +297,10 @@ class ExtendedFileUtility extends BasicFileUtility
}
$hookObject->processData_postProcessAction($action, $cmdArr, $result[$action], $this);
}
GeneralUtility::getContainer()->get(EventDispatcherInterface::class)->dispatch(
new AfterFileCommandProcessedEvent([$action => $cmdArr], $result[$action][$key], (string)$this->existingFilesConflictMode)
);
}
}
}
......
......@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Core\Utility\File;
/**
* Interface for classes which hook into extFileFunctions and do additional processData processing.
* @deprecated since TYPO3 v11 LTS, will be removed in TYPO3 v12.0. Use the PSR-14-based AfterFileCommandProcessedEvent instead.
*/
interface ExtendedFileUtilityProcessDataHookInterface
{
......
.. include:: ../../Includes.txt
==========================================================
Deprecation: #95089 - ExtendedFileUtility ProcessData hook
==========================================================
See :issue:`95089`
Description
===========
The TYPO3 Hook :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_extfilefunc.php']['processData']`
which can be used to execute additional tasks, after a file operation has
been performed, has been deprecated.
The accompanied PHP Interface for the hook
:php:`TYPO3\CMS\Core\Utility\File\ExtendedFileUtilityProcessDataHookInterface`
has been marked as deprecated as well.
Impact
======
If the 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 `AfterFileCommandProcessedEvent` PSR-14 event.
.. index:: PHP-API, FullyScanned, ext:core
.. include:: ../../Includes.txt
===========================================================
Feature: #95089 - New PSR-14 AfterFileCommandProcessedEvent
===========================================================
See :issue:`95089`
Description
===========
A new PSR-14 event `AfterFileCommandProcessedEvent` has been added to
TYPO3 Core. This event is fired in the :php:`ExtendedFileUtility`
class and allows extensions to execute additional tasks, after a file
operation has been performed.
The event features the following methods:
- :php:`getCommand()`: Returns the command array while the array key is the perfomerd action and the value is the command data ("cmdArr")
- :php:`getResult()`: Returns the operation result, which could e.g. be an uploaded or changed :php:`File` or a :php:`boolean` for the "delete" action
- :php:`getConflictMode()`: The conflict mode for the performed operation, e.g. "rename" or "cancel"
Registration of the Event in your extensions' `Services.yaml`:
.. code-block:: yaml
MyVendor\MyPackage\File\MyEventListener:
tags:
- name: event.listener
identifier: 'my-package/file/my-event-listener'
The corresponding event listener class:
.. code-block:: php
use TYPO3\CMS\Core\Resource\Event\AfterFileCommandProcessedEvent;
class MyEventListener {
public function __invoke(AfterFileCommandProcessedEvent $event): void
{
// do magic here
}
}
Impact
======
This event can be used to perform additional tasks for specific file commands.
For example, trigger a custom indexer after a file has been uploaded.
.. index:: PHP-API, ext:core
......@@ -512,4 +512,9 @@ return [
'Deprecation-95080-FileDumpCheckFileAccessHook.rst',
],
],
'$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'t3lib/class.t3lib_extfilefunc.php\'][\'processData\']' => [
'restFiles' => [
'Deprecation-95089-ExtendedFileUtilityProcessDataHook.rst',
],
],
];
......@@ -1799,4 +1799,9 @@ return [
'Deprecation-95080-FileDumpCheckFileAccessHook.rst',
],
],
'TYPO3\CMS\Core\Utility\File\ExtendedFileUtilityProcessDataHookInterface' => [
'restFiles' => [
'Deprecation-95089-ExtendedFileUtilityProcessDataHook.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