diff --git a/Classes/XClass/TemplateView.php b/Classes/XClass/TemplateView.php new file mode 100644 index 00000000..ba7295a6 --- /dev/null +++ b/Classes/XClass/TemplateView.php @@ -0,0 +1,69 @@ +isFrontend()) { + return parent::render($actionName); + } + + $renderingContext = $this->getCurrentRenderingContext(); + + if ((int)($renderingContext->getVariableProvider()->get('settings')['phpTemplate'] ?? 0) !== 1) { + return parent::render($actionName); + } + + $templatePaths = $renderingContext->getTemplatePaths(); + if ($actionName) { + $actionName = ucfirst($actionName); + $renderingContext->setControllerAction($actionName); + } + + $templateFile = $templatePaths->resolveTemplateFileForControllerAndActionAndFormat($renderingContext->getControllerName(), $renderingContext->getControllerAction(), 'php'); + + if ($templateFile === null) { + throw new InvalidTemplateResourceException('Template is not found'); + } + + return $this->loadTemplate($templateFile, $renderingContext); + } + + private function loadTemplate(string $templateFile, RenderingContextInterface $renderingContext): string + { + $__jsonContent = ''; + + try { + extract($renderingContext->getVariableProvider()->getAll()); + + ob_start(); + include $templateFile; + $__jsonContent = ob_get_clean(); + } catch (\Throwable $e) { + ob_end_clean(); + throw $e; + } + + return $__jsonContent; + } +} diff --git a/Configuration/Services.php b/Configuration/Services.php index 5a0573f2..d8659495 100644 --- a/Configuration/Services.php +++ b/Configuration/Services.php @@ -12,6 +12,8 @@ use FriendsOfTYPO3\Headless\Utility\HeadlessFrontendUrlInterface; use FriendsOfTYPO3\Headless\Utility\UrlUtility; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; +use TYPO3\CMS\Core\Configuration\Features; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Form\Controller\FormFrontendController; use TYPO3\CMS\FrontendLogin\Controller\LoginController; @@ -44,4 +46,10 @@ $services->set(HeadlessFrontendUrlInterface::class, UrlUtility::class)->autowire(false); $services->set(XmlSitemapRenderer::class)->public()->share(false); + + $features = GeneralUtility::makeInstance(Features::class); + + if ($features->isFeatureEnabled('headless.overrideFluidTemplates')) { + $services->alias(\TYPO3\CMS\Fluid\View\TemplateView::class, \FriendsOfTYPO3\Headless\XClass\TemplateView::class); + } }; diff --git a/Tests/Unit/XClass/Fixtures/Templates/Default/Default.php b/Tests/Unit/XClass/Fixtures/Templates/Default/Default.php new file mode 100644 index 00000000..1a6f43a3 --- /dev/null +++ b/Tests/Unit/XClass/Fixtures/Templates/Default/Default.php @@ -0,0 +1,12 @@ + $testValue, +]); diff --git a/Tests/Unit/XClass/TemplateViewTest.php b/Tests/Unit/XClass/TemplateViewTest.php new file mode 100644 index 00000000..9c2ab35f --- /dev/null +++ b/Tests/Unit/XClass/TemplateViewTest.php @@ -0,0 +1,72 @@ +expectException(InvalidTemplateResourceException::class); + + $GLOBALS['TYPO3_REQUEST'] = (new ServerRequest())->withAttribute('applicationType', 1); // fe request + + $context = new RenderingContext($this->createMock(ViewHelperResolver::class), $this->createMock(FluidCacheInterface::class), [], []); + + $variableProvider = new StandardVariableProvider(); + $variableProvider->add('settings', ['phpTemplate' => 1]); + + $context->setVariableProvider($variableProvider); + $view = new TemplateView($context); + $view->render(); + + $variableProvider = new StandardVariableProvider(); + $variableProvider->add('settings', ['phpTemplate' => 0]); + + $context->setVariableProvider($variableProvider); + $view = new TemplateView($context); + $view->render(); + } + + public function testTemplateRender(): void + { + $GLOBALS['TYPO3_REQUEST'] = (new ServerRequest())->withAttribute('applicationType', 1); // fe request + + $context = new RenderingContext($this->createMock(ViewHelperResolver::class), $this->createMock(FluidCacheInterface::class), [], []); + + $variableProvider = new StandardVariableProvider(); + $variableProvider->add('settings', ['phpTemplate' => 1]); + $variableProvider->add('testValue', 'TestingJsonValue'); + + $context->setVariableProvider($variableProvider); + + $templatePaths = $this->createMock(TemplatePaths::class); + $templatePaths->method('resolveTemplateFileForControllerAndActionAndFormat')->willReturn(__DIR__ . '/Fixtures/Templates/Default/Default.php'); + + $context->setTemplatePaths($templatePaths); + + $view = new TemplateView($context); + + self::assertSame(json_encode(['testKey' => 'TestingJsonValue']), $view->render()); + } +}