1
|
|
|
<?php |
2
|
|
|
namespace TYPO3Fluid\Fluid\Core\ViewHelper; |
3
|
|
|
|
4
|
|
|
/* |
5
|
|
|
* This file belongs to the package "TYPO3 Fluid". |
6
|
|
|
* See LICENSE.txt that was shipped with this package. |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
use TYPO3Fluid\Fluid\Core\Parser\SyntaxTree\NodeInterface; |
10
|
|
|
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Class ViewHelperInvoker |
14
|
|
|
* |
15
|
|
|
* Class which is responsible for calling the render methods |
16
|
|
|
* on ViewHelpers, and this alone. |
17
|
|
|
* |
18
|
|
|
* Can be replaced via the ViewHelperResolver if the system |
19
|
|
|
* that implements Fluid requires special handling of classes. |
20
|
|
|
* This includes for example when you want to validate arguments |
21
|
|
|
* differently, wish to use another ViewHelper initialization |
22
|
|
|
* process, or wish to store instances of ViewHelpers to reuse |
23
|
|
|
* as if they were Singletons. |
24
|
|
|
* |
25
|
|
|
* To override the instantiation process and class name resolving, |
26
|
|
|
* see ViewHelperResolver. This particular class should only be |
27
|
|
|
* responsible for invoking the render method of a ViewHelper |
28
|
|
|
* using the properties available in the node. |
29
|
|
|
*/ |
30
|
|
|
class ViewHelperInvoker |
31
|
|
|
{ |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Invoke the ViewHelper described by the ViewHelperNode, the properties |
35
|
|
|
* of which will already have been filled by the ViewHelperResolver. |
36
|
|
|
* |
37
|
|
|
* @param string|ViewHelperInterface $viewHelperClassNameOrInstance |
38
|
|
|
* @param array $arguments |
39
|
|
|
* @param RenderingContextInterface $renderingContext |
40
|
|
|
* @param null|\Closure $renderChildrenClosure |
41
|
|
|
* @return string |
42
|
|
|
*/ |
43
|
|
|
public function invoke($viewHelperClassNameOrInstance, array $arguments, RenderingContextInterface $renderingContext, \Closure $renderChildrenClosure = null) |
44
|
|
|
{ |
45
|
|
|
$viewHelperResolver = $renderingContext->getViewHelperResolver(); |
46
|
|
|
if ($viewHelperClassNameOrInstance instanceof ViewHelperInterface) { |
47
|
|
|
$viewHelper = $viewHelperClassNameOrInstance; |
48
|
|
|
} else { |
49
|
|
|
$viewHelper = $viewHelperResolver->createViewHelperInstanceFromClassName($viewHelperClassNameOrInstance); |
50
|
|
|
} |
51
|
|
|
$expectedViewHelperArguments = $viewHelperResolver->getArgumentDefinitionsForViewHelper($viewHelper); |
52
|
|
|
|
53
|
|
|
// Rendering process |
54
|
|
|
$evaluatedArguments = []; |
55
|
|
|
$undeclaredArguments = []; |
56
|
|
|
|
57
|
|
|
try { |
58
|
|
View Code Duplication |
foreach ($expectedViewHelperArguments as $argumentName => $argumentDefinition) { |
|
|
|
|
59
|
|
|
$argumentValue = $arguments[$argumentName] ?? $argumentDefinition->getDefaultValue(); |
60
|
|
|
$evaluatedArguments[$argumentName] = $argumentValue instanceof NodeInterface ? $argumentValue->evaluate($renderingContext) : $argumentValue; |
61
|
|
|
} |
62
|
|
View Code Duplication |
foreach ($arguments as $argumentName => $argumentValue) { |
|
|
|
|
63
|
|
|
if (!isset($evaluatedArguments[$argumentName])) { |
64
|
|
|
$undeclaredArguments[$argumentName] = $argumentValue instanceof NodeInterface ? $argumentValue->evaluate($renderingContext) : $argumentValue; |
65
|
|
|
} |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
if ($renderChildrenClosure) { |
69
|
|
|
$viewHelper->setRenderChildrenClosure($renderChildrenClosure); |
70
|
|
|
} |
71
|
|
|
$viewHelper->setRenderingContext($renderingContext); |
72
|
|
|
$viewHelper->setArguments($evaluatedArguments); |
73
|
|
|
$viewHelper->handleAdditionalArguments($undeclaredArguments); |
74
|
|
|
return $viewHelper->initializeArgumentsAndRender(); |
75
|
|
|
} catch (Exception $error) { |
76
|
|
|
return $renderingContext->getErrorHandler()->handleViewHelperError($error); |
77
|
|
|
} |
78
|
|
|
} |
79
|
|
|
} |
80
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.