From ddcf28741d2c8fc6a0570e3347f746ee93fb1682 Mon Sep 17 00:00:00 2001
From: Helmut Hummel <typo3@helhum.io>
Date: Tue, 27 Jun 2023 10:15:59 +0200
Subject: [PATCH] [TASK] Clean up usages of ContentObjectRenderer request
 attribute
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

ContentObjectRenderer is now added as request attribute in
certain cases. But since the signature of obtaining an attribute
from a request correctly states, that the attribute can be null,
consuming code should account for that and defensively
fall back to defaults, when the object can not be obtained.

Releases: 12.4, main
Resolves: #101201
Change-Id: I3b3145794cafd8f5a8c1081e97599f9862be8b99
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/80921
Tested-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: core-ci <typo3@b13.com>
---
 .../FrontendConfigurationManager.php            |  6 +++---
 .../Controller/FormFrontendController.php       |  4 ++--
 .../form/Classes/Domain/Runtime/FormRuntime.php | 17 +++++++----------
 3 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/typo3/sysext/extbase/Classes/Configuration/FrontendConfigurationManager.php b/typo3/sysext/extbase/Classes/Configuration/FrontendConfigurationManager.php
index b48ad5027fd8..dd1743459989 100644
--- a/typo3/sysext/extbase/Classes/Configuration/FrontendConfigurationManager.php
+++ b/typo3/sysext/extbase/Classes/Configuration/FrontendConfigurationManager.php
@@ -326,10 +326,10 @@ class FrontendConfigurationManager implements SingletonInterface
     {
         // @deprecated: Remove fallback to $this->contentObject in v13.
         $contentObject = $this->request?->getAttribute('currentContentObject') ?? $this->contentObject;
-        $pages = (string)($contentObject->data['pages'] ?? '');
+        $pages = (string)($contentObject?->data['pages'] ?? '');
         if ($pages !== '') {
             $storagePids = GeneralUtility::intExplode(',', $pages, true);
-            $recursionDepth = (int)($contentObject->data['recursive'] ?? 0);
+            $recursionDepth = (int)($contentObject?->data['recursive'] ?? 0);
             $recursiveStoragePids = $this->pageRepository->getPageIdsRecursive($storagePids, $recursionDepth);
             $pages = implode(',', $recursiveStoragePids);
             ArrayUtility::mergeRecursiveWithOverrule($frameworkConfiguration, [
@@ -375,7 +375,7 @@ class FrontendConfigurationManager implements SingletonInterface
     {
         // @todo: Remove fallback to $this->contentObject in v13.
         $contentObject = $this->request?->getAttribute('currentContentObject') ?? $this->contentObject;
-        $flexFormConfiguration = $contentObject->data['pi_flexform'] ?? [];
+        $flexFormConfiguration = $contentObject?->data['pi_flexform'] ?? [];
         if (is_string($flexFormConfiguration)) {
             if ($flexFormConfiguration !== '') {
                 $flexFormConfiguration = $this->flexFormService->convertFlexFormContentToArray($flexFormConfiguration);
diff --git a/typo3/sysext/form/Classes/Controller/FormFrontendController.php b/typo3/sysext/form/Classes/Controller/FormFrontendController.php
index a331ad2f4862..f80cbeceb64c 100644
--- a/typo3/sysext/form/Classes/Controller/FormFrontendController.php
+++ b/typo3/sysext/form/Classes/Controller/FormFrontendController.php
@@ -69,7 +69,7 @@ class FormFrontendController extends ActionController
             $formDefinition['persistenceIdentifier'] = $this->settings['persistenceIdentifier'];
             $formDefinition = $this->overrideByFlexFormSettings($formDefinition);
             $formDefinition = ArrayUtility::setValueByPath($formDefinition, 'renderingOptions._originalIdentifier', $formDefinition['identifier'], '.');
-            $formDefinition['identifier'] .= '-' . $this->request->getAttribute('currentContentObject')->data['uid'];
+            $formDefinition['identifier'] .= '-' . ($this->request->getAttribute('currentContentObject')?->data['uid'] ?? '');
         }
         $this->view->assign('formConfiguration', $formDefinition);
 
@@ -93,7 +93,7 @@ class FormFrontendController extends ActionController
      */
     protected function overrideByFlexFormSettings(array $formDefinition): array
     {
-        $flexFormData = GeneralUtility::xml2array($this->request->getAttribute('currentContentObject')->data['pi_flexform'] ?? '');
+        $flexFormData = GeneralUtility::xml2array($this->request->getAttribute('currentContentObject')?->data['pi_flexform'] ?? '');
 
         if (!is_array($flexFormData)) {
             return $formDefinition;
diff --git a/typo3/sysext/form/Classes/Domain/Runtime/FormRuntime.php b/typo3/sysext/form/Classes/Domain/Runtime/FormRuntime.php
index 4d0bf895210f..c1837f078398 100644
--- a/typo3/sysext/form/Classes/Domain/Runtime/FormRuntime.php
+++ b/typo3/sysext/form/Classes/Domain/Runtime/FormRuntime.php
@@ -499,16 +499,16 @@ class FormRuntime implements RootRenderableInterface, \ArrayAccess
      * If no surrounding content object can be found (which would be strange)
      * we assume a cached request for safety which means that an empty form
      * will be rendered.
-     *
-     * @todo: this should be checked against https://forge.typo3.org/issues/91625 as this was fixed differently for UriBuilder
      */
     protected function isRenderedCached(): bool
     {
         $contentObject = $this->request->getAttribute('currentContentObject');
-        return $contentObject === null
-            ? true
-            // @todo this does not work when rendering a cached `FLUIDTEMPLATE` (not nested in `COA_INT`)
-            : $contentObject->getUserObjectType() === ContentObjectRenderer::OBJECTTYPE_USER;
+        // @todo: this does not work when rendering a cached `FLUIDTEMPLATE` (not nested in `COA_INT`)
+        //        Rendering the form other than with the controller, will never work out cleanly.
+        //        This likely can only be resolved by deprecating using the form render view helper
+        //        other than in a template for the form plugin and covering the use cases the VH was introduced
+        //        with a different concept
+        return $contentObject === null || $contentObject->getUserObjectType() === ContentObjectRenderer::OBJECTTYPE_USER;
     }
 
     /**
@@ -1078,10 +1078,7 @@ class FormRuntime implements RootRenderableInterface, \ArrayAccess
             }
         }
 
-        $contentObjectData = [];
-        if ($this->request->getAttribute('currentContentObject') instanceof ContentObjectRenderer) {
-            $contentObjectData = $this->request->getAttribute('currentContentObject')->data;
-        }
+        $contentObjectData = $this->request->getAttribute('currentContentObject')?->data ?? [];
 
         return GeneralUtility::makeInstance(
             Resolver::class,
-- 
GitLab