[ Index ] |
PHP Cross Reference of phpBB-3.2.11-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 3 /* 4 * This file is part of Twig. 5 * 6 * (c) Fabien Potencier 7 * (c) Armin Ronacher 8 * 9 * For the full copyright and license information, please view the LICENSE 10 * file that was distributed with this source code. 11 */ 12 13 namespace Twig\Node; 14 15 use Twig\Compiler; 16 use Twig\Node\Expression\AbstractExpression; 17 use Twig\Node\Expression\ConstantExpression; 18 use Twig\Source; 19 20 /** 21 * Represents a module node. 22 * 23 * Consider this class as being final. If you need to customize the behavior of 24 * the generated class, consider adding nodes to the following nodes: display_start, 25 * display_end, constructor_start, constructor_end, and class_end. 26 * 27 * @author Fabien Potencier <fabien@symfony.com> 28 */ 29 class ModuleNode extends Node 30 { 31 public function __construct(\Twig_NodeInterface $body, AbstractExpression $parent = null, \Twig_NodeInterface $blocks, \Twig_NodeInterface $macros, \Twig_NodeInterface $traits, $embeddedTemplates, $name, $source = '') 32 { 33 if (!$name instanceof Source) { 34 @trigger_error(sprintf('Passing a string as the $name argument of %s() is deprecated since version 1.27. Pass a \Twig\Source instance instead.', __METHOD__), E_USER_DEPRECATED); 35 $source = new Source($source, $name); 36 } else { 37 $source = $name; 38 } 39 40 $nodes = [ 41 'body' => $body, 42 'blocks' => $blocks, 43 'macros' => $macros, 44 'traits' => $traits, 45 'display_start' => new Node(), 46 'display_end' => new Node(), 47 'constructor_start' => new Node(), 48 'constructor_end' => new Node(), 49 'class_end' => new Node(), 50 ]; 51 if (null !== $parent) { 52 $nodes['parent'] = $parent; 53 } 54 55 // embedded templates are set as attributes so that they are only visited once by the visitors 56 parent::__construct($nodes, [ 57 // source to be remove in 2.0 58 'source' => $source->getCode(), 59 // filename to be remove in 2.0 (use getTemplateName() instead) 60 'filename' => $source->getName(), 61 'index' => null, 62 'embedded_templates' => $embeddedTemplates, 63 ], 1); 64 65 // populate the template name of all node children 66 $this->setTemplateName($source->getName()); 67 $this->setSourceContext($source); 68 } 69 70 public function setIndex($index) 71 { 72 $this->setAttribute('index', $index); 73 } 74 75 public function compile(Compiler $compiler) 76 { 77 $this->compileTemplate($compiler); 78 79 foreach ($this->getAttribute('embedded_templates') as $template) { 80 $compiler->subcompile($template); 81 } 82 } 83 84 protected function compileTemplate(Compiler $compiler) 85 { 86 if (!$this->getAttribute('index')) { 87 $compiler->write('<?php'); 88 } 89 90 $this->compileClassHeader($compiler); 91 92 if ( 93 \count($this->getNode('blocks')) 94 || \count($this->getNode('traits')) 95 || !$this->hasNode('parent') 96 || $this->getNode('parent') instanceof ConstantExpression 97 || \count($this->getNode('constructor_start')) 98 || \count($this->getNode('constructor_end')) 99 ) { 100 $this->compileConstructor($compiler); 101 } 102 103 $this->compileGetParent($compiler); 104 105 $this->compileDisplay($compiler); 106 107 $compiler->subcompile($this->getNode('blocks')); 108 109 $this->compileMacros($compiler); 110 111 $this->compileGetTemplateName($compiler); 112 113 $this->compileIsTraitable($compiler); 114 115 $this->compileDebugInfo($compiler); 116 117 $this->compileGetSource($compiler); 118 119 $this->compileGetSourceContext($compiler); 120 121 $this->compileClassFooter($compiler); 122 } 123 124 protected function compileGetParent(Compiler $compiler) 125 { 126 if (!$this->hasNode('parent')) { 127 return; 128 } 129 $parent = $this->getNode('parent'); 130 131 $compiler 132 ->write("protected function doGetParent(array \$context)\n", "{\n") 133 ->indent() 134 ->addDebugInfo($parent) 135 ->write('return ') 136 ; 137 138 if ($parent instanceof ConstantExpression) { 139 $compiler->subcompile($parent); 140 } else { 141 $compiler 142 ->raw('$this->loadTemplate(') 143 ->subcompile($parent) 144 ->raw(', ') 145 ->repr($this->getSourceContext()->getName()) 146 ->raw(', ') 147 ->repr($parent->getTemplateLine()) 148 ->raw(')') 149 ; 150 } 151 152 $compiler 153 ->raw(";\n") 154 ->outdent() 155 ->write("}\n\n") 156 ; 157 } 158 159 protected function compileClassHeader(Compiler $compiler) 160 { 161 $compiler 162 ->write("\n\n") 163 ; 164 if (!$this->getAttribute('index')) { 165 $compiler 166 ->write("use Twig\Environment;\n") 167 ->write("use Twig\Error\LoaderError;\n") 168 ->write("use Twig\Error\RuntimeError;\n") 169 ->write("use Twig\Markup;\n") 170 ->write("use Twig\Sandbox\SecurityError;\n") 171 ->write("use Twig\Sandbox\SecurityNotAllowedTagError;\n") 172 ->write("use Twig\Sandbox\SecurityNotAllowedFilterError;\n") 173 ->write("use Twig\Sandbox\SecurityNotAllowedFunctionError;\n") 174 ->write("use Twig\Source;\n") 175 ->write("use Twig\Template;\n\n") 176 ; 177 } 178 $compiler 179 // if the template name contains */, add a blank to avoid a PHP parse error 180 ->write('/* '.str_replace('*/', '* /', $this->getSourceContext()->getName())." */\n") 181 ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getSourceContext()->getName(), $this->getAttribute('index'))) 182 ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass())) 183 ->write("{\n") 184 ->indent() 185 ; 186 } 187 188 protected function compileConstructor(Compiler $compiler) 189 { 190 $compiler 191 ->write("public function __construct(Environment \$env)\n", "{\n") 192 ->indent() 193 ->subcompile($this->getNode('constructor_start')) 194 ->write("parent::__construct(\$env);\n\n") 195 ; 196 197 // parent 198 if (!$this->hasNode('parent')) { 199 $compiler->write("\$this->parent = false;\n\n"); 200 } 201 202 $countTraits = \count($this->getNode('traits')); 203 if ($countTraits) { 204 // traits 205 foreach ($this->getNode('traits') as $i => $trait) { 206 $this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i)); 207 208 $node = $trait->getNode('template'); 209 $compiler 210 ->addDebugInfo($node) 211 ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i)) 212 ->indent() 213 ->write("throw new RuntimeError('Template \"'.") 214 ->subcompile($trait->getNode('template')) 215 ->raw(".'\" cannot be used as a trait.', ") 216 ->repr($node->getTemplateLine()) 217 ->raw(", \$this->getSourceContext());\n") 218 ->outdent() 219 ->write("}\n") 220 ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i)) 221 ; 222 223 foreach ($trait->getNode('targets') as $key => $value) { 224 $compiler 225 ->write(sprintf('if (!isset($_trait_%s_blocks[', $i)) 226 ->string($key) 227 ->raw("])) {\n") 228 ->indent() 229 ->write("throw new RuntimeError(sprintf('Block ") 230 ->string($key) 231 ->raw(' is not defined in trait ') 232 ->subcompile($trait->getNode('template')) 233 ->raw(".'), ") 234 ->repr($node->getTemplateLine()) 235 ->raw(", \$this->getSourceContext());\n") 236 ->outdent() 237 ->write("}\n\n") 238 239 ->write(sprintf('$_trait_%s_blocks[', $i)) 240 ->subcompile($value) 241 ->raw(sprintf('] = $_trait_%s_blocks[', $i)) 242 ->string($key) 243 ->raw(sprintf(']; unset($_trait_%s_blocks[', $i)) 244 ->string($key) 245 ->raw("]);\n\n") 246 ; 247 } 248 } 249 250 if ($countTraits > 1) { 251 $compiler 252 ->write("\$this->traits = array_merge(\n") 253 ->indent() 254 ; 255 256 for ($i = 0; $i < $countTraits; ++$i) { 257 $compiler 258 ->write(sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i)) 259 ; 260 } 261 262 $compiler 263 ->outdent() 264 ->write(");\n\n") 265 ; 266 } else { 267 $compiler 268 ->write("\$this->traits = \$_trait_0_blocks;\n\n") 269 ; 270 } 271 272 $compiler 273 ->write("\$this->blocks = array_merge(\n") 274 ->indent() 275 ->write("\$this->traits,\n") 276 ->write("[\n") 277 ; 278 } else { 279 $compiler 280 ->write("\$this->blocks = [\n") 281 ; 282 } 283 284 // blocks 285 $compiler 286 ->indent() 287 ; 288 289 foreach ($this->getNode('blocks') as $name => $node) { 290 $compiler 291 ->write(sprintf("'%s' => [\$this, 'block_%s'],\n", $name, $name)) 292 ; 293 } 294 295 if ($countTraits) { 296 $compiler 297 ->outdent() 298 ->write("]\n") 299 ->outdent() 300 ->write(");\n") 301 ; 302 } else { 303 $compiler 304 ->outdent() 305 ->write("];\n") 306 ; 307 } 308 309 $compiler 310 ->subcompile($this->getNode('constructor_end')) 311 ->outdent() 312 ->write("}\n\n") 313 ; 314 } 315 316 protected function compileDisplay(Compiler $compiler) 317 { 318 $compiler 319 ->write("protected function doDisplay(array \$context, array \$blocks = [])\n", "{\n") 320 ->indent() 321 ->subcompile($this->getNode('display_start')) 322 ->subcompile($this->getNode('body')) 323 ; 324 325 if ($this->hasNode('parent')) { 326 $parent = $this->getNode('parent'); 327 328 $compiler->addDebugInfo($parent); 329 if ($parent instanceof ConstantExpression) { 330 $compiler 331 ->write('$this->parent = $this->loadTemplate(') 332 ->subcompile($parent) 333 ->raw(', ') 334 ->repr($this->getSourceContext()->getName()) 335 ->raw(', ') 336 ->repr($parent->getTemplateLine()) 337 ->raw(");\n") 338 ; 339 $compiler->write('$this->parent'); 340 } else { 341 $compiler->write('$this->getParent($context)'); 342 } 343 $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n"); 344 } 345 346 $compiler 347 ->subcompile($this->getNode('display_end')) 348 ->outdent() 349 ->write("}\n\n") 350 ; 351 } 352 353 protected function compileClassFooter(Compiler $compiler) 354 { 355 $compiler 356 ->subcompile($this->getNode('class_end')) 357 ->outdent() 358 ->write("}\n") 359 ; 360 } 361 362 protected function compileMacros(Compiler $compiler) 363 { 364 $compiler->subcompile($this->getNode('macros')); 365 } 366 367 protected function compileGetTemplateName(Compiler $compiler) 368 { 369 $compiler 370 ->write("public function getTemplateName()\n", "{\n") 371 ->indent() 372 ->write('return ') 373 ->repr($this->getSourceContext()->getName()) 374 ->raw(";\n") 375 ->outdent() 376 ->write("}\n\n") 377 ; 378 } 379 380 protected function compileIsTraitable(Compiler $compiler) 381 { 382 // A template can be used as a trait if: 383 // * it has no parent 384 // * it has no macros 385 // * it has no body 386 // 387 // Put another way, a template can be used as a trait if it 388 // only contains blocks and use statements. 389 $traitable = !$this->hasNode('parent') && 0 === \count($this->getNode('macros')); 390 if ($traitable) { 391 if ($this->getNode('body') instanceof BodyNode) { 392 $nodes = $this->getNode('body')->getNode(0); 393 } else { 394 $nodes = $this->getNode('body'); 395 } 396 397 if (!\count($nodes)) { 398 $nodes = new Node([$nodes]); 399 } 400 401 foreach ($nodes as $node) { 402 if (!\count($node)) { 403 continue; 404 } 405 406 if ($node instanceof TextNode && ctype_space($node->getAttribute('data'))) { 407 continue; 408 } 409 410 if ($node instanceof BlockReferenceNode) { 411 continue; 412 } 413 414 $traitable = false; 415 break; 416 } 417 } 418 419 if ($traitable) { 420 return; 421 } 422 423 $compiler 424 ->write("public function isTraitable()\n", "{\n") 425 ->indent() 426 ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false')) 427 ->outdent() 428 ->write("}\n\n") 429 ; 430 } 431 432 protected function compileDebugInfo(Compiler $compiler) 433 { 434 $compiler 435 ->write("public function getDebugInfo()\n", "{\n") 436 ->indent() 437 ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true)))) 438 ->outdent() 439 ->write("}\n\n") 440 ; 441 } 442 443 protected function compileGetSource(Compiler $compiler) 444 { 445 $compiler 446 ->write("/** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */\n") 447 ->write("public function getSource()\n", "{\n") 448 ->indent() 449 ->write("@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED);\n\n") 450 ->write('return $this->getSourceContext()->getCode();') 451 ->raw("\n") 452 ->outdent() 453 ->write("}\n\n") 454 ; 455 } 456 457 protected function compileGetSourceContext(Compiler $compiler) 458 { 459 $compiler 460 ->write("public function getSourceContext()\n", "{\n") 461 ->indent() 462 ->write('return new Source(') 463 ->string($compiler->getEnvironment()->isDebug() ? $this->getSourceContext()->getCode() : '') 464 ->raw(', ') 465 ->string($this->getSourceContext()->getName()) 466 ->raw(', ') 467 ->string($this->getSourceContext()->getPath()) 468 ->raw(");\n") 469 ->outdent() 470 ->write("}\n") 471 ; 472 } 473 474 protected function compileLoadTemplate(Compiler $compiler, $node, $var) 475 { 476 if ($node instanceof ConstantExpression) { 477 $compiler 478 ->write(sprintf('%s = $this->loadTemplate(', $var)) 479 ->subcompile($node) 480 ->raw(', ') 481 ->repr($node->getTemplateName()) 482 ->raw(', ') 483 ->repr($node->getTemplateLine()) 484 ->raw(");\n") 485 ; 486 } else { 487 throw new \LogicException('Trait templates can only be constant nodes.'); 488 } 489 } 490 } 491 492 class_alias('Twig\Node\ModuleNode', 'Twig_Node_Module');
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 11 20:33:01 2020 | Cross-referenced by PHPXref 0.7.1 |