diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-94959-ContentObjectRendererConstructorInStandaloneView.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-94959-ContentObjectRendererConstructorInStandaloneView.rst new file mode 100644 index 0000000000000000000000000000000000000000..298fc927ce92f1bd0be681b63aaa09a6e7b4b3ac --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-94959-ContentObjectRendererConstructorInStandaloneView.rst @@ -0,0 +1,43 @@ +.. include:: ../../Includes.txt + +========================================================================= +Deprecation: #94959 - ContentObjectRenderer constructor in StandaloneView +========================================================================= + +See :issue:`94959` + +Description +=========== + +The :php:`ContentObjectRenderer` argument to :php:`TYPO3\CMS\Fluid\View\StandaloneView` +has been deprecated. The TYPO3 core never used this optional argument and +it added a hard dependency to extbase classes from StandaloneView, which should +be avoided. + +The ContentObjectRenderer instance within StandaloneView has been used to update +the extbase :php:`ConfigurationManager` singleton, even though extbase bootstrap +already sets the current ContentObjectRenderer to ConfigurationManager. + + +Impact +====== + +Extensions creating instances of :php:`StandaloneView` and handing over an +instance of :php:`ContentObjectRenderer` as constructor argument will get +a deprecation level log message logged. + + +Affected Installations +====================== + +Most instances are probably not affected by this change since handing over +the constructor argument is rather unusual. + + +Migration +========= + +Do not hand over an instance of :php:`ContentObjectRenderer` when creating an +instance of :php:`StandaloneView`. + +.. index:: Fluid, PHP-API, NotScanned, ext:fluid diff --git a/typo3/sysext/extbase/Classes/Configuration/AbstractConfigurationManager.php b/typo3/sysext/extbase/Classes/Configuration/AbstractConfigurationManager.php index 4289b8b0c5b2d78d8ff8e1572e4c5aa152cf409d..7f68feb5e0042142cd0b18f34d9c55254927efc6 100644 --- a/typo3/sysext/extbase/Classes/Configuration/AbstractConfigurationManager.php +++ b/typo3/sysext/extbase/Classes/Configuration/AbstractConfigurationManager.php @@ -79,6 +79,7 @@ abstract class AbstractConfigurationManager implements SingletonInterface /** * @param ContentObjectRenderer $contentObject + * @todo: See note on getContentObject() below. */ public function setContentObject(ContentObjectRenderer $contentObject): void { @@ -86,10 +87,20 @@ abstract class AbstractConfigurationManager implements SingletonInterface } /** - * @return ContentObjectRenderer|null + * @return ContentObjectRenderer + * @todo: This dependency to ContentObjectRenderer on a singleton object is unfortunate: + * The current instance is set through USER cObj and extbase Bootstrap, its null in Backend. + * This getter is misused to retrieve current ContentObjectRenderer state by some extensions (eg. ext:form). + * This dependency should be removed altogether. + * Although the current implementation *always* returns an instance of ContentObjectRenderer, we do not want to + * hard-expect consuming classes on that, since this methods needs to be dropped anyways, so potential null return is kept. */ public function getContentObject(): ?ContentObjectRenderer { + if ($this->contentObject instanceof ContentObjectRenderer) { + return $this->contentObject; + } + $this->contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class); return $this->contentObject; } @@ -155,7 +166,9 @@ abstract class AbstractConfigurationManager implements SingletonInterface $isBackend = ($GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface && ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend(); if ($isBackend) { - FrontendSimulatorUtility::simulateFrontendEnvironment($this->getContentObject()); + // @todo: This BE specific switch should be moved to BackendConfigurationManager to drop the dependency to $GLOBALS['TYPO3_REQUEST'] here. + // Use makeInstance here since extbase Bootstrap always setContentObject(null) in Backend, no need to call getContentObject(). + FrontendSimulatorUtility::simulateFrontendEnvironment(GeneralUtility::makeInstance(ContentObjectRenderer::class)); } $conf = $this->typoScriptService->convertPlainArrayToTypoScriptArray($frameworkConfiguration['persistence']); $frameworkConfiguration['persistence']['storagePid'] = $GLOBALS['TSFE']->cObj->stdWrapValue('storagePid', $conf ?? []); diff --git a/typo3/sysext/extbase/Classes/Configuration/ConfigurationManager.php b/typo3/sysext/extbase/Classes/Configuration/ConfigurationManager.php index 15c29554b09efad0c6d8c379206359c2d0b5653f..52571af0afc6a083b20b9688e999cea6ee2bd3d9 100644 --- a/typo3/sysext/extbase/Classes/Configuration/ConfigurationManager.php +++ b/typo3/sysext/extbase/Classes/Configuration/ConfigurationManager.php @@ -24,10 +24,9 @@ use TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; /** - * A configuration manager following the strategy pattern (GoF315). It hides the concrete + * A configuration manager following the strategy pattern. It hides the concrete * implementation of the configuration manager and provides a unified access point. * - * Use the shutdown() method to drop the concrete implementation. * @internal only to be used within Extbase, not part of TYPO3 Core API. */ class ConfigurationManager implements ConfigurationManagerInterface diff --git a/typo3/sysext/extbase/Tests/Unit/Configuration/AbstractConfigurationManagerTest.php b/typo3/sysext/extbase/Tests/Unit/Configuration/AbstractConfigurationManagerTest.php index bc9a5bce7c8a576dd1743db14034d6a734453e11..4f2b84ab55d3a4cf5f48aba0bced15c16c00c703 100644 --- a/typo3/sysext/extbase/Tests/Unit/Configuration/AbstractConfigurationManagerTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Configuration/AbstractConfigurationManagerTest.php @@ -28,6 +28,8 @@ use TYPO3\TestingFramework\Core\Unit\UnitTestCase; */ class AbstractConfigurationManagerTest extends UnitTestCase { + protected $resetSingletonInstances = true; + /** * @var AbstractConfigurationManager|\PHPUnit\Framework\MockObject\MockObject|AccessibleObjectInterface */ @@ -376,9 +378,9 @@ class AbstractConfigurationManagerTest extends UnitTestCase /** * @test */ - public function getContentObjectReturnsNullIfNoContentObjectHasBeenSet(): void + public function getContentObjectReturnsInstanceOfContentObjectRenderer(): void { - self::assertNull($this->abstractConfigurationManager->getContentObject()); + self::assertInstanceOf(ContentObjectRenderer::class, $this->abstractConfigurationManager->getContentObject()); } /** diff --git a/typo3/sysext/fluid/Classes/View/StandaloneView.php b/typo3/sysext/fluid/Classes/View/StandaloneView.php index 205fc978a7f7b2ac8fb155de8b65a700b6707f75..d483aa2f34038806e0da1c036e1db809d9f22aaa 100644 --- a/typo3/sysext/fluid/Classes/View/StandaloneView.php +++ b/typo3/sysext/fluid/Classes/View/StandaloneView.php @@ -32,15 +32,17 @@ class StandaloneView extends AbstractTemplateView /** * Constructor * - * @param ContentObjectRenderer $contentObject The current cObject. If NULL a new instance will be created + * @param ContentObjectRenderer|null $contentObject @deprecated The current cObject. If NULL a new instance will be created * @throws \InvalidArgumentException * @throws \UnexpectedValueException */ public function __construct(ContentObjectRenderer $contentObject = null) { - // @todo: this needs to be removed in the future + // @deprecated since v11, will be removed with v12. Drop $contentObject argument and ConfigurationManager handling. $configurationManager = GeneralUtility::getContainer()->get(ConfigurationManager::class); - if ($contentObject === null) { + if ($contentObject !== null) { + trigger_error('Argument $contentObject of class ' . __CLASS__ . ' is deprecated since v11, will be removed with v12.', E_USER_DEPRECATED); + } else { /** @var ContentObjectRenderer $contentObject */ $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class); } diff --git a/typo3/sysext/fluid/Configuration/Services.yaml b/typo3/sysext/fluid/Configuration/Services.yaml index 103a3ee81383f885e53cbd6835ea6a83b7c90077..fc9b33d1bf8db990542e741454f53cc33c4b5357 100644 --- a/typo3/sysext/fluid/Configuration/Services.yaml +++ b/typo3/sysext/fluid/Configuration/Services.yaml @@ -13,6 +13,10 @@ services: arguments: $context: null + # @deprecated since v11, will be removed with v12: Obsolete with the removal of ContentObjectRenderer constructor argument + TYPO3\CMS\Fluid\View\StandaloneView: + autowire: false + cache.fluid_template: class: TYPO3\CMS\Core\Cache\Frontend\FrontendInterface factory: ['@TYPO3\CMS\Core\Cache\CacheManager', 'getCache']