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

[TASK] Deprecate extbase ViewInterface

The extbase ViewInterface fits little purpose: Most
methods are part of the fluid based class and interface
chain, with the exception of setControllerContext(),
which is deprecated, and initializeView(), which is
always only implemented as empty method.

The patch deprecates the interface keeping its usage
in API classes to prevent compatibility issues and
prepares the interface removal for v12.

Change-Id: I012ad0307f7a40923a793f55b596a27e8b770bf4
Resolves: #95222
Releases: master
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/71089

Tested-by: Jochen's avatarJochen <rothjochen@gmail.com>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
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 41c28016
......@@ -35,7 +35,6 @@ use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Messaging\FlashMessageService;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
use TYPO3\CMS\Fluid\View\StandaloneView;
/**
......@@ -122,7 +121,7 @@ class MfaConfigurationController extends AbstractMfaController
/**
* Setup the overview with all available MFA providers
*/
public function overviewAction(ServerRequestInterface $request, ViewInterface $view): ResponseInterface
public function overviewAction(ServerRequestInterface $request, StandaloneView $view): ResponseInterface
{
$this->addOverviewButtons($request);
$view->assignMultiple([
......@@ -138,7 +137,7 @@ class MfaConfigurationController extends AbstractMfaController
/**
* Render form to setup a provider by using provider specific content
*/
public function setupAction(ServerRequestInterface $request, MfaProviderManifestInterface $mfaProvider, ViewInterface $view): ResponseInterface
public function setupAction(ServerRequestInterface $request, MfaProviderManifestInterface $mfaProvider, StandaloneView $view): ResponseInterface
{
$this->addFormButtons();
$propertyManager = MfaProviderPropertyManager::create($mfaProvider, $this->getBackendUser());
......@@ -227,7 +226,7 @@ class MfaConfigurationController extends AbstractMfaController
/**
* Render form to edit a provider by using provider specific content
*/
public function editAction(ServerRequestInterface $request, MfaProviderManifestInterface $mfaProvider, ViewInterface $view): ResponseInterface
public function editAction(ServerRequestInterface $request, MfaProviderManifestInterface $mfaProvider, StandaloneView $view): ResponseInterface
{
$propertyManager = MfaProviderPropertyManager::create($mfaProvider, $this->getBackendUser());
if ($mfaProvider->isLocked($propertyManager)) {
......@@ -273,7 +272,7 @@ class MfaConfigurationController extends AbstractMfaController
/**
* Initialize the standalone view and set the template name
*/
protected function initializeView(string $templateName): ViewInterface
protected function initializeView(string $templateName): StandaloneView
{
$view = GeneralUtility::makeInstance(StandaloneView::class);
$view->setTemplateRootPaths(['EXT:backend/Resources/Private/Templates/Mfa']);
......
......@@ -34,7 +34,7 @@ use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Localization\Locales;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
use TYPO3\CMS\Fluid\View\StandaloneView;
/**
* Controller responsible for rendering and processing password reset requests
......@@ -44,7 +44,7 @@ use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
class ResetPasswordController
{
protected string $loginProvider = '';
protected ?ViewInterface $view = null;
protected ?StandaloneView $view = null;
protected ?ModuleTemplate $moduleTemplate = null;
protected Context $context;
......
......@@ -132,7 +132,9 @@ class BackendTemplateView implements ViewInterface
*/
public function initializeView()
{
$this->templateView->initializeView();
if (method_exists($this->templateView, 'initializeView')) {
$this->templateView->initializeView();
}
}
/**
......
......@@ -124,6 +124,7 @@ class BackendUserController extends ActionController
/**
* Assign default variables to view
* @param ViewInterface $view
* @todo v12: Change signature to TYPO3Fluid\Fluid\View\ViewInterface when extbase ViewInterface is dropped.
*/
protected function initializeView(ViewInterface $view): void
{
......
......@@ -29,7 +29,6 @@ use TYPO3\CMS\Core\Authentication\Mfa\MfaViewType;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Http\HtmlResponse;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
use TYPO3\CMS\Fluid\View\StandaloneView;
/**
......@@ -258,11 +257,8 @@ class TotpProvider implements MfaProviderInterface
* Generate a new shared secret, generate the otpauth URL and create a qr-code
* for improved usability. Set template and assign necessary variables for the
* setup view.
*
* @param ViewInterface $view
* @param MfaProviderPropertyManager $propertyManager
*/
protected function prepareSetupView(ViewInterface $view, MfaProviderPropertyManager $propertyManager): void
protected function prepareSetupView(StandaloneView $view, MfaProviderPropertyManager $propertyManager): void
{
$userData = $propertyManager->getUser()->user ?? [];
$secret = Totp::generateEncodedSecret([(string)($userData['uid'] ?? ''), (string)($userData['username'] ?? '')]);
......@@ -283,11 +279,8 @@ class TotpProvider implements MfaProviderInterface
/**
* Set the template and assign necessary variables for the edit view
*
* @param ViewInterface $view
* @param MfaProviderPropertyManager $propertyManager
*/
protected function prepareEditView(ViewInterface $view, MfaProviderPropertyManager $propertyManager): void
protected function prepareEditView(StandaloneView $view, MfaProviderPropertyManager $propertyManager): void
{
$view->setTemplate('Edit');
$view->assignMultiple([
......@@ -299,11 +292,8 @@ class TotpProvider implements MfaProviderInterface
/**
* Set the template for the auth view where the user has to provide the TOTP
*
* @param ViewInterface $view
* @param MfaProviderPropertyManager $propertyManager
*/
protected function prepareAuthView(ViewInterface $view, MfaProviderPropertyManager $propertyManager): void
protected function prepareAuthView(StandaloneView $view, MfaProviderPropertyManager $propertyManager): void
{
$view->setTemplate('Auth');
$view->assign('isLocked', $this->isLocked($propertyManager));
......
.. include:: ../../Includes.txt
===========================================
Deprecation: #95222 - Extbase ViewInterface
===========================================
See :issue:`95222`
Description
===========
To further streamline Fluid view related class inheritance and dependencies,
the interface :php:`TYPO3\CMS\Extbase\Mvc\View\ViewInterface` has been marked
as deprecated and will be removed in v12.
Impact
======
This deprecation has little impact on TYPO3 v11: The interface is kept and still
carried around in the core, no deprecation level log entry is raised.
The interface itself deviates from the casual view related classes only by requiring
an implementation of method :php:`initializeView()` which was never actively used,
calling that method will vanish in v12. The second deviation is method
:php:`setControllerContext()`, and class :php:`ControllerContext` is deprecated, too.
Affected Installations
======================
The extension scanner will find usages of extbase :php:`ViewInterface` as a strong match.
Migration
=========
Some instances may rely on extensions that type hint :php:`TYPO3\CMS\Extbase\Mvc\View\ViewInterface`,
especially in the extbase action controller method :php:`initializeView()`. The default
implementation of that method in :php:`TYPO3\CMS\Extbase\Mvc\Controller\ActionController` is
empty. To simplify compatibility for extensions supporting both v11 and v12,
that empty method will be removed in v12, but will still be called if it exists in classes
extending :php:`ActionController`.
Extension authors should thus avoid calling :php:`parent::initializeView($view)` in their
implementation of :php:`initializeView()` to prepare towards v12.
Apart from that, usages of :php:`TYPO3\CMS\Extbase\Mvc\View\ViewInterface` should be changed
to the more specific :php:`TYPO3\CMS\Fluid\View\StandaloneView` - usually in non-extbase
related classes, or to the less specific :php:`TYPO3Fluid\Fluid\View\ViewInterface`.
If using a custom view implementing :php:`TYPO3\CMS\Extbase\Mvc\View\ViewInterface`,
keep in mind that auto configuration based on the interface will be dropped in v12, you
may have to configure the service in :file:`Services.yaml` manually.
.. index:: Fluid, PHP-API, FullyScanned, ext:fluid
......@@ -35,7 +35,6 @@ use TYPO3\CMS\Dashboard\DashboardPresetRegistry;
use TYPO3\CMS\Dashboard\DashboardRepository;
use TYPO3\CMS\Dashboard\WidgetGroupInitializationService;
use TYPO3\CMS\Extbase\Mvc\Controller\Exception\RequiredArgumentMissingException;
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
use TYPO3\CMS\Fluid\View\StandaloneView;
/**
......@@ -43,16 +42,6 @@ use TYPO3\CMS\Fluid\View\StandaloneView;
*/
class DashboardController extends AbstractController
{
/**
* @var ModuleTemplate
*/
private $moduleTemplate;
/**
* @var ViewInterface
*/
protected $view;
protected PageRenderer $pageRenderer;
protected UriBuilder $uriBuilder;
protected Dashboard $currentDashboard;
......@@ -62,6 +51,9 @@ class DashboardController extends AbstractController
protected WidgetGroupInitializationService $widgetGroupInitializationService;
protected ModuleTemplateFactory $moduleTemplateFactory;
private ?ModuleTemplate $moduleTemplate = null;
protected StandaloneView $view;
public function __construct(
PageRenderer $pageRenderer,
UriBuilder $uriBuilder,
......@@ -82,6 +74,8 @@ class DashboardController extends AbstractController
$this->widgetGroupInitializationService = $widgetGroupInitializationService;
$this->moduleTemplateFactory = $moduleTemplateFactory;
$this->view = GeneralUtility::makeInstance(StandaloneView::class);
}
/**
......@@ -241,9 +235,7 @@ class DashboardController extends AbstractController
*/
protected function initializeView(string $templateName): void
{
$this->view = GeneralUtility::makeInstance(StandaloneView::class);
$this->view->setTemplate($templateName);
$this->view->getRenderingContext()->getTemplatePaths()->fillDefaultsByPackageName('dashboard');
$this->moduleTemplate->getDocHeaderComponent()->disable();
}
......
......@@ -96,6 +96,7 @@ abstract class ActionController implements ControllerInterface
* The current view, as resolved by resolveView()
*
* @var ViewInterface
* @todo v12: Change signature to TYPO3Fluid\Fluid\View\ViewInterface when extbase ViewInterface is dropped.
*/
protected $view;
......@@ -330,6 +331,7 @@ abstract class ActionController implements ControllerInterface
* or prepare the view in another way before the action is called.
*
* @param ViewInterface $view The view to be initialized
* @deprecated since v11, will be removed in v12: Drop method along with extbase ViewInterface.
*/
protected function initializeView(ViewInterface $view)
{
......@@ -482,7 +484,7 @@ abstract class ActionController implements ControllerInterface
// @deprecated since v11, will be removed with v12.
$this->controllerContext = $this->buildControllerContext();
$this->view = $this->resolveView();
if ($this->view !== null) {
if ($this->view !== null && method_exists($this, 'initializeView')) {
$this->initializeView($this->view);
}
$response = $this->callActionMethod($request);
......@@ -611,6 +613,7 @@ abstract class ActionController implements ControllerInterface
* By default, this method tries to locate a view with a name matching the current action.
*
* @return ViewInterface
* @todo v12: Change signature to TYPO3Fluid\Fluid\View\ViewInterface when extbase ViewInterface is dropped.
*
* @internal only to be used within Extbase, not part of TYPO3 Core API.
*/
......@@ -631,15 +634,16 @@ abstract class ActionController implements ControllerInterface
$this->request->getFormat()
);
if ($view instanceof ViewInterface) {
$this->setViewConfiguration($view);
}
$this->setViewConfiguration($view);
// @deprecated since v11, will be removed with v12.
$view->setControllerContext($this->controllerContext);
if (method_exists($view, 'injectSettings')) {
$view->injectSettings($this->settings);
}
$view->initializeView();
if (method_exists($view, 'initializeView')) {
// @deprecated since v11, will be removed with v12. Drop together with removal of extbase ViewInterface.
$view->initializeView();
}
// In TYPO3.Flow, solved through Object Lifecycle methods, we need to call it explicitly
$view->assign('settings', $this->settings);
// same with settings injection.
......@@ -650,6 +654,7 @@ abstract class ActionController implements ControllerInterface
* @param ViewInterface $view
*
* @internal only to be used within Extbase, not part of TYPO3 Core API.
* @todo v12: Change signature to TYPO3Fluid\Fluid\View\ViewInterface when extbase ViewInterface is dropped.
*/
protected function setViewConfiguration(ViewInterface $view)
{
......@@ -658,36 +663,30 @@ abstract class ActionController implements ControllerInterface
ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK
);
// set TemplateRootPaths
$viewFunctionName = 'setTemplateRootPaths';
if (method_exists($view, $viewFunctionName)) {
if (method_exists($view, 'setTemplateRootPaths')) {
$setting = 'templateRootPaths';
$parameter = $this->getViewProperty($extbaseFrameworkConfiguration, $setting);
// no need to bother if there is nothing to set
if ($parameter) {
$view->$viewFunctionName($parameter);
$view->setTemplateRootPaths($parameter);
}
}
// set LayoutRootPaths
$viewFunctionName = 'setLayoutRootPaths';
if (method_exists($view, $viewFunctionName)) {
if (method_exists($view, 'setLayoutRootPaths')) {
$setting = 'layoutRootPaths';
$parameter = $this->getViewProperty($extbaseFrameworkConfiguration, $setting);
// no need to bother if there is nothing to set
if ($parameter) {
$view->$viewFunctionName($parameter);
$view->setLayoutRootPaths($parameter);
}
}
// set PartialRootPaths
$viewFunctionName = 'setPartialRootPaths';
if (method_exists($view, $viewFunctionName)) {
if (method_exists($view, 'setPartialRootPaths')) {
$setting = 'partialRootPaths';
$parameter = $this->getViewProperty($extbaseFrameworkConfiguration, $setting);
// no need to bother if there is nothing to set
if ($parameter) {
$view->$viewFunctionName($parameter);
$view->setPartialRootPaths($parameter);
}
}
}
......
......@@ -47,6 +47,9 @@ class GenericViewResolver implements ViewResolverInterface
$this->defaultViewClass = $defaultViewClass;
}
/**
* @todo v12: Change signature to TYPO3Fluid\Fluid\View\ViewInterface when extbase ViewInterface is dropped.
*/
public function resolve(string $controllerObjectName, string $actionName, string $format): ViewInterface
{
if ($this->container->has($this->defaultViewClass)) {
......
......@@ -20,11 +20,14 @@ namespace TYPO3\CMS\Extbase\Mvc\View;
use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
use TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface;
use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
use TYPO3Fluid\Fluid\View\AbstractView;
/**
* A JSON view
*
* @todo v12: Drop 'implements ViewInterface' together with removal of extbase ViewInterface
*/
class JsonView implements ViewInterface
class JsonView extends AbstractView implements ViewInterface
{
/**
* Definition for the class name exposure configuration,
......@@ -240,6 +243,7 @@ class JsonView implements ViewInterface
* Initializes this view.
*
* Override this method for initializing your concrete view implementation.
* @deprecated since v11, will be removed with v12. Drop together with removal of extbase ViewInterface.
*/
public function initializeView()
{
......@@ -264,6 +268,24 @@ class JsonView implements ViewInterface
$this->configuration = $configuration;
}
/**
* @inheritdoc
*/
public function renderSection($sectionName, array $variables = [], $ignoreUnknown = false)
{
// No-op: renderSection does not make sense for this view
return '';
}
/**
* @inheritdoc
*/
public function renderPartial($partialName, $sectionName, array $variables, $ignoreUnknown = false)
{
// No-op: renderPartial does not make sense for this view
return '';
}
/**
* Transforms the value view variable to a serializable
* array representation using a YAML view configuration and JSON encodes
......
......@@ -19,6 +19,8 @@ use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
/**
* Interface of a view
*
* @deprecated since v11, will be removed with v12. Use TYPO3Fluid\Fluid\View\ViewInterface instead.
*/
interface ViewInterface
{
......
......@@ -11,6 +11,7 @@ return function (ContainerConfigurator $containerConfigurator, ContainerBuilder
$container->registerForAutoconfiguration(Mvc\RequestHandlerInterface::class)->addTag('extbase.request_handler');
$container->registerForAutoconfiguration(Mvc\Controller\ControllerInterface::class)->addTag('extbase.controller');
$container->registerForAutoconfiguration(Mvc\Controller\ActionController::class)->addTag('extbase.action_controller');
// @deprecated since v11, will be removed with v12. Drop together with extbase ViewInterface
$container->registerForAutoconfiguration(Mvc\View\ViewInterface::class)->addTag('extbase.view');
$container->addCompilerPass(new class() implements CompilerPassInterface {
......@@ -25,6 +26,7 @@ return function (ContainerConfigurator $containerConfigurator, ContainerBuilder
foreach ($container->findTaggedServiceIds('extbase.action_controller') as $id => $tags) {
$container->findDefinition($id)->setShared(false);
}
// @deprecated since v11, will be removed with v12. Drop together with extbase ViewInterface, set JsonView and StandaloneView public.
foreach ($container->findTaggedServiceIds('extbase.view') as $id => $tags) {
$container->findDefinition($id)->setShared(false)->setPublic(true);
}
......
......@@ -33,9 +33,13 @@ abstract class AbstractConfirmedEvent
/**
* @var ViewInterface
* @todo v12: Change signature to TYPO3Fluid\Fluid\View\ViewInterface when extbase ViewInterface is dropped.
*/
private $view;
/**
* @todo v12: Change signature to TYPO3Fluid\Fluid\View\ViewInterface when extbase ViewInterface is dropped.
*/
public function __construct(LoginController $controller, ViewInterface $view)
{
$this->controller = $controller;
......@@ -47,6 +51,9 @@ abstract class AbstractConfirmedEvent
return $this->controller;
}
/**
* @todo v12: Change signature to TYPO3Fluid\Fluid\View\ViewInterface when extbase ViewInterface is dropped.
*/
public function getView(): ViewInterface
{
return $this->view;
......
......@@ -26,14 +26,21 @@ final class ModifyLoginFormViewEvent
{
/**
* @var ViewInterface
* @todo v12: Change signature to TYPO3Fluid\Fluid\View\ViewInterface when extbase ViewInterface is dropped.
*/
private $view;
/**
* @todo v12: Change signature to TYPO3Fluid\Fluid\View\ViewInterface when extbase ViewInterface is dropped.
*/
public function __construct(ViewInterface $view)
{
$this->view = $view;
}
/**
* @todo v12: Change signature to TYPO3Fluid\Fluid\View\ViewInterface when extbase ViewInterface is dropped.
*/
public function getView(): ViewInterface
{
return $this->view;
......
......@@ -28,6 +28,8 @@ use TYPO3Fluid\Fluid\View\Exception\InvalidTemplateResourceException;
* Abstract Fluid Template View.
*
* Contains the fundamental methods which any Fluid based template view needs.
*
* @todo v12: Drop 'implements ViewInterface' together with removal of extbase ViewInterface
*/
abstract class AbstractTemplateView extends Typo3FluidAbstractTemplateView implements ViewInterface
{
......@@ -39,6 +41,8 @@ abstract class AbstractTemplateView extends Typo3FluidAbstractTemplateView imple
/**
* Initializes this view.
*
* @deprecated since v11, will be removed with v12. Drop together with removal of extbase ViewInterface.
*/
public function initializeView()
{
......
......@@ -1829,4 +1829,9 @@ return [
'Deprecation-95164-ExtbackendBackendTemplateView.rst'
],
],
'TYPO3\CMS\Extbase\Mvc\View\ViewInterface' => [
'restFiles' => [
'Deprecation-95222-ExtbaseViewInterface.rst',
],
],
];
......@@ -4928,13 +4928,6 @@ return [
'Deprecation-95139-ExtbaseControllerContext.rst',
],
],
'TYPO3\CMS\Extbase\Mvc\View\ViewInterface->setControllerContext' => [
'numberOfMandatoryArguments' => 1,
'maximumNumberOfArguments' => 1,
'restFiles' => [
'Deprecation-95139-ExtbaseControllerContext.rst',
],
],
'TYPO3\CMS\Fluid\Core\Rendering\RenderingContext->setControllerContext' => [
'numberOfMandatoryArguments' => 1,
'maximumNumberOfArguments' => 1,
......
......@@ -39,7 +39,6 @@ use TYPO3\CMS\Core\Routing\UnableToLinkToPageException;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
use TYPO3\CMS\Fluid\View\StandaloneView;
/**
......@@ -48,20 +47,6 @@ use TYPO3\CMS\Fluid\View\StandaloneView;
*/
class ViewModuleController
{
/**
* ModuleTemplate object
*
* @var ModuleTemplate
*/
protected $moduleTemplate;
/**
* View
*
* @var ViewInterface
*/
protected $view;
protected ModuleTemplateFactory $moduleTemplateFactory;
protected IconFactory $iconFactory;
protected PageRenderer $pageRenderer;
......@@ -69,6 +54,9 @@ class ViewModuleController
protected PageRepository $pageRepository;
protected SiteFinder $siteFinder;
protected ?ModuleTemplate $moduleTemplate = null;
protected StandaloneView $view;
public function __construct(
ModuleTemplateFactory $moduleTemplateFactory,
IconFactory $iconFactory,
......@@ -83,6 +71,7 @@ class ViewModuleController
$this->uriBuilder = $uriBuilder;
$this->pageRepository = $pageRepository;
$this->siteFinder = $siteFinder;
$this->view = GeneralUtility::makeInstance(StandaloneView::class);
}
/**
......@@ -92,7 +81,6 @@ class ViewModuleController
*/
protected function initializeView(string $templateName)
{
$this->view = GeneralUtility::makeInstance(StandaloneView::class);
$this->view->getRequest()->setControllerExtensionName('Viewpage');
$this->view->setTemplate($templateName);
$this->view->setTemplateRootPaths(['EXT:viewpage/Resources/Private/Templates/ViewModule']);
......
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