Skip to content

Commit

Permalink
[TASK] Deprecate StandaloneView getters
Browse files Browse the repository at this point in the history
Views should be data sinks, but not data sources:
In Fluid, RenderingContext is the main state object
used to carry rendering related state.

As such, StandaloneView should not provide getter
methods to retrieve state after it has been set:
They could be misused to "park" state, which is
a sign of bad architecture since only controllers
should keep track, carry and update such state.

The patch deprecates offending methods in
StandaloveView.

Change-Id: Id5c5fc2826b23c258b0f94aedbb0c5e75904e2db
Resolves: #98371
Releases: main
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/75773
Tested-by: core-ci <typo3@b13.com>
Tested-by: Simon Schaufelberger <simonschaufi+typo3@gmail.com>
Tested-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Simon Schaufelberger <simonschaufi+typo3@gmail.com>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
  • Loading branch information
lolli42 authored and sbuerk committed Sep 18, 2022
1 parent d70a479 commit b79f285
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
.. include:: /Includes.rst.txt

.. _deprecation-98371-1663524265:

==============================================
Deprecation: #98371 - Deprecated Fluid getters
==============================================

See :issue:`98371`

Description
===========

Views in a Model-View-Controller (MVC) construct should be data sinks.
Class :php:`\TYPO3\CMS\Fluid\View\StandaloneView` violates this concept by
providing some :php:`getXY()` methods that allow fetching previously set state.

The Fluid class :php:`\TYPO3\CMS\Fluid\Core\Rendering\RenderingContext`
is the main object carried around within the rendering chain to keep track
of state. It is the main data object used in view helpers.

As such, :php:`StandaloneView` should not allow fetching state since it allows
to be misused to park state, which is primarily a controller concern instead.

To enforce this pattern, the following methods have been marked as deprecated in
TYPO3 core v12 and will be removed in v13:

* :php:`\TYPO3\CMS\Fluid\View\StandaloneView->getRequest()`
* :php:`\TYPO3\CMS\Fluid\View\StandaloneView->getFormat()`
* :php:`\TYPO3\CMS\Fluid\View\StandaloneView->getTemplatePathAndFilename()`


Impact
======

Calling one of the above methods triggers a PHP :php:`E_USER_DEPRECATED` level
error.


Affected installations
======================

Instances with extensions using one of the above methods.


Migration
=========

Do not misuse :php:`StandaloneView` as data source. Typically, controllers
should handle and keep track of state like a PSR-7 Request and set or update
view state.


.. index:: Fluid, NotScanned, ext:fluid
34 changes: 22 additions & 12 deletions typo3/sysext/fluid/Classes/View/StandaloneView.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 CMS project.
*
Expand Down Expand Up @@ -43,10 +45,9 @@ public function __construct()
/**
* Sets the format of the current request (default format is "html")
*
* @param string $format
* @throws \RuntimeException
*/
public function setFormat($format)
public function setFormat(string $format): void
{
if (!$this->baseRenderingContext instanceof RenderingContext) {
throw new \RuntimeException('The rendering context must be of type ' . RenderingContext::class, 1482251886);
Expand All @@ -64,10 +65,14 @@ public function setFormat($format)
*
* @return string $format
* @throws \RuntimeException
* @todo: deprecate?!
* @deprecated since v12, will be removed in v13: Views should be data sinks, not data sources. No substitution.
*/
public function getFormat()
{
trigger_error(
'Method ' . __METHOD__ . ' has been deprecated in v12 and will be removed with v13. Do not use StandaloneView as data source.',
E_USER_DEPRECATED
);
if ($this->baseRenderingContext instanceof RenderingContext) {
return $this->baseRenderingContext->getRequest()->getFormat();
}
Expand All @@ -89,10 +94,14 @@ public function setRequest(?ServerRequestInterface $request = null): void
*
* @throws \RuntimeException
* @internal
* @todo: deprecate?!
* @deprecated since v12, will be removed in v13: Views should be data sinks, not data sources. No substitution.
*/
public function getRequest(): ?ServerRequestInterface
{
trigger_error(
'Method ' . __METHOD__ . ' has been deprecated in v12 and will be removed with v13. Do not use StandaloneView as data source.',
E_USER_DEPRECATED
);
if ($this->baseRenderingContext instanceof RenderingContext) {
return $this->baseRenderingContext->getRequest();
}
Expand All @@ -107,9 +116,14 @@ public function getRequest(): ?ServerRequestInterface
* and return that template path and filename directly, instead of attempting to resolve it.
*
* @return string Fluid template path
* @deprecated since v12, will be removed in v13: Views should be data sinks, not data sources. No substitution.
*/
public function getTemplatePathAndFilename()
{
trigger_error(
'Method ' . __METHOD__ . ' has been deprecated in v12 and will be removed with v13. Do not use StandaloneView as data source.',
E_USER_DEPRECATED
);
$templatePaths = $this->baseRenderingContext->getTemplatePaths();
return $templatePaths->resolveTemplateFileForControllerAndActionAndFormat(
$this->baseRenderingContext->getControllerName(),
Expand All @@ -119,30 +133,26 @@ public function getTemplatePathAndFilename()
}

/**
* Sets the Fluid template source
* Sets a Fluid template source string directly.
* You can use setTemplatePathAndFilename() alternatively if you only want to specify the template path
*
* @param string $templateSource Fluid template source code
*/
public function setTemplateSource($templateSource)
public function setTemplateSource(string $templateSource): void
{
$this->baseRenderingContext->getTemplatePaths()->setTemplateSource($templateSource);
}

/**
* Checks whether a template can be resolved for the current request
*
* @return bool
*/
public function hasTemplate()
public function hasTemplate(): bool
{
try {
$this->baseRenderingContext->getTemplatePaths()->getTemplateSource(
$this->baseRenderingContext->getControllerName(),
$this->baseRenderingContext->getControllerAction()
);
return true;
} catch (InvalidTemplateResourceException $e) {
} catch (InvalidTemplateResourceException $_) {
return false;
}
}
Expand Down

0 comments on commit b79f285

Please sign in to comment.