Commit b9f5c89f authored by Christian Kuhn's avatar Christian Kuhn
Browse files

[TASK] Deprecate extbase setDispatched() and isDispatched()

Extbase Request setDispatched() and isDispatched()
violate the PSR-7 'immutable' concept and need to fall.

With the changes from #92502 where extbase actions
usually return a ResponseInterface, together with the
deprecation of StopActionException in #94351, we don't
need this information in the Request anymore: It can
be handled internally within the dispatcher, depending
on the type of the response.

The patch deprecates the two methods in extbase request
and adapts usages towards an internal flag. We
throw a deprecation warning since the flag is needed for
b/w compat in v11, though.

Resolves: #94394
Related: #94351
Related: #92502
Releases: master
Change-Id: I1c70daa7f5b0c55e17e4b7c815d260ca68cef23c
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/69470

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: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Jochen's avatarJochen <rothjochen@gmail.com>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
parent 936eb708
.. include:: ../../Includes.txt
========================================================================
Deprecation: #94394 - Extbase Request setDispatched() and isDispatched()
========================================================================
See :issue:`94394`
Description
===========
To further prepare towards PSR-7 requests in extbase, the two
methods :php:`TYPO3\CMS\Extbase\Mvc\Request->setDispatched()` and
:php:`TYPO3\CMS\Extbase\Mvc\Request->isDispatched()` have been
marked as deprecated.
Impact
======
Using the methods is discouraged. The extbase dispatcher still
recognizes them and acts accordingly, the methods do NOT raise
a deprecation level log entry, though.
Affected Installations
======================
Some extbase based extensions may use :php:`setDispatched()`, but
it's rather unlikely since that flag has been mostly used internally
through existing helper methods in extbase controllers.
The extension scanner will find possible candidates.
Migration
=========
Action dispatching in extbase now depends on the returned response:
* A casual 2xx Response from a controller action that for instance contains HTML
or Json stops extbase dispatching, the response is later returned to the client.
* An extbase :php:`ForwardResponse` instructs the dispatcher to dispatch
internally to another controller action.
* A 3xx :php:`RedirectResponse` stops dispatching and is returned to the client
to initiate some client redirect.
.. index:: PHP-API, FullyScanned, ext:extbase
......@@ -17,6 +17,9 @@ namespace OliverHader\IrreTutorial\Controller;
use OliverHader\IrreTutorial\Domain\Repository\ContentRepository;
use OliverHader\IrreTutorial\Service\QueueService;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\Http\Response;
use TYPO3\CMS\Core\Http\Stream;
use TYPO3\CMS\Extbase\Http\ForwardResponse;
use TYPO3\CMS\Extbase\Mvc\View\JsonView;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory;
......@@ -46,7 +49,7 @@ class QueueController extends AbstractController
$this->persistenceManager = $persistenceManager;
}
public function indexAction()
public function indexAction(): ResponseInterface
{
$calls = [];
$calls[] = ['Content', 'list'];
......@@ -59,7 +62,7 @@ class QueueController extends AbstractController
return new ForwardResponse('process');
}
public function processAction()
public function processAction(): ResponseInterface
{
$call = $this->queueService->shift();
if ($call === null) {
......@@ -73,16 +76,21 @@ class QueueController extends AbstractController
$arguments = $call[2] ?? null;
if (is_array($arguments)) {
$response = $response->withArguments($arguments);
$response = $response->withArguments($arguments);
}
return $response;
}
public function finishAction()
public function finishAction(): ResponseInterface
{
$this->request->setDispatched(true);
$typoScriptFrontendController = $GLOBALS['TSFE'];
$typoScriptFrontendController->setContentType('application/json');
$value = $this->queueService->getValues();
$this->view->assign('value', $value);
$body = new Stream('php://temp', 'rw');
$body->write($this->view->render());
return new Response($body);
}
}
......@@ -446,6 +446,7 @@ abstract class ActionController implements ControllerInterface
public function processRequest(RequestInterface $request): ResponseInterface
{
$this->request = $request;
// @deprecated since v11, will be removed in v12.
$this->request->setDispatched(true);
$this->uriBuilder = $this->objectManager->get(UriBuilder::class);
$this->uriBuilder->setRequest($request);
......
......@@ -19,6 +19,7 @@ use Psr\Container\ContainerInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\Http\RedirectResponse;
use TYPO3\CMS\Core\Http\Response;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Extbase\Annotation\IgnoreValidation;
use TYPO3\CMS\Extbase\Event\Mvc\AfterRequestDispatchedEvent;
......@@ -83,7 +84,9 @@ class Dispatcher implements SingletonInterface
public function dispatch(RequestInterface $request): ResponseInterface
{
$dispatchLoopCount = 0;
while (!$request->isDispatched()) {
$isDispatched = false;
// @deprecated since v11, will be changed in v12 to: while (!$isDispatched) {
while (!$isDispatched || !$request->isDispatched()) {
if ($dispatchLoopCount++ > 99) {
throw new InfiniteLoopException('Could not ultimately dispatch the request after ' . $dispatchLoopCount . ' iterations. Most probably, a @' . IgnoreValidation::class . ' annotation is missing on re-displaying a form with validation errors.', 1217839467);
}
......@@ -94,23 +97,22 @@ class Dispatcher implements SingletonInterface
// The controller action returned an extbase internal Forward response:
// Another action should be dispatched.
$request = static::buildRequestFromCurrentRequestAndForwardResponse($request, $response);
}
if ($response instanceof RedirectResponse) {
} elseif ($response instanceof RedirectResponse) {
// The controller action returned a core HTTP redirect response.
// Dispatching ends here and response is sent to client.
return $response;
$isDispatched = true;
} else {
// Some casual response returned by action.
// Dispatching ends here and response is sent to client.
$isDispatched = true;
}
} catch (StopActionException $ignoredException) {
// @deprecated since v11, will be removed in v12
$isDispatched = true;
$response = $ignoredException->getResponse();
}
}
if (!isset($response)) {
// This fallback is no longer needed once the StopActionException is removed and replaced with proper
// redirect and forward response objects and we always get a response back from the controller.
$response = new \TYPO3\CMS\Core\Http\Response();
}
$this->eventDispatcher->dispatch(new AfterRequestDispatchedEvent($request, $response));
return $response;
}
......@@ -147,6 +149,7 @@ class Dispatcher implements SingletonInterface
public static function buildRequestFromCurrentRequestAndForwardResponse(Request $currentRequest, ForwardResponse $forwardResponse): Request
{
$request = clone $currentRequest;
// @deprecated since v11, will be removed in v12.
$request->setDispatched(false);
$request->setControllerActionName($forwardResponse->getActionName());
......
......@@ -79,6 +79,7 @@ class Request implements RequestInterface
/**
* @var bool If this request has been changed and needs to be dispatched again
* @deprecated since v11, will be removed in v12.
*/
protected $dispatched = false;
......@@ -100,6 +101,7 @@ class Request implements RequestInterface
* Sets the dispatched flag
*
* @param bool $flag If this request has been dispatched
* @deprecated since v11, will be removed in v12.
*/
public function setDispatched($flag)
{
......@@ -114,6 +116,7 @@ class Request implements RequestInterface
* addressed yet.
*
* @return bool TRUE if this request has been dispatched successfully
* @deprecated since v11, will be removed in v12.
*/
public function isDispatched()
{
......
......@@ -24,6 +24,7 @@ interface RequestInterface
* Sets the dispatched flag
*
* @param bool $flag If this request has been dispatched
* @deprecated since v11, will be removed in v12.
*/
public function setDispatched($flag);
......@@ -35,6 +36,7 @@ interface RequestInterface
* addressed yet.
*
* @return bool TRUE if this request has been dispatched successfully
* @deprecated since v11, will be removed in v12.
*/
public function isDispatched();
......
......@@ -4837,4 +4837,18 @@ return [
'Deprecation-94377-ExtbaseObjectManager-getEmptyObject.rst'
],
],
'TYPO3\CMS\Extbase\Mvc\Request->setDispatched' => [
'numberOfMandatoryArguments' => 1,
'maximumNumberOfArguments' => 1,
'restFiles' => [
'Deprecation-94394-ExtbaseRequestSetDispatchedAndIsDispatched.rst'
],
],
'TYPO3\CMS\Extbase\Mvc\Request->isDispatched' => [
'numberOfMandatoryArguments' => 0,
'maximumNumberOfArguments' => 0,
'restFiles' => [
'Deprecation-94394-ExtbaseRequestSetDispatchedAndIsDispatched.rst'
],
],
];
Markdown is supported
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