Commit 29cb01c6 authored by Christian Kuhn's avatar Christian Kuhn
Browse files

[TASK] Deprecate extbase ControllerContext

The Extbase ControllerContext is a dependency between
Extbase and Fluid to communicate state. It is wired
into various view related classes.

To further decouple fluid from extbase, this class
needs to fall. A couple of previous patches deprecated
parts of the class already, this patch deprecates the
rest.

The fluid RenderingContext can be used in view helpers
in almost all cases as substitution, especially since
extbase request implements PSR-7 ServerRequestInterface.

The core itself has no direct usages of ControllerContext
anymore, it is only moved around at various places.

Change-Id: Ic4af492b9818003321ceeb6c9e6dcd29c5662271
Resolves: #95139
Related: #93019
Related: #93016
Related: #94428
Related: #92826
Releases: master
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70956

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>
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: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
parent 41060458
......@@ -80,6 +80,7 @@ class BackendTemplateView implements ViewInterface
* Sets the current controller context
*
* @param \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext $controllerContext Controller context which is available inside the view
* @deprecated since v11, will be removed with v12.
*/
public function setControllerContext(ControllerContext $controllerContext)
{
......
.. include:: ../../Includes.txt
===============================================
Deprecation: #95139 - Extbase ControllerContext
===============================================
See :issue:`95139`
Description
===========
The Extbase related class :php:`TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext`
has been used in the past to transfer data between extbase controllers and fluid
views. It has been superseded by class :php:`TYPO3\CMS\Fluid\Core\Rendering\RenderingContext`
with various preparation patches. To further decouple Fluid from Extbase, class
:php:`ControllerContext` has been marked as deprecated.
Impact
======
Accessing :php:`ControllerContext` and consuming information carried in it has
been marked deprecated. The class will be removed in v12. The object is bound
to various Fluid view related classes and all occurrences have been marked with
an :php:`@deprecated` annotation.
To retain backwards compatibility, accessing :php:`ControllerContext` does not
actively trigger a deprecation level error in most cases, though.
Affected Installations
======================
Instances with extensions that access :php:`ControllerContext` are affected. This
typically affects extensions which provide own view helpers. The extension scanner
should find possible matches.
Migration
=========
Two getters of the class have already been deprecated with previous patches, namely
:php:`->getUriBuilder()` as documented with :doc:`->getFlashMessageQueue()`. Classes
should inject instances of these objects instead, or should :php:`makeInstance()` them.
Method :php:`getRequest()` is available in controllers directly, and view helpers
receive the current request by calling :php:`RenderingContext->getRequest()`.
Method :php:`getArguments()` returns the Extbase :php:`Arguments` created by the
:php:`ActionController`. The getter has become mostly useless within fluid context
since argument validation of forms is abstracted differently since various core versions.
If that object construct is still needed, it should be transferred differently to
consuming classes, for instance by assigning it as variable to the view and accessing
it in a view helper using the variable container. In many cases it should be sufficient
to directly work with the request object instead.
.. index:: Fluid, PHP-API, PartiallyScanned, ext:extbase
......@@ -173,6 +173,7 @@ abstract class ActionController implements ControllerInterface
/**
* @var ControllerContext
* @internal only to be used within Extbase, not part of TYPO3 Core API.
* @deprecated since v11, will be removed with v12.
*/
protected $controllerContext;
......@@ -467,6 +468,7 @@ abstract class ActionController implements ControllerInterface
$callable();
}
$this->mapRequestArgumentsToControllerArguments();
// @deprecated since v11, will be removed with v12.
$this->controllerContext = $this->buildControllerContext();
$this->view = $this->resolveView();
if ($this->view !== null) {
......@@ -621,6 +623,7 @@ abstract class ActionController implements ControllerInterface
if ($view instanceof ViewInterface) {
$this->setViewConfiguration($view);
}
// @deprecated since v11, will be removed with v12.
$view->setControllerContext($this->controllerContext);
if (method_exists($view, 'injectSettings')) {
$view->injectSettings($this->settings);
......@@ -818,6 +821,7 @@ abstract class ActionController implements ControllerInterface
/**
* @return ControllerContext
* @deprecated since v11, will be removed with v12.
*/
public function getControllerContext()
{
......@@ -877,6 +881,7 @@ abstract class ActionController implements ControllerInterface
* @return ControllerContext ControllerContext to be passed to the view
*
* @internal only to be used within Extbase, not part of TYPO3 Core API.
* @deprecated since v11, will be removed with v12.
*/
protected function buildControllerContext()
{
......
......@@ -23,6 +23,8 @@ use TYPO3\CMS\Extbase\Service\ExtensionService;
/**
* The controller context contains information from the controller
*
* @deprecated since v11, will be removed with v12
*/
class ControllerContext
{
......@@ -126,8 +128,6 @@ class ControllerContext
*/
public function getUriBuilder()
{
// todo: trigger an error as soon as this whole object can be deprecated
if (!$this->uriBuilder) {
$this->uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
if ($this->request) {
......@@ -144,8 +144,6 @@ class ControllerContext
*/
public function getFlashMessageQueue($identifier = null)
{
// todo: trigger an error as soon as this whole object can be deprecated
if ($identifier === null) {
if ($this->flashMessageQueueDefaultIdentifier === null) {
// cache the default-identifier for performance-reasons
......
......@@ -161,6 +161,7 @@ class JsonView implements ViewInterface
/**
* @var ControllerContext
* @deprecated since v11, will be removed with v12.
*/
protected $controllerContext;
......@@ -185,6 +186,7 @@ class JsonView implements ViewInterface
* Sets the current controller context
*
* @param ControllerContext $controllerContext
* @deprecated since v11, will be removed with v12.
*/
public function setControllerContext(ControllerContext $controllerContext)
{
......
......@@ -27,6 +27,7 @@ interface ViewInterface
*
* @param ControllerContext $controllerContext
* @internal
* @deprecated since v11, will be removed with v12.
*/
public function setControllerContext(ControllerContext $controllerContext);
......
......@@ -59,6 +59,7 @@ services:
factory: ['@TYPO3\CMS\Core\Cache\CacheManager', 'getCache']
arguments: ['extbase']
# @deprecated since v11, will be removed in v12
TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext:
public: true
shared: false
......
......@@ -79,7 +79,7 @@ class ActionControllerTest extends FunctionalTestCase
$this->subject->processRequest($this->request);
// Assertions
$arguments = $this->subject->getControllerContext()->getArguments();
$arguments = $this->subject->getArguments();
$argument = $arguments->getArgument('barParam');
/** @var ConjunctionValidator $validator */
......@@ -107,7 +107,7 @@ class ActionControllerTest extends FunctionalTestCase
$this->subject->processRequest($this->request);
// Assertions
$arguments = $this->subject->getControllerContext()->getArguments();
$arguments = $this->subject->getArguments();
$argument = $arguments->getArgument('bazParam');
/** @var ConjunctionValidator $validator */
......
......@@ -20,6 +20,7 @@ namespace ExtbaseTeam\ActionControllerTest\Controller;
use ExtbaseTeam\ActionControllerTest\Domain\Model\Model;
use TYPO3\CMS\Extbase\Annotation as Extbase;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Mvc\Controller\Arguments;
use TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfiguration;
use TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter;
......@@ -28,6 +29,11 @@ use TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter;
*/
class TestController extends ActionController
{
public function getArguments(): Arguments
{
return $this->arguments;
}
public function initializeFooAction()
{
/** @var MvcPropertyMappingConfiguration $propertyMappingConfiguration */
......
......@@ -309,6 +309,7 @@ class ActionControllerTest extends UnitTestCase
$mockController->injectConfigurationManager($mockConfigurationManager);
$mockController->_set('request', $this->createMock(Request::class), ['getControllerExtensionKey']);
$view = $this->getMockBuilder(ViewInterface::class)
// @deprecated since v11, will be removed with v12: Drop setControllerContext from list
->onlyMethods(['setControllerContext', 'assign', 'assignMultiple', 'render', 'initializeView'])
->addMethods(['setTemplateRootPaths'])
->getMock();
......@@ -388,6 +389,7 @@ class ActionControllerTest extends UnitTestCase
$mockController->injectConfigurationManager($mockConfigurationManager);
$mockController->_set('request', $this->createMock(Request::class), ['getControllerExtensionKey']);
$view = $this->getMockBuilder(ViewInterface::class)
// @deprecated since v11, will be removed with v12: Drop setControllerContext from list
->onlyMethods(['setControllerContext', 'assign', 'assignMultiple', 'render', 'initializeView'])
->addMethods(['setlayoutRootPaths'])
->getMock();
......@@ -467,6 +469,7 @@ class ActionControllerTest extends UnitTestCase
$mockController->injectConfigurationManager($mockConfigurationManager);
$mockController->_set('request', $this->createMock(Request::class), ['getControllerExtensionKey']);
$view = $this->getMockBuilder(ViewInterface::class)
// @deprecated since v11, will be removed with v12: Drop setControllerContext from list
->onlyMethods(['setControllerContext', 'assign', 'assignMultiple', 'render', 'initializeView'])
->addMethods(['setpartialRootPaths'])
->getMock();
......
......@@ -39,6 +39,7 @@ class RenderingContext extends \TYPO3Fluid\Fluid\Core\Rendering\RenderingContext
* Controller context being passed to the ViewHelper
*
* @var ControllerContext
* @deprecated since v11, will be removed with v12.
*/
protected $controllerContext;
......@@ -136,8 +137,6 @@ class RenderingContext extends \TYPO3Fluid\Fluid\Core\Rendering\RenderingContext
*/
public function getControllerContext()
{
// todo: trigger an error as soon as ControllerContext is deprecated
if ($this->controllerContext) {
return $this->controllerContext;
}
......@@ -195,12 +194,19 @@ class RenderingContext extends \TYPO3Fluid\Fluid\Core\Rendering\RenderingContext
* Set the controller context which will be passed to the ViewHelper
*
* @param ControllerContext $controllerContext The controller context to set
* @deprecated since v11, will be removed with v12.
*/
public function setControllerContext(ControllerContext $controllerContext)
{
$request = $controllerContext->getRequest();
$this->controllerContext = $controllerContext;
$this->setRequest($request);
if ($this->request === null) {
trigger_error(
'Setting request from controllerContext in class ' . __CLASS__ . ' is deprecated. Use setRequest() directly.',
E_USER_DEPRECATED
);
$request = $controllerContext->getRequest();
$this->setRequest($request);
}
}
/**
......@@ -216,6 +222,7 @@ class RenderingContext extends \TYPO3Fluid\Fluid\Core\Rendering\RenderingContext
$this->setControllerName($request->getControllerName());
// Also ensure that controller context is filled, if not set yet.
if ($this->controllerContext === null) {
// @deprecated since v11, will be removed with v12.
$this->controllerContext = GeneralUtility::makeInstance(ControllerContext::class);
$this->controllerContext->setRequest($request);
}
......
......@@ -33,6 +33,7 @@ abstract class AbstractTemplateView extends Typo3FluidAbstractTemplateView imple
{
/**
* @var \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext
* @deprecated since v11, will be removed with v12.
*/
protected $controllerContext;
......@@ -76,14 +77,19 @@ abstract class AbstractTemplateView extends Typo3FluidAbstractTemplateView imple
*
* @param \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext $controllerContext
* @internal
* @deprecated since v11, will be removed with v12.
*/
public function setControllerContext(ControllerContext $controllerContext)
{
$request = $controllerContext->getRequest();
$this->controllerContext = $controllerContext;
// @todo: Move these two lines elsewhere when dropping the method
$this->baseRenderingContext->getTemplatePaths()->fillDefaultsByPackageName($request->getControllerExtensionKey());
$this->baseRenderingContext->getTemplatePaths()->setFormat($request->getFormat());
if ($this->baseRenderingContext instanceof RenderingContext) {
$this->baseRenderingContext->setRequest($request);
$this->baseRenderingContext->setControllerContext($controllerContext);
}
}
......
......@@ -17,7 +17,6 @@ declare(strict_types=1);
namespace TYPO3\CMS\Fluid\Tests\Unit\Core\Rendering;
use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
use TYPO3\CMS\Extbase\Mvc\Request;
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContext;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
......@@ -55,19 +54,6 @@ class RenderingContextTest extends UnitTestCase
self::assertSame($this->renderingContext->getVariableProvider(), $templateVariableContainer, 'Template Variable Container could not be read out again.');
}
/**
* @test
*/
public function controllerContextCanBeReadCorrectly()
{
$controllerContext = $this->getMockBuilder(ControllerContext::class)
->disableOriginalConstructor()
->getMock();
$controllerContext->expects(self::atLeastOnce())->method('getRequest')->willReturn($this->createMock(Request::class));
$this->renderingContext->setControllerContext($controllerContext);
self::assertSame($this->renderingContext->getControllerContext(), $controllerContext);
}
/**
* @test
*/
......@@ -93,9 +79,7 @@ class RenderingContextTest extends UnitTestCase
$request = $this->getMockBuilder(Request::class)->getMock();
$request->expects(self::exactly(2))->method('setControllerActionName')->with(lcfirst($expected));
$request->expects(self::exactly(2))->method('getControllerActionName')->willReturn(lcfirst($expected));
$controllerContext = $this->getMockBuilder(ControllerContext::class)->onlyMethods(['getRequest'])->getMock();
$controllerContext->expects(self::atLeastOnce())->method('getRequest')->willReturn($request);
$subject->setControllerContext($controllerContext);
$subject->setRequest($request);
$subject->setControllerAction($input);
self::assertSame(lcfirst($expected), $subject->getControllerAction());
}
......
<?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\Fluid\Tests\UnitDeprecated\Core\Rendering;
use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
use TYPO3\CMS\Extbase\Mvc\Request;
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContext;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
/**
* Test case
*/
class RenderingContextTest extends UnitTestCase
{
/**
* Parsing state
*
* @var RenderingContext
*/
protected $renderingContext;
protected function setUp(): void
{
parent::setUp();
$this->renderingContext = $this->getMockBuilder(RenderingContext::class)
->addMethods(['dummy'])
->disableOriginalConstructor()
->getMock();
}
/**
* @test
* @deprecated since v11, will be removed with v12.
*/
public function controllerContextCanBeReadCorrectly()
{
$controllerContext = $this->getMockBuilder(ControllerContext::class)
->disableOriginalConstructor()
->getMock();
$controllerContext->expects(self::atLeastOnce())->method('getRequest')->willReturn($this->createMock(Request::class));
$this->renderingContext->setControllerContext($controllerContext);
self::assertSame($this->renderingContext->getControllerContext(), $controllerContext);
}
}
......@@ -494,6 +494,7 @@ class FormEditorController extends AbstractBackendController
$insertRenderablesPanelConfiguration = $this->getInsertRenderablesPanelConfiguration($formEditorDefinitions['formElements']);
$view = GeneralUtility::makeInstance(TemplateView::class);
// @deprecated since v11, will be removed with v12.
$view->setControllerContext(clone $this->controllerContext);
$view->getRenderingContext()->getTemplatePaths()->fillFromConfigurationArray($fluidConfiguration);
$view->setTemplatePathAndFilename($fluidConfiguration['templatePathAndFilename']);
......
......@@ -51,6 +51,7 @@ class FinisherContext
/**
* The assigned controller context which might be needed by the finisher.
* @deprecated since v11, will be removed with v12.
*/
protected ControllerContext $controllerContext;
......@@ -63,13 +64,14 @@ class FinisherContext
/**
* @param FormRuntime $formRuntime
* @param ControllerContext $controllerContext
* @param ControllerContext $controllerContext @deprecated since v11, will be removed with v12.
* @param Request $request
* @internal
*/
public function __construct(FormRuntime $formRuntime, ControllerContext $controllerContext, Request $request)
{
$this->formRuntime = $formRuntime;
// @deprecated since v11, will be removed with v12.
$this->controllerContext = $controllerContext;
$this->request = $request;
$this->finisherVariableProvider = GeneralUtility::makeInstance(FinisherVariableProvider::class);
......
......@@ -207,7 +207,7 @@ use TYPO3\CMS\Form\Mvc\ProcessingRule;
*
* /---code php
* # $currentRequest and $currentResponse need to be available, f.e. inside a controller you would
* # use $this->request. Inside a ViewHelper you would use $this->controllerContext->getRequest()
* # use $this->request. Inside a ViewHelper you would use $this->renderingContext->getRequest()
* $form = $formDefinition->bind($currentRequest);
*
* # now, you can use the $form object to get information about the currently
......
......@@ -37,6 +37,7 @@ abstract class AbstractElementRenderer implements RendererInterface
* The assigned controller context which might be needed by the renderer.
*
* @var \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext
* @deprecated since v11, will be removed with v12.
*/
protected $controllerContext;
......@@ -49,6 +50,7 @@ abstract class AbstractElementRenderer implements RendererInterface
* Set the controller context which should be used
*
* @param \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext $controllerContext
* @deprecated since v11, will be removed with v12.
*/
public function setControllerContext(ControllerContext $controllerContext)
{
......
......@@ -145,6 +145,7 @@ class FluidFormRenderer extends AbstractElementRenderer
$renderingOptions = $this->formRuntime->getRenderingOptions();
$view = GeneralUtility::makeInstance(TemplateView::class);
// @deprecated since v11, will be removed with v12.
$view->setControllerContext($this->controllerContext);
if (!isset($renderingOptions['templateRootPaths'])) {
......
......@@ -38,6 +38,7 @@ interface RendererInterface
* Set the controller context which should be used
*
* @param ControllerContext $controllerContext
* @deprecated since v11, will be removed with v12.
*/
public function setControllerContext(ControllerContext $controllerContext);
......
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