Skip to content

Commit

Permalink
[FEATURE] Introduce ContentObjectFetcher
Browse files Browse the repository at this point in the history
Solution is forward-compatible with v13 which does not allow
reading content object renderer from ConfigurationManager.
  • Loading branch information
NamelessCoder committed Oct 28, 2024
1 parent e64c897 commit b03c966
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 15 deletions.
39 changes: 30 additions & 9 deletions Classes/Controller/AbstractFluxController.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
use FluidTYPO3\Flux\Provider\ProviderResolver;
use FluidTYPO3\Flux\Service\TypoScriptService;
use FluidTYPO3\Flux\Service\WorkspacesAwareRecordService;
use FluidTYPO3\Flux\Utility\ContentObjectFetcher;
use FluidTYPO3\Flux\Utility\ExtensionNamingUtility;
use FluidTYPO3\Flux\Utility\RecursiveArrayUtility;
use FluidTYPO3\Flux\ViewHelpers\FormViewHelper;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\VersionNumberUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Mvc\Controller\Arguments;
Expand All @@ -37,6 +39,7 @@
use TYPO3\CMS\Fluid\View\TemplatePaths;
use TYPO3\CMS\Fluid\View\TemplateView;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\ViewHelperVariableContainer;
use TYPO3Fluid\Fluid\View\ViewInterface;
Expand Down Expand Up @@ -554,7 +557,32 @@ public function getRecord(): array
1666538343
);
}
$record = $contentObject->data;

if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '11.5', '<')) {
/** @var TypoScriptFrontendController|null $tsfe */
$tsfe = $GLOBALS['TSFE'] ?? null;
} else {
$tsfe = $contentObject->getTypoScriptFrontendController();
}
if ($tsfe === null) {
throw new \UnexpectedValueException(
"Record of table " . $this->getFluxTableName() . ' not found',
1729864782
);
}

[$table, $recordUid] = GeneralUtility::trimExplode(
':',
$tsfe->currentRecord
);
$record = $this->recordService->getSingle($table, '*', (integer) $recordUid);
if ($record === null) {
throw new \UnexpectedValueException(
"Record of table " . $this->getFluxTableName() . ' not found',
1729864698
);
}

