From 3bddf0968f758711847be5a39d1aeaee792c3bd5 Mon Sep 17 00:00:00 2001 From: Claus Due <claus@namelesscoder.net> Date: Fri, 31 Jan 2020 20:44:11 +0100 Subject: [PATCH] [TASK] Check methods in RenderingContext before calling Checks for method presence before attempting to call them, and exposes getControllerName/getControllerAction for public usage. Release: master, 9.5, 8.7 Resolves: #90284 Change-Id: I29b850ccb2f535c1f708af32a61e50c04386d9b7 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/63111 Tested-by: TYPO3com <noreply@typo3.com> Tested-by: Manuel Selbach <manuel_selbach@yahoo.de> Tested-by: Kevin Appelt <kevin.appelt@icloud.com> Tested-by: Claus Due <claus@phpmind.net> Reviewed-by: Manuel Selbach <manuel_selbach@yahoo.de> Reviewed-by: Kevin Appelt <kevin.appelt@icloud.com> Reviewed-by: Claus Due <claus@phpmind.net> --- .../Core/Rendering/RenderingContext.php | 94 ++++++++++++++----- .../Core/Rendering/RenderingContextTest.php | 8 +- 2 files changed, 77 insertions(+), 25 deletions(-) diff --git a/typo3/sysext/fluid/Classes/Core/Rendering/RenderingContext.php b/typo3/sysext/fluid/Classes/Core/Rendering/RenderingContext.php index 12577e91e8d4..d2365d181214 100644 --- a/typo3/sysext/fluid/Classes/Core/Rendering/RenderingContext.php +++ b/typo3/sysext/fluid/Classes/Core/Rendering/RenderingContext.php @@ -41,6 +41,16 @@ class RenderingContext extends \TYPO3Fluid\Fluid\Core\Rendering\RenderingContext */ protected $controllerContext; + /** + * @var string + */ + protected $controllerName = 'Default'; + + /** + * @var string + */ + protected $controllerAction = 'Default'; + /** * @param \TYPO3Fluid\Fluid\Core\ViewHelper\ViewHelperVariableContainer $viewHelperVariableContainer */ @@ -62,26 +72,46 @@ class RenderingContext extends \TYPO3Fluid\Fluid\Core\Rendering\RenderingContext } else { // Reproduced partial initialisation from parent::__construct; minus the custom // implementations we attach below. - $this->setTemplateParser(new TemplateParser()); - $this->setTemplateCompiler(new TemplateCompiler()); - $this->setViewHelperInvoker(new ViewHelperInvoker()); + $this->setTemplateParser(new TemplateParser($this)); + if (method_exists($this, 'setTemplateCompiler')) { + $this->setTemplateCompiler(new TemplateCompiler()); + } + if (method_exists($this, 'setViewHelperInvoker')) { + $this->setViewHelperInvoker(new ViewHelperInvoker()); + } $this->setViewHelperVariableContainer(new ViewHelperVariableContainer()); $this->setVariableProvider(new StandardVariableProvider()); } $objectManager = GeneralUtility::makeInstance(ObjectManager::class); - $this->setTemplateProcessors(array_map([$objectManager, 'get'], $GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['preProcessors'])); + if (method_exists($this, 'setTemplateProcessors')) { + $this->setTemplateProcessors(array_map([$objectManager, 'get'], $GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['preProcessors'])); + } $this->setExpressionNodeTypes($GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['expressionNodeTypes']); $this->setTemplatePaths($objectManager->get(TemplatePaths::class)); $this->setViewHelperResolver($objectManager->get(ViewHelperResolver::class)); - /** @var FluidTemplateCache $cache */ - $cache = $objectManager->get(CacheManager::class)->getCache('fluid_template'); - if (is_a($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['fluid_template']['frontend'], FluidTemplateCache::class, true)) { - $this->setCache($cache); + if (method_exists($this, 'setCache')) { + /** @var FluidTemplateCache $cache */ + $cache = $objectManager->get(CacheManager::class)->getCache('fluid_template'); + if (is_a($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['fluid_template']['frontend'], FluidTemplateCache::class, true)) { + $this->setCache($cache); + } } } + /** + * Alternative to buildParserConfiguration, called only in Fluid 3.0 + * + * @return Configuration + */ + public function getParserConfiguration(): Configuration + { + $parserConfiguration = parent::getParserConfiguration(); + $this->addInterceptorsToParserConfiguration($GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['interceptors'], $parserConfiguration); + return $parserConfiguration; + } + /** * Build parser configuration * @@ -91,17 +121,19 @@ class RenderingContext extends \TYPO3Fluid\Fluid\Core\Rendering\RenderingContext public function buildParserConfiguration() { $parserConfiguration = parent::buildParserConfiguration(); - if (!empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['interceptors'])) { - foreach ($GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['interceptors'] as $className) { - $interceptor = GeneralUtility::makeInstance($className); - if (!$interceptor instanceof InterceptorInterface) { - throw new \InvalidArgumentException('Interceptor "' . $className . '" needs to implement ' . InterceptorInterface::class . '.', 1462869795); - } - $parserConfiguration->addInterceptor($interceptor); + $this->addInterceptorsToParserConfiguration($GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['interceptors'], $parserConfiguration); + return $parserConfiguration; + } + + protected function addInterceptorsToParserConfiguration(iterable $interceptors, Configuration $parserConfiguration): void + { + foreach ($interceptors as $className) { + $interceptor = GeneralUtility::makeInstance($className); + if (!$interceptor instanceof InterceptorInterface) { + throw new \InvalidArgumentException('Interceptor "' . $className . '" needs to implement ' . InterceptorInterface::class . '.', 1462869795); } + $parserConfiguration->addInterceptor($interceptor); } - - return $parserConfiguration; } /** @@ -123,8 +155,10 @@ class RenderingContext extends \TYPO3Fluid\Fluid\Core\Rendering\RenderingContext if ($dotPosition !== false) { $action = substr($action, 0, $dotPosition); } - parent::setControllerAction($action); - $this->controllerContext->getRequest()->setControllerActionName(lcfirst($action)); + $this->controllerAction = $action; + if ($this->controllerContext) { + $this->controllerContext->getRequest()->setControllerActionName(lcfirst($action)); + } } /** @@ -133,8 +167,26 @@ class RenderingContext extends \TYPO3Fluid\Fluid\Core\Rendering\RenderingContext */ public function setControllerName($controllerName) { - parent::setControllerName($controllerName); - $this->controllerContext->getRequest()->setControllerName($controllerName); + $this->controllerName = $controllerName; + if ($this->controllerContext) { + $this->controllerContext->getRequest()->setControllerName($controllerName); + } + } + + /** + * @return string + */ + public function getControllerName() + { + return $this->controllerContext ? $this->controllerContext->getRequest()->getControllerName() : $this->controllerName; + } + + /** + * @return string + */ + public function getControllerAction() + { + return $this->controllerContext ? $this->controllerContext->getRequest()->getControllerActionName() : $this->controllerAction; } /** diff --git a/typo3/sysext/fluid/Tests/Unit/Core/Rendering/RenderingContextTest.php b/typo3/sysext/fluid/Tests/Unit/Core/Rendering/RenderingContextTest.php index 3b457ecc444a..f3d5d4ac51cb 100644 --- a/typo3/sysext/fluid/Tests/Unit/Core/Rendering/RenderingContextTest.php +++ b/typo3/sysext/fluid/Tests/Unit/Core/Rendering/RenderingContextTest.php @@ -109,14 +109,14 @@ class RenderingContextTest extends UnitTestCase ->addMethods(['dummy']) ->disableOriginalConstructor() ->getMock(); - $request = $this->getMockBuilder(Request::class)->setMethods(['setControllerActionName'])->getMock(); - $request->expects(self::at(0))->method('setControllerActionName')->with('index'); - $request->expects(self::at(1))->method('setControllerActionName')->with(lcfirst($expected)); + $request = $this->getMockBuilder(Request::class)->getMock(); + $request->expects(self::exactly(2))->method('setControllerActionName')->with(lcfirst($expected)); + $request->expects(self::exactly(2))->method('getControllerActionName')->willReturn(lcfirst($expected)); $controllerContext = $this->getMockBuilder(ControllerContext::class)->setMethods(['getRequest'])->getMock(); $controllerContext->expects(self::atLeastOnce())->method('getRequest')->willReturn($request); $subject->setControllerContext($controllerContext); $subject->setControllerAction($input); - self::assertEquals($expected, $subject->getControllerAction()); + self::assertSame(lcfirst($expected), $subject->getControllerAction()); } /** -- GitLab