From 254a190db195caef2961d9d8025db2f9d6a410ee Mon Sep 17 00:00:00 2001 From: Claus Due Date: Mon, 11 Sep 2023 16:01:02 +0200 Subject: [PATCH] [BUGFIX] Assign "data" and "contentObject" template variables Refs: #2131 --- Classes/Controller/AbstractFluxController.php | 23 ++++++++++- .../AbstractFluxControllerTestCase.php | 39 +++++++++++-------- .../Unit/Controller/ContentControllerTest.php | 11 +++++- 3 files changed, 53 insertions(+), 20 deletions(-) diff --git a/Classes/Controller/AbstractFluxController.php b/Classes/Controller/AbstractFluxController.php index 544f5c311..47a3c68ab 100644 --- a/Classes/Controller/AbstractFluxController.php +++ b/Classes/Controller/AbstractFluxController.php @@ -36,6 +36,7 @@ use TYPO3\CMS\Extbase\Mvc\ResponseInterface; use TYPO3\CMS\Fluid\View\TemplatePaths; use TYPO3\CMS\Fluid\View\TemplateView; +use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; use TYPO3Fluid\Fluid\Core\ViewHelper\ViewHelperVariableContainer; use TYPO3Fluid\Fluid\View\ViewInterface; @@ -145,7 +146,7 @@ protected function initializeOverriddenSettings(): void if (is_array($this->data['settings'] ?? null)) { // a "settings." array is defined in the flexform configuration - extract it, use as "settings" in template // as well as the internal $this->settings array as per expected Extbase behavior. - $this->settings = RecursiveArrayUtility::merge($this->settings, $this->data['settings']); + $this->settings = RecursiveArrayUtility::merge($this->settings, $this->data['settings'] ?? []); } if ($this->settings['useTypoScript'] ?? false) { // an override shared by all Flux enabled controllers: setting plugin.tx_EXTKEY.settings.useTypoScript = 1 @@ -181,7 +182,11 @@ protected function initializeProvider(): void protected function initializeViewVariables(ViewInterface $view): void { + $contentObject = $this->getContentObject(); $row = $this->getRecord(); + + $view->assign('contentObject', $contentObject); + $view->assign('data', $contentObject instanceof ContentObjectRenderer ? $contentObject->data : null); if ($this->provider instanceof FluidProviderInterface) { $view->assignMultiple($this->provider->getTemplateVariables($row)); } @@ -189,6 +194,7 @@ protected function initializeViewVariables(ViewInterface $view): void $view->assign('settings', $this->settings); $view->assign('provider', $this->provider); $view->assign('record', $row); + HookHandler::trigger( HookHandler::CONTROLLER_VARIABLES_ASSIGNED, [ @@ -196,6 +202,7 @@ protected function initializeViewVariables(ViewInterface $view): void 'record' => $row, 'settings' => $this->settings, 'provider' => $this->provider, + 'contentObject' => $contentObject, ] ); } @@ -540,7 +547,7 @@ protected function getFluxTableName(): ?string public function getRecord(): array { - $contentObject = $this->configurationManager->getContentObject(); + $contentObject = $this->getContentObject(); if ($contentObject === null) { throw new \UnexpectedValueException( "Record of table " . $this->getFluxTableName() . ' not found', @@ -561,6 +568,18 @@ public function getRecord(): array return $record; } + protected function getContentObject(): ?ContentObjectRenderer + { + /** @var ContentObjectRenderer|null $renderer */ + $renderer = $this->getServerRequest()->getAttribute( + 'currentContentObject', + method_exists($this->configurationManager, 'getContentObject') ? + $this->configurationManager->getContentObject() + : null + ); + return $renderer; + } + protected function getServerRequest(): ServerRequestInterface { /** @var ServerRequestInterface $request */ diff --git a/Tests/Unit/Controller/AbstractFluxControllerTestCase.php b/Tests/Unit/Controller/AbstractFluxControllerTestCase.php index 3e33a603e..efc176f37 100644 --- a/Tests/Unit/Controller/AbstractFluxControllerTestCase.php +++ b/Tests/Unit/Controller/AbstractFluxControllerTestCase.php @@ -179,7 +179,7 @@ protected function createAndTestDummyControllerInstance(): AbstractFluxControlle { $controllerClassName = str_replace('Tests\\Unit\\', '', substr(get_class($this), 0, -4)); return $this->getMockBuilder($controllerClassName) - ->setMethods(['dummy']) + ->onlyMethods(['getContentObject', 'getServerRequest']) ->setConstructorArgs($this->getConstructorArguments()) ->getMock(); } @@ -205,14 +205,14 @@ public function testCanGetData(): void public function testCanGetRecord(): void { - $instance = $this->testCanCreateInstanceOfCustomRegisteredController(); $contentObjectRenderer = $this->getMockBuilder(ContentObjectRenderer::class) ->disableOriginalConstructor() ->getMock(); $contentObjectRenderer->data = []; - $configurationManager = $this->getMockBuilder(ConfigurationManagerInterface::class)->getMockForAbstractClass(); - $configurationManager->method('getContentObject')->willReturn($contentObjectRenderer); - $instance->injectConfigurationManager($configurationManager); + + $instance = $this->testCanCreateInstanceOfCustomRegisteredController(); + $instance->method('getContentObject')->willReturn($contentObjectRenderer); + $record = $this->callInaccessibleMethod($instance, 'getRecord'); $this->assertIsArray($record); } @@ -642,9 +642,15 @@ public function testCanInitializeViewVariables(): void $variables = ['foo' => 'bar']; $row = Records::$contentRecordWithoutParentAndWithoutChildren; $instance = $this->getMockBuilder($controllerClassName) - ->onlyMethods(['getRecord']) + ->onlyMethods(['getRecord', 'getServerRequest']) ->setConstructorArgs($this->getConstructorArguments()) ->getMock(); + $instance->method('getServerRequest')->willReturn( + $this->getMockBuilder(ServerRequestInterface::class)->getMockForAbstractClass() + ); + $instance->injectConfigurationManager( + $this->getMockBuilder(ConfigurationManagerInterface::class)->getMockForAbstractClass() + ); $instance->expects($this->once())->method('getRecord')->will($this->returnValue($row)); $view = $this->getMockBuilder(TemplateView::class) ->onlyMethods(['assign', 'assignMultiple']) @@ -670,13 +676,14 @@ public function testCanInitializeViewVariables(): void public function testCanUseTypoScriptSettingsInsteadOfFlexFormDataWhenRequested(): void { $instance = $this->testCanCreateInstanceOfCustomRegisteredController(); + $instance->method('getServerRequest')->willReturn( + $this->getMockBuilder(ServerRequestInterface::class)->getMockForAbstractClass() + ); $contentObjectRenderer = $this->getMockBuilder(ContentObjectRenderer::class) ->disableOriginalConstructor() ->getMock(); $contentObjectRenderer->data = []; - $configurationManager = $this->getMockBuilder(ConfigurationManagerInterface::class)->getMockForAbstractClass(); - $configurationManager->method('getContentObject')->willReturn($contentObjectRenderer); - $instance->injectConfigurationManager($configurationManager); + $instance->method('getContentObject')->willReturn($contentObjectRenderer); $provider = $this->getMockBuilder(Provider::class) ->onlyMethods(['getFlexFormValues']) ->disableOriginalConstructor() @@ -703,9 +710,10 @@ public function testCanUseFlexFormDataWhenPresent(): void ->setConstructorArgs($this->getConstructorArguments()) ->getMock(); $contentObjectRenderer->data = []; - $configurationManager = $this->getMockBuilder(ConfigurationManagerInterface::class)->getMockForAbstractClass(); - $configurationManager->method('getContentObject')->willReturn($contentObjectRenderer); - $instance->injectConfigurationManager($configurationManager); + $instance->method('getContentObject')->willReturn($contentObjectRenderer); + $instance->injectConfigurationManager( + $this->getMockBuilder(ConfigurationManagerInterface::class)->getMockForAbstractClass() + ); $this->providerResolver->method('resolvePrimaryConfigurationProvider')->willReturn( $this->getMockBuilder(Provider::class)->disableOriginalConstructor()->getMock() @@ -734,14 +742,11 @@ public function testRenderActionReturnsEmptyStringWithoutProvider(): void public function testGetRecordThrowsExceptionIfContentObjectIsEmpty(): void { - $configurationManager = $this->getMockBuilder(ConfigurationManagerInterface::class) - ->getMockForAbstractClass(); - $configurationManager->method('getContentObject')->willReturn(null); $subject = $this->getMockBuilder(AbstractFluxController::class) - ->setMethods(['dummy']) + ->onlyMethods(['getContentObject']) ->disableOriginalConstructor() ->getMockForAbstractClass(); - $subject->injectConfigurationManager($configurationManager); + $subject->method('getContentObject')->willReturn(null); self::expectExceptionCode(1666538343); $subject->getRecord(); diff --git a/Tests/Unit/Controller/ContentControllerTest.php b/Tests/Unit/Controller/ContentControllerTest.php index ea917f7bb..37fadf009 100644 --- a/Tests/Unit/Controller/ContentControllerTest.php +++ b/Tests/Unit/Controller/ContentControllerTest.php @@ -9,6 +9,7 @@ */ use FluidTYPO3\Flux\Controller\ContentController; +use Psr\Http\Message\ServerRequestInterface; class ContentControllerTest extends AbstractFluxControllerTestCase { @@ -22,8 +23,16 @@ protected function createAndTestDummyControllerInstance(): ContentController $this->performDummyRegistration(); $controllerClassName = ContentController::class; /** @var ContentController $instance */ - $instance = new $controllerClassName(...$this->getConstructorArguments()); + $instance = $this->getMockBuilder($controllerClassName) + ->onlyMethods(['getContentObject', 'getServerRequest']) + ->setConstructorArgs($this->getConstructorArguments()) + ->getMock(); $this->setInaccessiblePropertyValue($instance, 'extensionName', 'Flux'); return $instance; } + + public function testCanGetRecord(): void + { + parent::testCanGetRecord(); + } }