From a5fff2c8ba71e11384fe3c51dc4aa8e1103fe738 Mon Sep 17 00:00:00 2001
From: Benni Mack <benni@typo3.org>
Date: Mon, 23 Aug 2021 19:16:32 +0200
Subject: [PATCH] [TASK] Deprecate extbase's AbstractView

TemplateView does not use AbstractView, and
others do not need this as well, ViewInterface
is the one people should rely on.

Resolves: #94991
Releases: master
Change-Id: Ie09d6dcb3644b4e383bf67e7043765227b622948
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70726
Tested-by: core-ci <typo3@b13.com>
Tested-by: Oliver Bartsch <bo@cedev.de>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Oliver Bartsch <bo@cedev.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
---
 .../Deprecation-94991-ExtbaseAbstractView.rst | 40 ++++++++++
 .../extbase/Classes/Mvc/View/AbstractView.php |  1 +
 .../extbase/Classes/Mvc/View/JsonView.php     | 77 ++++++++++++++++++-
 .../extbase/Classes/Mvc/View/NotFoundView.php | 77 ++++++++++++++++++-
 .../Classes/Mvc/View/ViewInterface.php        |  8 +-
 .../ExtensionScanner/Php/ClassNameMatcher.php |  5 ++
 6 files changed, 202 insertions(+), 6 deletions(-)
 create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Deprecation-94991-ExtbaseAbstractView.rst

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-94991-ExtbaseAbstractView.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-94991-ExtbaseAbstractView.rst
new file mode 100644
index 000000000000..b4350d9d727c
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-94991-ExtbaseAbstractView.rst
@@ -0,0 +1,40 @@
+.. include:: ../../Includes.txt
+
+==========================================
+Deprecation: #94991 - Extbase AbstractView
+==========================================
+
+See :issue:`94991`
+
+Description
+===========
+
+To simplify and streamline fluid view related class inheritance,
+the exbase class :php:`TYPO3\CMS\Extbase\Mvc\View\AbstractView`
+has been marked as deprecated and will be removed in v12.
+
+
+Impact
+======
+
+Extending the class should be avoided. Consuming classes should
+directly implement :php:`TYPO3\CMS\Extbase\Mvc\View\ViewInterface`
+instead.
+
+
+Affected Installations
+======================
+
+Instances with own extbase view classes that extend :php:`AbstractView`
+are affected, but this is rather uncommon. The extension scanner will
+find class usages as a strong match.
+
+
+Migration
+=========
+
+Affected extbase view classes should implement :php:`ViewInterface` instead
+and not extend :php:`AbstractView` anymore. The most simple solution is to
+copy the interface implementation from the deprecated :php:`AbstractView` class.
+
+.. index:: Fluid, PHP-API, FullyScanned, ext:extbase
diff --git a/typo3/sysext/extbase/Classes/Mvc/View/AbstractView.php b/typo3/sysext/extbase/Classes/Mvc/View/AbstractView.php
index 172626720fa7..dc5819c9ad37 100644
--- a/typo3/sysext/extbase/Classes/Mvc/View/AbstractView.php
+++ b/typo3/sysext/extbase/Classes/Mvc/View/AbstractView.php
@@ -19,6 +19,7 @@ use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
 
 /**
  * An abstract View
+ * @deprecated since TYPO3 v11, will be removed in TYPO3 v12.0. It is highly recommended to implement all needed logic of ViewInterface yourself
  */
 abstract class AbstractView implements ViewInterface
 {
diff --git a/typo3/sysext/extbase/Classes/Mvc/View/JsonView.php b/typo3/sysext/extbase/Classes/Mvc/View/JsonView.php
index fe1c655ae191..9408920d6f6a 100644
--- a/typo3/sysext/extbase/Classes/Mvc/View/JsonView.php
+++ b/typo3/sysext/extbase/Classes/Mvc/View/JsonView.php
@@ -17,13 +17,14 @@ declare(strict_types=1);
 
 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;
 
 /**
  * A JSON view
  */
-class JsonView extends AbstractView
+class JsonView implements ViewInterface
 {
     /**
      * Definition for the class name exposure configuration,
@@ -158,6 +159,19 @@ class JsonView extends AbstractView
      */
     protected $persistenceManager;
 
+    /**
+     * @var ControllerContext
+     */
+    protected $controllerContext;
+
+    /**
+     * View variables and their values
+     *
+     * @var array
+     * @see assign()
+     */
+    protected $variables = [];
+
     /**
      * @param PersistenceManagerInterface $persistenceManager
      * @internal
@@ -167,6 +181,67 @@ class JsonView extends AbstractView
         $this->persistenceManager = $persistenceManager;
     }
 
+    /**
+     * Sets the current controller context
+     *
+     * @param ControllerContext $controllerContext
+     */
+    public function setControllerContext(ControllerContext $controllerContext)
+    {
+        $this->controllerContext = $controllerContext;
+    }
+
+    /**
+     * Add a variable to $this->viewData.
+     * Can be chained, so $this->view->assign(..., ...)->assign(..., ...); is possible
+     *
+     * @param string $key Key of variable
+     * @param mixed $value Value of object
+     * @return self an instance of $this, to enable chaining
+     */
+    public function assign($key, $value)
+    {
+        $this->variables[$key] = $value;
+        return $this;
+    }
+
+    /**
+     * Add multiple variables to $this->viewData.
+     *
+     * @param array $values array in the format array(key1 => value1, key2 => value2).
+     * @return self an instance of $this, to enable chaining
+     */
+    public function assignMultiple(array $values)
+    {
+        foreach ($values as $key => $value) {
+            $this->assign($key, $value);
+        }
+        return $this;
+    }
+
+    /**
+     * Tells if the view implementation can render the view for the given context.
+     *
+     * By default we assume that the view implementation can handle all kinds of
+     * contexts. Override this method if that is not the case.
+     *
+     * @param ControllerContext $controllerContext
+     * @return bool TRUE if the view has something useful to display, otherwise FALSE
+     */
+    public function canRender(ControllerContext $controllerContext)
+    {
+        return true;
+    }
+
+    /**
+     * Initializes this view.
+     *
+     * Override this method for initializing your concrete view implementation.
+     */
+    public function initializeView()
+    {
+    }
+
     /**
      * Specifies which variables this JsonView should render
      * By default only the variable 'value' will be rendered
diff --git a/typo3/sysext/extbase/Classes/Mvc/View/NotFoundView.php b/typo3/sysext/extbase/Classes/Mvc/View/NotFoundView.php
index 24f7b5bf97e3..e29d0aab9476 100644
--- a/typo3/sysext/extbase/Classes/Mvc/View/NotFoundView.php
+++ b/typo3/sysext/extbase/Classes/Mvc/View/NotFoundView.php
@@ -16,6 +16,7 @@
 namespace TYPO3\CMS\Extbase\Mvc\View;
 
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
+use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
 use TYPO3\CMS\Extbase\Mvc\Exception;
 use TYPO3\CMS\Extbase\Mvc\Request;
 
@@ -23,13 +24,26 @@ use TYPO3\CMS\Extbase\Mvc\Request;
  * The not found view - a special case.
  * @internal only to be used within Extbase, not part of TYPO3 Core API.
  */
-class NotFoundView extends AbstractView
+class NotFoundView implements ViewInterface
 {
     /**
      * @var array
      */
     protected $variablesMarker = ['errorMessage' => 'ERROR_MESSAGE'];
 
+    /**
+     * @var ControllerContext
+     */
+    protected $controllerContext;
+
+    /**
+     * View variables and their values
+     *
+     * @var array
+     * @see assign()
+     */
+    protected $variables = [];
+
     /**
      * Renders the not found view
      *
@@ -77,4 +91,65 @@ class NotFoundView extends AbstractView
     public function __call($methodName, array $arguments)
     {
     }
+
+    /**
+     * Sets the current controller context
+     *
+     * @param ControllerContext $controllerContext
+     */
+    public function setControllerContext(ControllerContext $controllerContext)
+    {
+        $this->controllerContext = $controllerContext;
+    }
+
+    /**
+     * Add a variable to $this->viewData.
+     * Can be chained, so $this->view->assign(..., ...)->assign(..., ...); is possible
+     *
+     * @param string $key Key of variable
+     * @param mixed $value Value of object
+     * @return NotFoundView an instance of $this, to enable chaining
+     */
+    public function assign($key, $value)
+    {
+        $this->variables[$key] = $value;
+        return $this;
+    }
+
+    /**
+     * Add multiple variables to $this->viewData.
+     *
+     * @param array $values array in the format array(key1 => value1, key2 => value2).
+     * @return NotFoundView an instance of $this, to enable chaining
+     */
+    public function assignMultiple(array $values)
+    {
+        foreach ($values as $key => $value) {
+            $this->assign($key, $value);
+        }
+        return $this;
+    }
+
+    /**
+     * Tells if the view implementation can render the view for the given context.
+     *
+     * By default we assume that the view implementation can handle all kinds of
+     * contexts. Override this method if that is not the case.
+     *
+     * @param ControllerContext $controllerContext
+     * @return bool TRUE if the view has something useful to display, otherwise FALSE
+     */
+    public function canRender(ControllerContext $controllerContext)
+    {
+        return true;
+    }
+
+    /**
+     * Initializes this view.
+     *
+     * Override this method for initializing your concrete view implementation.
+     */
+    public function initializeView()
+    {
+    }
 }
diff --git a/typo3/sysext/extbase/Classes/Mvc/View/ViewInterface.php b/typo3/sysext/extbase/Classes/Mvc/View/ViewInterface.php
index ff049a500485..7abf65b11da8 100644
--- a/typo3/sysext/extbase/Classes/Mvc/View/ViewInterface.php
+++ b/typo3/sysext/extbase/Classes/Mvc/View/ViewInterface.php
@@ -25,7 +25,7 @@ interface ViewInterface
     /**
      * Sets the current controller context
      *
-     * @param \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext $controllerContext
+     * @param ControllerContext $controllerContext
      * @internal
      */
     public function setControllerContext(ControllerContext $controllerContext);
@@ -36,7 +36,7 @@ interface ViewInterface
      *
      * @param string $key Key of variable
      * @param mixed $value Value of object
-     * @return \TYPO3\CMS\Extbase\Mvc\View\ViewInterface an instance of $this, to enable chaining
+     * @return self an instance of $this, to enable chaining
      */
     public function assign($key, $value);
 
@@ -44,14 +44,14 @@ interface ViewInterface
      * Add multiple variables to the view data collection
      *
      * @param array $values array in the format array(key1 => value1, key2 => value2)
-     * @return \TYPO3\CMS\Extbase\Mvc\View\ViewInterface an instance of $this, to enable chaining
+     * @return self an instance of $this, to enable chaining
      */
     public function assignMultiple(array $values);
 
     /**
      * Tells if the view implementation can render the view for the given context.
      *
-     * @param \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext $controllerContext
+     * @param ControllerContext $controllerContext
      * @return bool TRUE if the view has something useful to display, otherwise FALSE
      */
     public function canRender(ControllerContext $controllerContext);
diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php
index 3ebea2cd86a7..8d17caa32685 100644
--- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php
+++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php
@@ -1774,4 +1774,9 @@ return [
             'Deprecation-94953-EditPanelRelatedFrontendFunctionality.rst',
         ],
     ],
+    'TYPO3\CMS\Extbase\Mvc\View\AbstractView' => [
+        'restFiles' => [
+            'Deprecation-94991-ExtbaseAbstractView.rst',
+        ],
+    ],
 ];
-- 
GitLab