[!!!][TASK] Refactor property access in compiled fluid templates
[Packages/TYPO3.CMS.git] / typo3 / sysext / fluid / Classes / Core / Compiler / TemplateCompiler.php
index c4ebb66..8cb0fdd 100644 (file)
@@ -86,6 +86,8 @@ class TemplateCompiler implements \TYPO3\CMS\Core\SingletonInterface {
                $templateCode = <<<EOD
 %s {
 
+public \$propertyAccessorReplacements = array();
+
 public function getVariableContainer() {
        // @todo
        return new \TYPO3\CMS\Fluid\Core\ViewHelper\TemplateVariableContainer();
@@ -139,6 +141,11 @@ public function %s(\TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface \$r
 
 %s
 
+       if (\$this->propertyAccessorReplacements !== array()) {
+               \$this->replacePropertyAccessors(\$this->propertyAccessorReplacements, __FILE__);
+               \$this->propertyAccessorReplacements = array();
+       }
+
 return %s;
 }
 
@@ -270,16 +277,32 @@ EOD;
        protected function convertObjectAccessorNode(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ObjectAccessorNode $node) {
                $objectPathSegments = explode('.', $node->getObjectPath());
                $firstPathElement = array_shift($objectPathSegments);
+               $nodeIdentifier = md5(spl_object_hash($node) . $node->getObjectPath() . uniqid());
                if ($objectPathSegments === array()) {
                        return array(
                                'initialization' => '',
                                'execution' => sprintf('$currentVariableContainer->getOrNull(\'%s\')', $firstPathElement)
                        );
                } else {
-                       $executionCode = '\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ObjectAccessorNode::getPropertyPath($currentVariableContainer->getOrNull(\'%s\'), \'%s\', $renderingContext)';
+                       $executionCode = <<<EOD
+/** ###%s### */ call_user_func(function(\$self) use (\$currentVariableContainer, \$renderingContext) {
+       \$subject = \$currentVariableContainer->getOrNull('%s');
+
+       \$accessors = \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ObjectAccessorNode::getPropertyAccessors(\$subject, %s);
+
+       if (\$accessors !== NULL) {
+               \$self->propertyAccessorReplacements['~/\*\* ###%s### \*/ .* /\*\* ###%s### \*/~s'] = '\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ObjectAccessorNode::resolvePropertyAccessors(\$currentVariableContainer->getOrNull(\'%s\'), ' . var_export(\$accessors, TRUE) . ')';
+               return \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ObjectAccessorNode::resolvePropertyAccessors(\$subject, \$accessors);
+       } else {
+               \$self->propertyAccessorReplacements['~/\*\* ###%s### \*/ .* /\*\* ###%s### \*/~s'] = '\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ObjectAccessorNode::getPropertyPath(\$currentVariableContainer->getOrNull(\'%s\'), \'%s\', \$renderingContext)';
+               return \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ObjectAccessorNode::getPropertyPath(\$subject, '%s', \$renderingContext);
+       }
+}, \$self) /** ###%s### */
+
+EOD;
                        return array(
                                'initialization' => '',
-                               'execution' => sprintf($executionCode, $firstPathElement, implode('.', $objectPathSegments))
+                               'execution' => sprintf($executionCode, $nodeIdentifier, $firstPathElement, var_export($objectPathSegments, TRUE), $nodeIdentifier, $nodeIdentifier, $firstPathElement, $nodeIdentifier, $nodeIdentifier, $firstPathElement, implode('.', $objectPathSegments), implode('.', $objectPathSegments), $nodeIdentifier)
                        );
                }
        }