diff --git a/Neos.FluidAdaptor/Classes/Core/ViewHelper/TemplateVariableContainer.php b/Neos.FluidAdaptor/Classes/Core/ViewHelper/TemplateVariableContainer.php index 3a042ec52a..622db76013 100644 --- a/Neos.FluidAdaptor/Classes/Core/ViewHelper/TemplateVariableContainer.php +++ b/Neos.FluidAdaptor/Classes/Core/ViewHelper/TemplateVariableContainer.php @@ -24,18 +24,7 @@ */ class TemplateVariableContainer extends StandardVariableProvider implements VariableProviderInterface { - /** - * @param string $identifier - * @return mixed - */ - public function get($identifier) - { - $subject = parent::get($identifier); - if ($subject instanceof TemplateObjectAccessInterface) { - $subject = $subject->objectAccess(); - } - return $subject; - } + const ACCESSOR_OBJECT_ACCESS = 'object_access'; /** * Get a variable by dotted path expression, retrieving the @@ -50,27 +39,63 @@ public function get($identifier) */ public function getByPath($path, array $accessors = []) { - $propertyPathSegments = explode('.', $path); - $subject = $this->variables; + $subject = parent::getByPath($path, $accessors); - foreach ($propertyPathSegments as $propertyName) { - if ($subject === null) { - break; + if ($subject === null) { + $subject = $this->getBooleanValue($path); + } + + return $subject; + } + + /** + * @param string $propertyPath + * @return string + */ + protected function resolveSubVariableReferences($propertyPath) + { + if (strpos($propertyPath, '{') !== false) { + // NOTE: This is an inclusion of https://github.com/TYPO3/Fluid/pull/472 to allow multiple nested variables + preg_match_all('/(\{.*?\})/', $propertyPath, $matches); + foreach ($matches[1] as $match) { + $subPropertyPath = substr($match, 1, -1); + $propertyPath = str_replace($match, $this->getByPath($subPropertyPath), $propertyPath); } + } + return $propertyPath; + } + + /** + * @param mixed $subject + * @param string $propertyName + * @return NULL|string + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + protected function detectAccessor($subject, $propertyName) + { + return TemplateVariableContainer::ACCESSOR_OBJECT_ACCESS; + } + /** + * @param mixed $subject + * @param string $propertyName + * @param string $accessor + * @return mixed|null + */ + protected function extractWithAccessor($subject, $propertyName, $accessor) + { + if (TemplateVariableContainer::ACCESSOR_OBJECT_ACCESS === $accessor) { try { $subject = ObjectAccess::getProperty($subject, $propertyName); - } catch (PropertyNotAccessibleException $exception) { + } catch (PropertyNotAccessibleException $e) { $subject = null; } - - if ($subject instanceof TemplateObjectAccessInterface) { - $subject = $subject->objectAccess(); - } + } else { + $subject = parent::extractWithAccessor($subject, $propertyName, $accessor); } - if ($subject === null) { - $subject = $this->getBooleanValue($path); + if ($subject instanceof TemplateObjectAccessInterface) { + return $subject->objectAccess(); } return $subject; diff --git a/Neos.FluidAdaptor/Tests/Functional/View/StandaloneViewTest.php b/Neos.FluidAdaptor/Tests/Functional/View/StandaloneViewTest.php index 70a3b31619..ebaf78c052 100644 --- a/Neos.FluidAdaptor/Tests/Functional/View/StandaloneViewTest.php +++ b/Neos.FluidAdaptor/Tests/Functional/View/StandaloneViewTest.php @@ -178,6 +178,22 @@ public function variablesAreNotEscapedIfEscapingIsDisabled() $this->assertSame($expected, $actual); } + /** + * @test + */ + public function variablesCanBeNested() + { + $standaloneView = new StandaloneView(null, $this->standaloneViewNonce); + $standaloneView->assign('type', 'thing'); + $standaloneView->assign('flavor', 'yellow'); + $standaloneView->assign('config', ['thing' => ['value' => ['yellow' => 'Okayish']]]); + $standaloneView->setTemplateSource('{config.{type}.value.{flavor}}'); + + $expected = 'Okayish'; + $actual = $standaloneView->render(); + $this->assertSame($expected, $actual); + } + /** * @test */