/** * @test */ public function processReenablesEscapingInterceptorOnClosingViewHelperTagIfItWasDisabledBefore() { $interceptorPosition = InterceptorInterface::INTERCEPT_CLOSING_VIEWHELPER; $this->mockViewHelper->expects($this->any())->method('isOutputEscapingEnabled')->will($this->returnValue(FALSE)); $this->mockNode->expects($this->any())->method('getUninitializedViewHelper')->will($this->returnValue($this->mockViewHelper)); $this->escapeInterceptor->_set('childrenEscapingEnabled', FALSE); $this->escapeInterceptor->_set('viewHelperNodesWhichDisableTheInterceptor', array($this->mockNode)); $this->escapeInterceptor->process($this->mockNode, $interceptorPosition, $this->mockParsingState); $this->assertTrue($this->escapeInterceptor->_get('childrenEscapingEnabled')); }
/** * @test */ public function testEvaluateCallsInvoker() { $resolver = $this->getMock('NamelessCoder\\Fluid\\Core\\ViewHelper\\ViewHelperResolver', array('resolveViewHelperInvoker')); $invoker = $this->getMock('NamelessCoder\\Fluid\\Core\\ViewHelper\\ViewHelperInvoker', array('invoke'), array($resolver)); $resolver->expects($this->once())->method('resolveViewHelperInvoker')->willReturn($invoker); $invoker->expects($this->once())->method('invoke')->willReturn('test'); $node = new ViewHelperNode($resolver, 'f', 'count', array(), new ParsingState()); $context = new RenderingContext(); $context->setViewHelperResolver($resolver); $result = $node->evaluate($context); $this->assertEquals('test', $result); }
/** * @test * @dataProvider getCompileTestValues * @param array $childNodes * @param $expected */ public function testCompileReturnsAndAssignsExpectedVariables(array $childNodes, $expected) { $node = new ViewHelperNode(new ViewHelperResolver(), 'f', 'if', array(), new ParsingState()); foreach ($childNodes as $childNode) { $node->addChildNode($childNode); } $compiler = $this->getMock('NamelessCoder\\Fluid\\Core\\Compiler\\TemplateCompiler', array('wrapChildNodesInClosure', 'wrapViewHelperNodeArgumentEvaluationInClosure')); $compiler->expects($this->any())->method('wrapChildNodesInClosure')->willReturn('closure'); $compiler->expects($this->any())->method('wrapViewHelperNodeArgumentEvaluationInClosure')->willReturn('arg-closure'); $init = ''; $this->viewHelper->compile('foobar-args', 'foobar-closure', $init, $node, $compiler); $this->assertEquals($expected, $init); }
/** * Helper method which triggers the rendering of everything between the * opening and the closing tag. * * @return mixed The finally rendered child nodes. * @api */ public function renderChildren() { if ($this->renderChildrenClosure !== NULL) { $closure = $this->renderChildrenClosure; return $closure(); } return $this->viewHelperNode->evaluateChildNodes($this->renderingContext); }
/** * Wraps one ViewHelper argument evaluation in a closure that can be * rendered by passing a rendering context. * * @param ViewHelperNode $node * @param string $argumentName * @return string */ public function wrapViewHelperNodeArgumentEvaluationInClosure(ViewHelperNode $node, $argumentName) { $arguments = $node->getArguments(); $argument = $arguments[$argumentName]; $closure = 'function() use ($renderingContext, $self) {' . chr(10); if ($node->getArgumentDefinition($argumentName)->getType() === 'boolean') { // We treat boolean nodes by compiling a closure to evaluate the stack of the boolean argument $compiledIfArgumentStack = $this->nodeConverter->convert(new ArrayNode($argument->getStack())); $closure .= $compiledIfArgumentStack['initialization'] . chr(10); $closure .= sprintf('return \\NamelessCoder\\Fluid\\Core\\Parser\\SyntaxTree\\BooleanNode::evaluateStack($renderingContext, %s);', $compiledIfArgumentStack['execution']) . chr(10); } else { $closure .= sprintf('$argument = unserialize(\'%s\'); return $argument->evaluate($renderingContext);', serialize($argument)) . chr(10); } $closure .= '}'; return $closure; }
/** * Initialize the given ViewHelper and adds it to the current node and to * the stack. * * @param ParsingState $state Current parsing state * @param string $namespaceIdentifier Namespace identifier - being looked up in $this->namespaces * @param string $methodIdentifier Method identifier * @param array $argumentsObjectTree Arguments object tree * @return boolean whether the viewHelper was found and added to the stack or not * @throws Exception */ protected function initializeViewHelperAndAddItToStack(ParsingState $state, $namespaceIdentifier, $methodIdentifier, $argumentsObjectTree) { if ($this->viewHelperResolver->isNamespaceValid($namespaceIdentifier, $methodIdentifier) === FALSE) { return FALSE; } $currentViewHelperNode = new ViewHelperNode($this->viewHelperResolver, $namespaceIdentifier, $methodIdentifier, $argumentsObjectTree, $state); $viewHelper = $currentViewHelperNode->getUninitializedViewHelper(); $this->callInterceptor($currentViewHelperNode, InterceptorInterface::INTERCEPT_OPENING_VIEWHELPER, $state); $viewHelper::postParseEvent($currentViewHelperNode, $argumentsObjectTree, $state->getVariableContainer()); $state->pushNodeToStack($currentViewHelperNode); return TRUE; }
/** * The compiled ViewHelper adds two new ViewHelper arguments: __thenClosure and __elseClosure. * These contain closures which are be executed to render the then(), respectively else() case. * * @param string $argumentsName * @param string $closureName * @param string $initializationPhpCode * @param ViewHelperNode $node * @param TemplateCompiler $compiler * @return string */ public function compile($argumentsName, $closureName, &$initializationPhpCode, ViewHelperNode $node, TemplateCompiler $compiler) { $thenViewHelperEncountered = $elseViewHelperEncountered = FALSE; foreach ($node->getChildNodes() as $childNode) { if ($childNode instanceof ViewHelperNode) { $viewHelperClassName = $childNode->getViewHelperClassName(); if (substr($viewHelperClassName, -14) === 'ThenViewHelper') { $thenViewHelperEncountered = TRUE; $childNodesAsClosure = $compiler->wrapChildNodesInClosure($childNode); $initializationPhpCode .= sprintf('%s[\'__thenClosure\'] = %s;', $argumentsName, $childNodesAsClosure) . chr(10); } elseif (substr($viewHelperClassName, -14) === 'ElseViewHelper') { $elseViewHelperEncountered = TRUE; $childNodesAsClosure = $compiler->wrapChildNodesInClosure($childNode); $initializationPhpCode .= sprintf('%s[\'__elseClosures\'][] = %s;', $argumentsName, $childNodesAsClosure) . chr(10); $arguments = $childNode->getArguments(); if (isset($arguments['if'])) { // The "else" has an argument, indicating it has a secondary (elseif) condition. // Compile a closure which will evaluate the condition. $elseIfConditionAsClosure = $compiler->wrapViewHelperNodeArgumentEvaluationInClosure($childNode, 'if'); $initializationPhpCode .= sprintf('%s[\'__elseifClosures\'][] = %s;', $argumentsName, $elseIfConditionAsClosure) . chr(10); } } } } if (!$thenViewHelperEncountered && !$elseViewHelperEncountered && !isset($node->getArguments()['then'])) { $initializationPhpCode .= sprintf('%s[\'__thenClosure\'] = %s;', $argumentsName, $closureName) . chr(10); } return parent::compile($argumentsName, $closureName, $initializationPhpCode, $node, $compiler); }
/** * Convert a single ViewHelperNode into its cached representation. If the ViewHelper implements the "Compilable" facet, * the ViewHelper itself is asked for its cached PHP code representation. If not, a ViewHelper is built and then invoked. * * @param ViewHelperNode $node * @return array * @see convert() */ protected function convertViewHelperNode(ViewHelperNode $node) { $initializationPhpCode = '// Rendering ViewHelper ' . $node->getViewHelperClassName() . chr(10); // Build up $arguments array $argumentsVariableName = $this->variableName('arguments'); $initializationPhpCode .= sprintf('%s = array();', $argumentsVariableName) . chr(10); $alreadyBuiltArguments = array(); foreach ($node->getArguments() as $argumentName => $argumentValue) { if ($argumentValue instanceof NodeInterface) { $converted = $this->convert($argumentValue); } else { $converted = array('initialization' => '', 'execution' => $argumentValue); } $initializationPhpCode .= $converted['initialization']; $initializationPhpCode .= sprintf('%s[\'%s\'] = %s;', $argumentsVariableName, $argumentName, $converted['execution']) . chr(10); $alreadyBuiltArguments[$argumentName] = TRUE; } $arguments = $node->getArgumentDefinitions(); foreach ($arguments as $argumentName => $argumentDefinition) { if (!isset($alreadyBuiltArguments[$argumentName])) { $initializationPhpCode .= sprintf('%s[\'%s\'] = %s;', $argumentsVariableName, $argumentName, var_export($argumentDefinition->getDefaultValue(), TRUE)) . chr(10); } } // Build up closure which renders the child nodes $renderChildrenClosureVariableName = $this->variableName('renderChildrenClosure'); $initializationPhpCode .= sprintf('%s = %s;', $renderChildrenClosureVariableName, $this->templateCompiler->wrapChildNodesInClosure($node)) . chr(10); $viewHelperInitializationPhpCode = ''; $convertedViewHelperExecutionCode = $node->getUninitializedViewHelper()->compile($argumentsVariableName, $renderChildrenClosureVariableName, $viewHelperInitializationPhpCode, $node, $this->templateCompiler); $initializationPhpCode .= $viewHelperInitializationPhpCode; $initializationArray = array('initialization' => $initializationPhpCode, 'execution' => $convertedViewHelperExecutionCode); return $initializationArray; }