if ($record['_LOCALIZED_UID'] ?? false) {
$record = array_merge(
$record,
Expand All @@ -570,14 +598,7 @@ public function getRecord(): array

protected function getContentObject(): ?ContentObjectRenderer
{
/** @var ContentObjectRenderer|null $renderer */
$renderer = $this->getServerRequest()->getAttribute(
'currentContentObject',
method_exists($this->configurationManager, 'getContentObject') ?
$this->configurationManager->getContentObject()
: null
);
return $renderer;
return ContentObjectFetcher::resolve($this->configurationManager);
}

protected function getServerRequest(): ServerRequestInterface
Expand Down
46 changes: 46 additions & 0 deletions Classes/Utility/ContentObjectFetcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php
namespace FluidTYPO3\Flux\Utility;

/*
* This file is part of the FluidTYPO3/Flux project under GPLv2 or later.
*
* For the full copyright and license information, please read the
* LICENSE.md file that was distributed with this source code.
*/

use TYPO3\CMS\Core\Http\ServerRequest;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;

class ContentObjectFetcher
{
public static function resolve(?ConfigurationManagerInterface $configurationManager = null): ?ContentObjectRenderer
{
$contentObject = null;
$request = $configurationManager !== null && method_exists($configurationManager, 'getRequest')
? $configurationManager->getRequest()
: ($GLOBALS['TYPO3_REQUEST'] ?? null);

if ($request && $configurationManager === null) {
$contentObject = static::resolveFromRequest($request);
}

if ($contentObject === null) {
if ($configurationManager !== null && method_exists($configurationManager, 'getContentObject')) {
$contentObject = $configurationManager->getContentObject();
} else {
$contentObject = static::resolveFromRequest($request);
}
}

return $contentObject;
}

protected static function resolveFromRequest(ServerRequest $request): ?ContentObjectRenderer
{
/** @var TypoScriptFrontendController $controller */
$controller = $request->getAttribute('frontend.controller');
return $controller instanceof TypoScriptFrontendController ? $controller->cObj : null;
}
}
21 changes: 20 additions & 1 deletion Tests/Unit/Controller/AbstractFluxControllerTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use TYPO3\CMS\Fluid\View\TemplatePaths;
use TYPO3\CMS\Fluid\View\TemplateView;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContext;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\ViewHelperVariableContainer;
Expand All @@ -60,6 +61,8 @@ abstract class AbstractFluxControllerTestCase extends AbstractTestCase
*/
protected RequestBuilder $requestBuilder;

protected WorkspacesAwareRecordService $recordService;

protected TypoScriptService $typoScriptService;

protected ProviderResolver $providerResolver;
Expand All @@ -81,6 +84,10 @@ protected function setUp(): void
->getMock();
$this->requestBuilder->method('getEnvironmentVariable')->willReturn('env');

$this->recordService = $this->getMockBuilder(WorkspacesAwareRecordService::class)
->disableOriginalConstructor()
->getMock();

$this->typoScriptService = $this->getMockBuilder(TypoScriptService::class)
->onlyMethods(['getSettingsForExtensionName'])
->disableOriginalConstructor()
Expand All @@ -101,7 +108,7 @@ protected function getConstructorArguments(): array
return [
$this->renderingContextBuilder,
$this->requestBuilder,
$this->getMockBuilder(WorkspacesAwareRecordService::class)->disableOriginalConstructor()->getMock(),
$this->recordService,
$this->typoScriptService,
$this->providerResolver,
$this->resolver,
Expand Down Expand Up @@ -206,10 +213,20 @@ public function testCanGetData(): void
public function testCanGetRecord(): void
{
$contentObjectRenderer = $this->getMockBuilder(ContentObjectRenderer::class)
->onlyMethods(['getTypoScriptFrontendController'])
->disableOriginalConstructor()
->getMock();
$contentObjectRenderer->data = [];

$GLOBALS['TSFE'] = $this->getMockBuilder(TypoScriptFrontendController::class)
->disableOriginalConstructor()
->getMock();
$GLOBALS['TSFE']->currentRecord = 'tt_content:123';

$contentObjectRenderer->method('getTypoScriptFrontendController')->willReturn($GLOBALS['TSFE']);

$this->recordService->method('getSingle')->willReturn(['uid' => 123]);

$instance = $this->testCanCreateInstanceOfCustomRegisteredController();
$instance->method('getContentObject')->willReturn($contentObjectRenderer);

Expand Down Expand Up @@ -691,6 +708,7 @@ public function testCanUseTypoScriptSettingsInsteadOfFlexFormDataWhenRequested()
$provider->method('getFlexFormValues')->willReturn(['settings' => ['useTypoScript' => 1]]);
$this->typoScriptService->method('getSettingsForExtensionName')->willReturn(['foo' => 'bar']);
$this->providerResolver->method('resolvePrimaryConfigurationProvider')->willReturn($provider);
$this->recordService->method('getSingle')->willReturn(['uid' => 123]);
$settings = [
'useTypoScript' => true
];
Expand All @@ -715,6 +733,7 @@ public function testCanUseFlexFormDataWhenPresent(): void
$this->getMockBuilder(ConfigurationManagerInterface::class)->getMockForAbstractClass()
);

$this->recordService->method('getSingle')->willReturn(['uid' => 123]);
$this->providerResolver->method('resolvePrimaryConfigurationProvider')->willReturn(
$this->getMockBuilder(Provider::class)->disableOriginalConstructor()->getMock()
);
Expand Down
5 changes: 0 additions & 5 deletions Tests/Unit/Controller/ContentControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,4 @@ protected function createAndTestDummyControllerInstance(): ContentController
$this->setInaccessiblePropertyValue($instance, 'extensionName', 'Flux');
return $instance;
}

public function testCanGetRecord(): void
{
parent::testCanGetRecord();
}
}
4 changes: 4 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ parameters:
message: "#^Caught class TYPO3\\\\CMS\\\\Extbase\\\\Mvc\\\\Exception\\\\StopActionException not found\\.$#"
count: 1
path: Classes/Controller/AbstractFluxController.php
-
message: "#^Call to protected method getTypoScriptFrontendController\\(\\) of class TYPO3\\\\CMS\\\\Frontend\\\\ContentObject\\\\ContentObjectRenderer\\.$#"
count: 1
path: Classes/Controller/AbstractFluxController.php
-
message: "#^Method FluidTYPO3\\\\Flux\\\\Integration\\\\BackendLayoutRenderer\\:\\:getContext\\(\\) should return TYPO3\\\\CMS\\\\Backend\\\\View\\\\PageLayoutContext but returns TYPO3\\\\CMS\\\\Backend\\\\View\\\\PageLayoutContext\\|null\\.$#"
count: 1
Expand Down

0 comments on commit b03c966

Please sign in to comment.