blob: 64b4f296f27c65631a62dc696d98c7de13bd9036 [file] [log] [blame]
Matthias Andreas Benkard12a57352021-12-28 18:02:04 +01001<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Twig\TokenParser;
13
14use Twig\Node\EmbedNode;
15use Twig\Node\Expression\ConstantExpression;
16use Twig\Node\Expression\NameExpression;
17use Twig\Node\Node;
18use Twig\Token;
19
20/**
21 * Embeds a template.
22 *
23 * @internal
24 */
25final class EmbedTokenParser extends IncludeTokenParser
26{
27 public function parse(Token $token): Node
28 {
29 $stream = $this->parser->getStream();
30
31 $parent = $this->parser->getExpressionParser()->parseExpression();
32
33 list($variables, $only, $ignoreMissing) = $this->parseArguments();
34
35 $parentToken = $fakeParentToken = new Token(/* Token::STRING_TYPE */ 7, '__parent__', $token->getLine());
36 if ($parent instanceof ConstantExpression) {
37 $parentToken = new Token(/* Token::STRING_TYPE */ 7, $parent->getAttribute('value'), $token->getLine());
38 } elseif ($parent instanceof NameExpression) {
39 $parentToken = new Token(/* Token::NAME_TYPE */ 5, $parent->getAttribute('name'), $token->getLine());
40 }
41
42 // inject a fake parent to make the parent() function work
43 $stream->injectTokens([
44 new Token(/* Token::BLOCK_START_TYPE */ 1, '', $token->getLine()),
45 new Token(/* Token::NAME_TYPE */ 5, 'extends', $token->getLine()),
46 $parentToken,
47 new Token(/* Token::BLOCK_END_TYPE */ 3, '', $token->getLine()),
48 ]);
49
50 $module = $this->parser->parse($stream, [$this, 'decideBlockEnd'], true);
51
52 // override the parent with the correct one
53 if ($fakeParentToken === $parentToken) {
54 $module->setNode('parent', $parent);
55 }
56
57 $this->parser->embedTemplate($module);
58
59 $stream->expect(/* Token::BLOCK_END_TYPE */ 3);
60
61 return new EmbedNode($module->getTemplateName(), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
62 }
63
64 public function decideBlockEnd(Token $token): bool
65 {
66 return $token->test('endembed');
67 }
68
69 public function getTag(): string
70 {
71 return 'embed';
72 }
73}