Commit 3fde1b1d authored by Alexander Schnitzler's avatar Alexander Schnitzler Committed by Daniel Goerz
Browse files

[TASK] Deprecate \TYPO3\CMS\Extbase\Mvc\Controller\AbstractController

The AbstractController is an internal class which never
really had any functionality than to provide some basic
method for the ActionController.

If users implemented their own controllers and
extended the AbstractController directly, the further
execution led to an exception. Unless people used the
AbstractController and implemented the missing logic
of the ActionController themselves, they didn't have
a functional controller, therefore it's safe to assume
that nobody extends the AbstractController directly.

To be on the safe side however, the AbstractController
is properly deprecated and will not be removed until
TYPO3 11.0.

People are - and always have been - encouraged to
extend the ActionController.

Releases: master
Resolves: #89554
Change-Id: I86a45621f4d32249f94deec0d932a930d3a9824f
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/62162


Tested-by: Susanne Moog's avatarSusanne Moog <look@susi.dev>
Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Daniel Goerz's avatarDaniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Susanne Moog's avatarSusanne Moog <look@susi.dev>
Reviewed-by: Daniel Goerz's avatarDaniel Goerz <daniel.goerz@posteo.de>
parent 7378035e
......@@ -21,6 +21,10 @@ ignoreFiles+="sysext/form/Classes/Mvc/Property/Exception/TypeConverterException.
ignoreFiles+="sysext/core/Classes/Database/Driver/PDOStatement.php"
ignoreFiles+="sysext/core/Classes/Database/Driver/PDOConnection.php"
# both ActionController and AbstractController throw the same exceptions
# until AbstractController is removed
ignoreFiles+="sysext/extbase/Classes/Mvc/Controller/AbstractController.php"
foundNewFile=0
oldFilename=""
firstLineOfMatch=""
......
.. include:: ../../Includes.txt
====================================================================================
Deprecation: #89554 - Deprecate \TYPO3\CMS\Extbase\Mvc\Controller\AbstractController
====================================================================================
See :issue:`89554`
Description
===========
The class :php:`\TYPO3\CMS\Extbase\Mvc\Controller\AbstractController` has been marked as deprecated.
The :php:`AbstractController` is an internal class which never really had any functionality besides
providing some basic methods for the :php:`\TYPO3\CMS\Extbase\Mvc\Controller\ActionController`. Therefore
and in order to streamline the codebase of extbase, the :php:`AbstractController` will be removed
with TYPO3 11.0.
Impact
======
As all functionality of the :php:`AbstractController` has been moved to the :php:`ActionController` there is no impact
for extbase extensions that used and extended the :php:`ActionController`.
Affected Installations
======================
Installations that extended the :php:`AbstractController` directly.
Migration
=========
Extend the :php:`ActionController`.
.. index:: PHP-API, PartiallyScanned, ext:extbase
......@@ -14,6 +14,7 @@ namespace TYPO3\CMS\Extbase\Mvc\Controller;
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
......@@ -22,54 +23,74 @@ use TYPO3\CMS\Extbase\Mvc\Web\Request as WebRequest;
/**
* An abstract base class for Controllers
* @deprecated since TYPO3 10.2, will be removed in version 11.0
*/
abstract class AbstractController implements ControllerInterface
{
use PublicPropertyDeprecationTrait;
/**
* @var array
*/
private $deprecatedPublicProperties = [
'signalSlotDispatcher' => 'Property ' . self::class . '::$signalSlotDispatcher is deprecated since TYPO3 10.2 and will be removed in TYPO3 11.0',
'objectManager' => 'Property ' . self::class . '::$objectManager is deprecated since TYPO3 10.2 and will be removed in TYPO3 11.0',
'uriBuilder' => 'Property ' . self::class . '::$uriBuilder is deprecated since TYPO3 10.2 and will be removed in TYPO3 11.0',
'settings' => 'Property ' . self::class . '::$settings is deprecated since TYPO3 10.2 and will be removed in TYPO3 11.0',
'request' => 'Property ' . self::class . '::$request is deprecated since TYPO3 10.2 and will be removed in TYPO3 11.0',
'response' => 'Property ' . self::class . '::$response is deprecated since TYPO3 10.2 and will be removed in TYPO3 11.0',
'arguments' => 'Property ' . self::class . '::$arguments is deprecated since TYPO3 10.2 and will be removed in TYPO3 11.0',
'validatorResolver' => 'Property ' . self::class . '::$validatorResolver is deprecated since TYPO3 10.2 and will be removed in TYPO3 11.0',
'supportedRequestTypes' => 'Property ' . self::class . '::$supportedRequestTypes is deprecated since TYPO3 10.2 and will be removed in TYPO3 11.0',
'controllerContext' => 'Property ' . self::class . '::$controllerContext is deprecated since TYPO3 10.2 and will be removed in TYPO3 11.0',
'configurationManager' => 'Property ' . self::class . '::$configurationManager is deprecated since TYPO3 10.2 and will be removed in TYPO3 11.0',
];
/**
* @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
*/
protected $signalSlotDispatcher;
private $signalSlotDispatcher;
/**
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
*/
protected $objectManager;
private $objectManager;
/**
* @var \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder
*/
protected $uriBuilder;
private $uriBuilder;
/**
* Contains the settings of the current extension
*
* @var array
*/
protected $settings;
private $settings;
/**
* The current request.
*
* @var \TYPO3\CMS\Extbase\Mvc\RequestInterface
*/
protected $request;
private $request;
/**
* The response which will be returned by this action controller
*
* @var \TYPO3\CMS\Extbase\Mvc\ResponseInterface
*/
protected $response;
private $response;
/**
* @var \TYPO3\CMS\Extbase\Validation\ValidatorResolver
*/
protected $validatorResolver;
private $validatorResolver;
/**
* @var \TYPO3\CMS\Extbase\Mvc\Controller\Arguments Arguments passed to the controller
*/
protected $arguments;
private $arguments;
/**
* @param \TYPO3\CMS\Extbase\SignalSlot\Dispatcher $signalSlotDispatcher
......@@ -94,25 +115,30 @@ abstract class AbstractController implements ControllerInterface
*
* @var array
*/
protected $supportedRequestTypes = [\TYPO3\CMS\Extbase\Mvc\Request::class];
private $supportedRequestTypes = [\TYPO3\CMS\Extbase\Mvc\Request::class];
/**
* @var \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext
*/
protected $controllerContext;
private $controllerContext;
/**
* @return ControllerContext
*/
public function getControllerContext()
{
trigger_error(
__METHOD__ . ' is deprecated since TYPO3 10.2 and will be removed in version 11.0',
E_USER_DEPRECATED
);
return $this->controllerContext;
}
/**
* @var ConfigurationManagerInterface
*/
protected $configurationManager;
private $configurationManager;
/**
* @param ConfigurationManagerInterface $configurationManager
......@@ -143,9 +169,15 @@ abstract class AbstractController implements ControllerInterface
* @param bool $storeInSession Optional, defines whether the message should be stored in the session (default) or not
* @throws \InvalidArgumentException if the message body is no string
* @see \TYPO3\CMS\Core\Messaging\FlashMessage
* @deprecated since TYPO3 10.2 and will be removed in version 11.0
*/
public function addFlashMessage($messageBody, $messageTitle = '', $severity = \TYPO3\CMS\Core\Messaging\AbstractMessage::OK, $storeInSession = true)
{
trigger_error(
__METHOD__ . ' is deprecated since TYPO3 10.2 and will be removed in version 11.0',
E_USER_DEPRECATED
);
if (!is_string($messageBody)) {
throw new \InvalidArgumentException('The message body must be of type string, "' . gettype($messageBody) . '" given.', 1243258395);
}
......@@ -169,9 +201,15 @@ abstract class AbstractController implements ControllerInterface
*
* @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request The current request
* @return bool TRUE if this request type is supported, otherwise FALSE
* @deprecated since TYPO3 10.2 and will be removed in version 11.0
*/
public function canProcessRequest(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request)
{
trigger_error(
__METHOD__ . ' is deprecated since TYPO3 10.2 and will be removed in version 11.0',
E_USER_DEPRECATED
);
foreach ($this->supportedRequestTypes as $supportedRequestType) {
if ($request instanceof $supportedRequestType) {
return true;
......@@ -186,9 +224,15 @@ abstract class AbstractController implements ControllerInterface
* @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request The request object
* @param \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response The response, modified by this handler
* @throws UnsupportedRequestTypeException if the controller doesn't support the current request type
* @deprecated since TYPO3 10.2 and will be removed in version 11.0
*/
public function processRequest(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request, \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response)
{
trigger_error(
__METHOD__ . ' is deprecated since TYPO3 10.2 and will be removed in version 11.0',
E_USER_DEPRECATED
);
if (!$this->canProcessRequest($request)) {
throw new UnsupportedRequestTypeException(static::class . ' does not support requests of type "' . get_class($request) . '". Supported types are: ' . implode(' ', $this->supportedRequestTypes), 1187701132);
}
......@@ -209,9 +253,15 @@ abstract class AbstractController implements ControllerInterface
* Initialize the controller context
*
* @return \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext ControllerContext to be passed to the view
* @deprecated since TYPO3 10.2 and will be removed in version 11.0
*/
protected function buildControllerContext()
{
trigger_error(
__METHOD__ . ' is deprecated since TYPO3 10.2 and will be removed in version 11.0',
E_USER_DEPRECATED
);
/** @var \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext $controllerContext */
$controllerContext = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext::class);
$controllerContext->setRequest($this->request);
......@@ -236,9 +286,15 @@ abstract class AbstractController implements ControllerInterface
* @param array|null $arguments Arguments to pass to the target action
* @throws StopActionException
* @see redirect()
* @deprecated since TYPO3 10.2 and will be removed in version 11.0
*/
public function forward($actionName, $controllerName = null, $extensionName = null, array $arguments = null)
{
trigger_error(
__METHOD__ . ' is deprecated since TYPO3 10.2 and will be removed in version 11.0',
E_USER_DEPRECATED
);
$this->request->setDispatched(false);
if ($this->request instanceof WebRequest) {
$this->request->setControllerActionName($actionName);
......@@ -273,9 +329,15 @@ abstract class AbstractController implements ControllerInterface
* @throws UnsupportedRequestTypeException If the request is not a web request
* @throws StopActionException
* @see forward()
* @deprecated since TYPO3 10.2 and will be removed in version 11.0
*/
protected function redirect($actionName, $controllerName = null, $extensionName = null, array $arguments = null, $pageUid = null, $delay = 0, $statusCode = 303)
{
trigger_error(
__METHOD__ . ' is deprecated since TYPO3 10.2 and will be removed in version 11.0',
E_USER_DEPRECATED
);
if (!$this->request instanceof WebRequest) {
throw new UnsupportedRequestTypeException('redirect() only supports web requests.', 1220539734);
}
......@@ -303,9 +365,15 @@ abstract class AbstractController implements ControllerInterface
* @param int $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other
* @throws UnsupportedRequestTypeException If the request is not a web request
* @throws StopActionException
* @deprecated since TYPO3 10.2 and will be removed in version 11.0
*/
protected function redirectToUri($uri, $delay = 0, $statusCode = 303)
{
trigger_error(
__METHOD__ . ' is deprecated since TYPO3 10.2 and will be removed in version 11.0',
E_USER_DEPRECATED
);
if (!$this->request instanceof WebRequest) {
throw new UnsupportedRequestTypeException('redirect() only supports web requests.', 1220539735);
}
......@@ -335,9 +403,15 @@ abstract class AbstractController implements ControllerInterface
*
* @param string $uri The URI
* @return string
* @deprecated since TYPO3 10.2 and will be removed in version 11.0
*/
protected function addBaseUriIfNecessary($uri)
{
trigger_error(
__METHOD__ . ' is deprecated since TYPO3 10.2 and will be removed in version 11.0',
E_USER_DEPRECATED
);
return \TYPO3\CMS\Core\Utility\GeneralUtility::locationHeaderUrl((string)$uri);
}
......@@ -351,9 +425,15 @@ abstract class AbstractController implements ControllerInterface
* @param string $content Body content which further explains the status
* @throws UnsupportedRequestTypeException If the request is not a web request
* @throws StopActionException
* @deprecated since TYPO3 10.2 and will be removed in version 11.0
*/
public function throwStatus($statusCode, $statusMessage = null, $content = null)
{
trigger_error(
__METHOD__ . ' is deprecated since TYPO3 10.2 and will be removed in version 11.0',
E_USER_DEPRECATED
);
if (!$this->request instanceof WebRequest) {
throw new UnsupportedRequestTypeException('throwStatus() only supports web requests.', 1220539739);
}
......@@ -370,9 +450,15 @@ abstract class AbstractController implements ControllerInterface
/**
* Collects the base validators which were defined for the data type of each
* controller argument and adds them to the argument's validator chain.
* @deprecated since TYPO3 10.2 and will be removed in version 11.0
*/
public function initializeControllerArgumentsBaseValidators()
{
trigger_error(
__METHOD__ . ' is deprecated since TYPO3 10.2 and will be removed in version 11.0',
E_USER_DEPRECATED
);
/** @var \TYPO3\CMS\Extbase\Mvc\Controller\Argument $argument */
foreach ($this->arguments as $argument) {
$validator = $this->validatorResolver->getBaseValidatorConjunction($argument->getDataType());
......@@ -386,9 +472,15 @@ abstract class AbstractController implements ControllerInterface
* Maps arguments delivered by the request object to the local controller arguments.
*
* @throws Exception\RequiredArgumentMissingException
* @deprecated since TYPO3 10.2 and will be removed in version 11.0
*/
protected function mapRequestArgumentsToControllerArguments()
{
trigger_error(
__METHOD__ . ' is deprecated since TYPO3 10.2 and will be removed in version 11.0',
E_USER_DEPRECATED
);
/** @var \TYPO3\CMS\Extbase\Mvc\Controller\Argument $argument */
foreach ($this->arguments as $argument) {
$argumentName = $argument->getName();
......
......@@ -17,8 +17,10 @@ namespace TYPO3\CMS\Extbase\Mvc\Controller;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
use TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException;
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
use TYPO3\CMS\Extbase\Mvc\Web\ReferringRequest;
use TYPO3\CMS\Extbase\Mvc\Web\Request as WebRequest;
......@@ -30,7 +32,7 @@ use TYPO3Fluid\Fluid\View\TemplateView;
/**
* A multi action controller. This is by far the most common base class for Controllers.
*/
class ActionController extends AbstractController
class ActionController implements ControllerInterface
{
/**
* @var \TYPO3\CMS\Extbase\Reflection\ReflectionService
......@@ -572,4 +574,340 @@ class ActionController extends AbstractController
$outputMessage = 'Validation failed while trying to call ' . static::class . '->' . $this->actionMethodName . '().' . PHP_EOL;
return $outputMessage;
}
/**
* @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
*/
protected $signalSlotDispatcher;
/**
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
*/
protected $objectManager;
/**
* @var \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder
*/
protected $uriBuilder;
/**
* Contains the settings of the current extension
*
* @var array
*/
protected $settings;
/**
* @var \TYPO3\CMS\Extbase\Validation\ValidatorResolver
*/
protected $validatorResolver;
/**
* @var \TYPO3\CMS\Extbase\Mvc\Controller\Arguments Arguments passed to the controller
*/
protected $arguments;
/**
* @param \TYPO3\CMS\Extbase\SignalSlot\Dispatcher $signalSlotDispatcher
*/
public function injectSignalSlotDispatcher(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher $signalSlotDispatcher)
{
$this->signalSlotDispatcher = $signalSlotDispatcher;
}
/**
* @param \TYPO3\CMS\Extbase\Validation\ValidatorResolver $validatorResolver
*/
public function injectValidatorResolver(\TYPO3\CMS\Extbase\Validation\ValidatorResolver $validatorResolver)
{
$this->validatorResolver = $validatorResolver;
}
/**
* An array of supported request types. By default only web requests are supported.
* Modify or replace this array if your specific controller supports certain
* (additional) request types.
*
* @var array
*/
protected $supportedRequestTypes = [\TYPO3\CMS\Extbase\Mvc\Request::class];
/**
* @var \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext
*/
protected $controllerContext;
/**
* @return ControllerContext
*/
public function getControllerContext()
{
return $this->controllerContext;
}
/**
* @var ConfigurationManagerInterface
*/
protected $configurationManager;
/**
* @param ConfigurationManagerInterface $configurationManager
*/
public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
{
$this->configurationManager = $configurationManager;
$this->settings = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS);
}
/**
* Injects the object manager
*
* @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
*/
public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager)
{
$this->objectManager = $objectManager;
$this->arguments = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\Controller\Arguments::class);
}
/**
* Creates a Message object and adds it to the FlashMessageQueue.
*
* @param string $messageBody The message
* @param string $messageTitle Optional message title
* @param int $severity Optional severity, must be one of \TYPO3\CMS\Core\Messaging\FlashMessage constants
* @param bool $storeInSession Optional, defines whether the message should be stored in the session (default) or not
* @throws \InvalidArgumentException if the message body is no string
* @see \TYPO3\CMS\Core\Messaging\FlashMessage
*/
public function addFlashMessage($messageBody, $messageTitle = '', $severity = \TYPO3\CMS\Core\Messaging\AbstractMessage::OK, $storeInSession = true)
{
if (!is_string($messageBody)) {
throw new \InvalidArgumentException('The message body must be of type string, "' . gettype($messageBody) . '" given.', 1243258395);
}
/* @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */
$flashMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
\TYPO3\CMS\Core\Messaging\FlashMessage::class,
(string)$messageBody,
(string)$messageTitle,
$severity,
$storeInSession
);
$this->controllerContext->getFlashMessageQueue()->enqueue($flashMessage);
}
/**
* Checks if the current request type is supported by the controller.
*
* If your controller only supports certain request types, either
* replace / modify the supportedRequestTypes property or override this
* method.
*
* @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request The current request
* @return bool TRUE if this request type is supported, otherwise FALSE
*/
public function canProcessRequest(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request)
{
foreach ($this->supportedRequestTypes as $supportedRequestType) {
if ($request instanceof $supportedRequestType) {
return true;
}
}
return false;
}
/**
* Initialize the controller context
*
* @return \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext ControllerContext to be passed to the view
*/
protected function buildControllerContext()
{
/** @var \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext $controllerContext */
$controllerContext = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext::class);
$controllerContext->setRequest($this->request);
$controllerContext->setResponse($this->response);
if ($this->arguments !== null) {
$controllerContext->setArguments($this->arguments);
}
$controllerContext->setUriBuilder($this->uriBuilder);
return $controllerContext;
}
/**
* Forwards the request to another action and / or controller.
*
* Request is directly transferred to the other action / controller
* without the need for a new request.
*
* @param string $actionName Name of the action to forward to
* @param string|null $controllerName Unqualified object name of the controller to forward to. If not specified, the current controller is used.
* @param string|null $extensionName Name of the extension containing the controller to forward to. If not specified, the current extension is assumed.
* @param array|null $arguments Arguments to pass to the target action
* @throws StopActionException
* @see redirect()
*/
public function forward($actionName, $controllerName = null, $extensionName = null, array $arguments = null)
{
$this->request->setDispatched(false);
if ($this->request instanceof WebRequest) {
$this->request->setControllerActionName($actionName);
if ($controllerName !== null) {
$this->request->setControllerName($controllerName);
}
if ($extensionName !== null) {
$this->request->setControllerExtensionName($extensionName);
}
}
if ($arguments !== null) {
$this->request->setArguments($arguments);
}
throw new StopActionException('forward', 1476045801);
}
/**
* Redirects the request to another action and / or controller.
*
* Redirect will be sent to the client which then performs another request to the new URI.
*
* NOTE: This method only supports web requests and will thrown an exception
* if used with other request types.
*
* @param string $actionName Name of the action to forward to
* @param string|null $controllerName Unqualified object name of the controller to forward to. If not specified, the current controller is used.
* @param string|null $extensionName Name of the extension containing the controller to forward to. If not specified, the current extension is assumed.
* @param array|null $arguments Arguments to pass to the target action
* @param int|null $pageUid Target page uid. If NULL, the current page uid is used
* @param int $delay (optional) The delay in seconds. Default is no delay.
* @param int $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other
* @throws UnsupportedRequestTypeException If the request is not a web request
* @throws StopActionException
* @see forward()
*/
protected function redirect($actionName, $controllerName = null, $extensionName = null, array $arguments = null, $pageUid = null, $delay = 0, $statusCode = 303)
{
if (!$this->request instanceof WebRequest) {
throw new UnsupportedRequestTypeException('redirect() only supports web requests.', 1220539734);
}
if ($controllerName === null) {
$controllerName = $this->request->getControllerName();
}
$this->uriBuilder->reset()->setCreateAbsoluteUri(true);
if (MathUtility::canBeInterpretedAsInteger($pageUid)) {
$this->uriBuilder->setTargetPageUid((int)$pageUid);