/** * Invoke the ViewHelper described by the ViewHelperNode, the properties * of which will already have been filled by the ViewHelperResolver. * * @param string|ViewHelperInterface $viewHelperClassName * @param array $arguments * @param RenderingContextInterface $renderingContext * @param \Closure $renderChildrenClosure * @return mixed */ public function invoke($viewHelperClassNameOrInstance, array $arguments, RenderingContextInterface $renderingContext, \Closure $renderChildrenClosure = NULL) { if ($viewHelperClassNameOrInstance instanceof ViewHelperInterface) { $viewHelper = $viewHelperClassNameOrInstance; } else { $viewHelper = $this->viewHelperResolver->createViewHelperInstanceFromClassName($viewHelperClassNameOrInstance); } $expectedViewHelperArguments = $renderingContext->getViewHelperResolver()->getArgumentDefinitionsForViewHelper($viewHelper); // Rendering process $evaluatedArguments = array(); foreach ($expectedViewHelperArguments as $argumentName => $argumentDefinition) { if (isset($arguments[$argumentName])) { /** @var NodeInterface|mixed $argumentValue */ $argumentValue = $arguments[$argumentName]; $evaluatedArguments[$argumentName] = $argumentValue instanceof NodeInterface ? $argumentValue->evaluate($renderingContext) : $argumentValue; } else { $evaluatedArguments[$argumentName] = $argumentDefinition->getDefaultValue(); } } $this->abortIfUnregisteredArgumentsExist($expectedViewHelperArguments, $evaluatedArguments); $this->abortIfRequiredArgumentsAreMissing($expectedViewHelperArguments, $evaluatedArguments); $viewHelper->setArguments($evaluatedArguments); $viewHelper->setRenderingContext($renderingContext); if ($renderChildrenClosure) { $viewHelper->setRenderChildrenClosure($renderChildrenClosure); } return $viewHelper->initializeArgumentsAndRender(); }
/** * Constructor. * * @param ViewHelperResolver an instance or subclass of ViewHelperResolver * @param string $namespace the namespace identifier of the ViewHelper. * @param string $identifier the name of the ViewHelper to render, inside the namespace provided. * @param NodeInterface[] $arguments Arguments of view helper - each value is a RootNode. * @param ParsingState $state */ public function __construct(ViewHelperResolver $resolver, $namespace, $identifier, array $arguments, ParsingState $state) { $this->viewHelperResolver = $resolver; $this->viewHelperClassName = $resolver->resolveViewHelperClassName($namespace, $identifier); $this->uninitializedViewHelper = $resolver->createViewHelperInstance($namespace, $identifier); $this->arguments = $arguments; $this->argumentDefinitions = $resolver->getArgumentDefinitionsForViewHelper($this->uninitializedViewHelper); $this->rewriteBooleanNodesInArgumentsObjectTree($this->argumentDefinitions, $this->arguments); }
/** * Setup fixture */ public function setUp() { $this->renderingContext = new RenderingContextFixture(); $this->mockViewHelperResolver = $this->getMock(ViewHelperResolver::class, ['resolveViewHelperClassName', 'createViewHelperInstanceFromClassName', 'getArgumentDefinitionsForViewHelper']); $this->mockViewHelperResolver->expects($this->any())->method('resolveViewHelperClassName')->with('f', 'vh')->willReturn(TestViewHelper::class); $this->mockViewHelperResolver->expects($this->any())->method('createViewHelperInstanceFromClassName')->with(TestViewHelper::class)->willReturn(new TestViewHelper()); $this->mockViewHelperResolver->expects($this->any())->method('getArgumentDefinitionsForViewHelper')->willReturn(['foo' => new ArgumentDefinition('foo', 'string', 'Dummy required argument', true)]); $this->renderingContext->setViewHelperResolver($this->mockViewHelperResolver); }
/** * Asks the ViewHelper for argument definitions and adds * a case which matches our custom ViewHelper in order to * manipulate its argument definitions. * * @param ViewHelperInterface $viewHelper * @return ArgumentDefinition[] */ public function getArgumentDefinitionsForViewHelper(ViewHelperInterface $viewHelper) { $arguments = parent::getArgumentDefinitionsForViewHelper($viewHelper); if ($viewHelper instanceof CustomViewHelper) { $arguments['page'] = new ArgumentDefinition('page', 'array', 'This is our new description for the argument', false, ['foo' => 'bar']); } return $arguments; }
/** * Handler for everything which is not a ViewHelperNode. * * This includes Text, array syntax, and object accessor syntax. * * @param ParsingState $state Current parsing state * @param string $text Text to process * @param integer $context one of the CONTEXT_* constants, defining whether we are inside or outside of ViewHelper arguments currently. * @return void */ protected function textAndShorthandSyntaxHandler(ParsingState $state, $text, $context) { $sections = preg_split(Patterns::$SPLIT_PATTERN_SHORTHANDSYNTAX, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); foreach ($sections as $section) { $matchedVariables = array(); $expressionNode = NULL; if (preg_match(Patterns::$SCAN_PATTERN_SHORTHANDSYNTAX_OBJECTACCESSORS, $section, $matchedVariables) > 0) { $this->objectAccessorHandler($state, $matchedVariables['Object'], $matchedVariables['Delimiter'], isset($matchedVariables['ViewHelper']) ? $matchedVariables['ViewHelper'] : '', isset($matchedVariables['AdditionalViewHelpers']) ? $matchedVariables['AdditionalViewHelpers'] : ''); } elseif ($context === self::CONTEXT_INSIDE_VIEWHELPER_ARGUMENTS && preg_match(Patterns::$SCAN_PATTERN_SHORTHANDSYNTAX_ARRAYS, $section, $matchedVariables) > 0) { // We only match arrays if we are INSIDE viewhelper arguments $this->arrayHandler($state, $this->recursiveArrayHandler($matchedVariables['Array'])); } else { // We ask custom ExpressionNode instances from ViewHelperResolver // if any match our expression: foreach ($this->viewHelperResolver->getExpressionNodeTypes() as $expressionNodeTypeClassName) { $detetionExpression = $expressionNodeTypeClassName::$detectionExpression; $matchedVariables = array(); preg_match_all($detetionExpression, $section, $matchedVariables, PREG_SET_ORDER); foreach ($matchedVariables as $matchedVariableSet) { $expressionStartPosition = strpos($section, $matchedVariableSet[0]); $expressionNode = new $expressionNodeTypeClassName($matchedVariableSet[0], $matchedVariableSet, $state); if ($expressionStartPosition > 0) { $state->getNodeFromStack()->addChildNode(new TextNode(substr($section, 0, $expressionStartPosition))); } $state->getNodeFromStack()->addChildNode($expressionNode); $expressionEndPosition = $expressionStartPosition + strlen($matchedVariableSet[0]); if ($expressionEndPosition < strlen($section)) { $this->textAndShorthandSyntaxHandler($state, substr($section, $expressionEndPosition), $context); break; } } } // As fallback we simply render the expression back as template content. if (!$expressionNode) { $this->textHandler($state, $section); } } } }
/** * @test */ public function testIsNamespaceReturnsFalseIfNamespaceNotValid() { $resolver = new ViewHelperResolver(); $result = $resolver->isNamespaceValid('test2', 'test'); $this->assertFalse($result); }
/** * @param array $namespaces * @param string $subject * @param boolean $expected * @test * @dataProvider getIsNamespaceValidOrIgnoredTestValues */ public function testIsNamespaceValidOrIgnoredTestValues(array $namespaces, $subject, $expected) { $resolver = new ViewHelperResolver(); $resolver->setNamespaces($namespaces); $result = $resolver->isNamespaceValidOrIgnored($subject); $this->assertEquals($expected, $result); }