2 namespace TYPO3\CMS\Fluid\Core\Compiler;
46 public function has($identifier)
49 return $this->templateCache->has($identifier);
56 public function get($identifier)
59 if (!isset($this->syntaxTreeInstanceCache[$identifier])) {
60 $this->templateCache->requireOnce($identifier);
61 $templateClassName =
'FluidCache_' . $identifier;
62 $this->syntaxTreeInstanceCache[$identifier] =
new $templateClassName();
64 return $this->syntaxTreeInstanceCache[$identifier];
72 public function store($identifier, \TYPO3\CMS\
Fluid\Core\Parser\ParsingState $parsingState)
75 $this->variableCounter = 0;
76 $generatedRenderFunctions =
'';
78 if ($parsingState->getVariableContainer()->exists(
'sections')) {
79 $sections = $parsingState->getVariableContainer()->get(
'sections');
81 foreach ($sections as $sectionName => $sectionRootNode) {
86 $convertedLayoutNameNode = $parsingState->hasLayout() ? $this->
convert($parsingState->getLayoutNameNode()) : array(
'initialization' =>
'',
'execution' =>
'NULL');
88 $classDefinition =
'class FluidCache_' . $identifier .
' extends \\TYPO3\\CMS\\Fluid\\Core\\Compiler\\AbstractCompiledTemplate';
90 $templateCode = <<<EOD
93 public function getVariableContainer() {
95 return new \TYPO3\CMS\Fluid\Core\ViewHelper\TemplateVariableContainer();
97 public function getLayoutName(\TYPO3\CMS\
Fluid\Core\Rendering\RenderingContextInterface \$renderingContext) {
98 \$currentVariableContainer = \$renderingContext->getTemplateVariableContainer();
102 public function hasLayout() {
110 $templateCode = sprintf($templateCode,
112 $convertedLayoutNameNode[
'initialization'],
113 $convertedLayoutNameNode[
'execution'],
114 ($parsingState->hasLayout() ?
'TRUE' :
'FALSE'),
115 $generatedRenderFunctions);
116 $this->templateCache->set($identifier, $templateCode);
128 return preg_replace(
'([^a-zA-Z0-9_\\x7f-\\xff])',
'_', $identifier);
139 $templateCode = <<<EOD
143 public function %s(\TYPO3\CMS\
Fluid\Core\Rendering\RenderingContextInterface \$renderingContext) {
145 \$currentVariableContainer = \$renderingContext->getTemplateVariableContainer();
153 return sprintf($templateCode, $comment, $expectedFunctionName, $converted[
'initialization'], $converted[
'execution']);
165 protected function convert(\TYPO3\CMS\
Fluid\Core\Parser\SyntaxTree\AbstractNode $node)
167 if ($node instanceof \TYPO3\CMS\
Fluid\Core\Parser\SyntaxTree\TextNode) {
169 }
elseif ($node instanceof \TYPO3\CMS\
Fluid\Core\Parser\SyntaxTree\NumericNode) {
171 }
elseif ($node instanceof \TYPO3\CMS\
Fluid\Core\Parser\SyntaxTree\ViewHelperNode) {
173 }
elseif ($node instanceof \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ObjectAccessorNode) {
175 }
elseif ($node instanceof \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ArrayNode) {
177 }
elseif ($node instanceof \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\RootNode) {
179 }
elseif ($node instanceof \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\BooleanNode) {
182 throw new \TYPO3\CMS\Fluid\Exception(
'Syntax tree node type "' . get_class($node) .
'" is not supported.');
191 protected function convertTextNode(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\TextNode $node)
194 'initialization' =>
'',
204 protected function convertNumericNode(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\NumericNode $node)
207 'initialization' =>
'',
208 'execution' => $node->getValue()
220 protected function convertViewHelperNode(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ViewHelperNode $node)
222 $initializationPhpCode =
'// Rendering ViewHelper ' . $node->getViewHelperClassName() . LF;
225 $argumentsVariableName = $this->
variableName(
'arguments');
226 $initializationPhpCode .= sprintf(
'%s = array();', $argumentsVariableName) . LF;
228 $alreadyBuiltArguments = array();
229 foreach ($node->getArguments() as $argumentName => $argumentValue) {
230 $converted = $this->
convert($argumentValue);
231 $initializationPhpCode .= $converted[
'initialization'];
232 $initializationPhpCode .= sprintf(
'%s[\'%s\'] = %s;', $argumentsVariableName, $argumentName, $converted[
'execution']) . LF;
233 $alreadyBuiltArguments[$argumentName] =
true;
236 foreach ($node->getUninitializedViewHelper()->prepareArguments() as $argumentName => $argumentDefinition) {
237 if (!isset($alreadyBuiltArguments[$argumentName])) {
238 $initializationPhpCode .= sprintf(
'%s[\'%s\'] = %s;', $argumentsVariableName, $argumentName, var_export($argumentDefinition->getDefaultValue(),
true)) . LF;
243 $renderChildrenClosureVariableName = $this->
variableName(
'renderChildrenClosure');
244 $initializationPhpCode .= sprintf(
'%s = %s;', $renderChildrenClosureVariableName, $this->
wrapChildNodesInClosure($node)) . LF;
246 if ($node->getUninitializedViewHelper() instanceof \TYPO3\CMS\Fluid\Core\ViewHelper\Facets\CompilableInterface) {
248 $viewHelperInitializationPhpCode =
'';
249 $convertedViewHelperExecutionCode = $node->getUninitializedViewHelper()->compile($argumentsVariableName, $renderChildrenClosureVariableName, $viewHelperInitializationPhpCode, $node, $this);
250 $initializationPhpCode .= $viewHelperInitializationPhpCode;
251 if ($convertedViewHelperExecutionCode !== self::SHOULD_GENERATE_VIEWHELPER_INVOCATION) {
253 'initialization' => $initializationPhpCode,
254 'execution' => $convertedViewHelperExecutionCode
260 $viewHelperVariableName = $this->
variableName(
'viewHelper');
262 $initializationPhpCode .= sprintf(
'%s = $self->getViewHelper(\'%s\', $renderingContext, \'%s\');', $viewHelperVariableName, $viewHelperVariableName, $node->getViewHelperClassName()) . LF;
263 $initializationPhpCode .= sprintf(
'%s->setArguments(%s);', $viewHelperVariableName, $argumentsVariableName) . LF;
264 $initializationPhpCode .= sprintf(
'%s->setRenderingContext($renderingContext);', $viewHelperVariableName) . LF;
266 $initializationPhpCode .= sprintf(
'%s->setRenderChildrenClosure(%s);', $viewHelperVariableName, $renderChildrenClosureVariableName) . LF;
268 $initializationPhpCode .=
'// End of ViewHelper ' . $node->getViewHelperClassName() . LF;
271 'initialization' => $initializationPhpCode,
272 'execution' => sprintf(
'%s->initializeArgumentsAndRender()', $viewHelperVariableName)
283 $objectPathSegments = explode(
'.', $node->getObjectPath());
284 $firstPathElement = array_shift($objectPathSegments);
285 if ($objectPathSegments === array()) {
287 'initialization' =>
'',
288 'execution' => sprintf(
'$currentVariableContainer->getOrNull(\'%s\')', $firstPathElement)
291 $executionCode =
'\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ObjectAccessorNode::getPropertyPath($currentVariableContainer->getOrNull(\'%s\'), \'%s\', $renderingContext)';
293 'initialization' =>
'',
294 'execution' => sprintf($executionCode, $firstPathElement, implode(
'.', $objectPathSegments))
304 protected function convertArrayNode(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ArrayNode $node)
306 $initializationPhpCode =
'// Rendering Array' . LF;
309 $initializationPhpCode .= sprintf(
'%s = array();', $arrayVariableName) . LF;
311 foreach ($node->getInternalArray() as $key => $value) {
312 if ($value instanceof \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\AbstractNode) {
313 $converted = $this->
convert($value);
314 $initializationPhpCode .= $converted[
'initialization'];
315 $initializationPhpCode .= sprintf(
'%s[\'%s\'] = %s;', $arrayVariableName, $key, $converted[
'execution']) . LF;
316 }
elseif (is_numeric($value)) {
318 $initializationPhpCode .= sprintf(
'%s[\'%s\'] = %s;', $arrayVariableName, $key, $value) . LF;
325 'initialization' => $initializationPhpCode,
326 'execution' => $arrayVariableName
337 switch (count($node->getChildNodes())) {
340 'initialization' =>
'',
341 'execution' =>
'NULL'
344 $converted = $this->
convert(current($node->getChildNodes()));
349 $initializationPhpCode = sprintf(
'%s = \'\';', $outputVariableName) . LF;
351 foreach ($node->getChildNodes() as $childNode) {
352 $converted = $this->
convert($childNode);
354 $initializationPhpCode .= $converted[
'initialization'] . LF;
355 $initializationPhpCode .= sprintf(
'%s .= %s;', $outputVariableName, $converted[
'execution']) . LF;
359 'initialization' => $initializationPhpCode,
360 'execution' => $outputVariableName
370 protected function convertBooleanNode(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\BooleanNode $node)
372 $initializationPhpCode =
'// Rendering Boolean node' . LF;
373 if ($node->getComparator() !== null) {
374 $convertedLeftSide = $this->
convert($node->getLeftSide());
375 $convertedRightSide = $this->
convert($node->getRightSide());
378 'initialization' => $initializationPhpCode . $convertedLeftSide[
'initialization'] . $convertedRightSide[
'initialization'],
379 'execution' => sprintf(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\BooleanNode::class .
'::evaluateComparator(\'%s\', %s, %s)', $node->getComparator(), $convertedLeftSide[
'execution'], $convertedRightSide[
'execution'])
383 $converted = $this->
convert($node->getSyntaxTreeNode());
385 'initialization' => $initializationPhpCode . $converted[
'initialization'],
386 'execution' => sprintf(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\BooleanNode::class .
'::convertToBoolean(%s)', $converted[
'execution'])
397 return str_replace(array(
'\\',
'\''), array(
'\\\\',
'\\\''), $text);
407 if ($convertedSubNodes[
'execution'] ===
'NULL') {
408 return 'function() {return NULL;}';
412 $closure .=
'function() use ($renderingContext, $self) {' . LF;
413 $closure .=
'$currentVariableContainer = $renderingContext->getTemplateVariableContainer();' . LF;
414 $closure .= $convertedSubNodes[
'initialization'];
415 $closure .= sprintf(
'return %s;', $convertedSubNodes[
'execution']) . LF;
428 return '$' . $prefix . $this->variableCounter++;