• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nette / latte / 15809643126

22 Jun 2025 06:35PM UTC coverage: 93.67% (+0.09%) from 93.583%
15809643126

push

github

dg
added {include?} {import?} {embed?} {sandbox?}

34 of 36 new or added lines in 7 files covered. (94.44%)

164 existing lines in 43 files now uncovered.

5164 of 5513 relevant lines covered (93.67%)

0.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.55
/src/Latte/Essential/Nodes/IncludeBlockNode.php
1
<?php
2

3
/**
4
 * This file is part of the Latte (https://latte.nette.org)
5
 * Copyright (c) 2008 David Grudl (https://davidgrudl.com)
6
 */
7

8
declare(strict_types=1);
9

10
namespace Latte\Essential\Nodes;
11

12
use Latte\CompileException;
13
use Latte\Compiler\Block;
14
use Latte\Compiler\Nodes\Php\Expression\ArrayNode;
15
use Latte\Compiler\Nodes\Php\ExpressionNode;
16
use Latte\Compiler\Nodes\Php\ModifierNode;
17
use Latte\Compiler\Nodes\Php\Scalar;
18
use Latte\Compiler\Nodes\StatementNode;
19
use Latte\Compiler\PhpHelpers;
20
use Latte\Compiler\PrintContext;
21
use Latte\Compiler\Tag;
22
use Latte\Compiler\TemplateParser;
23
use Latte\Runtime\Template;
24
use function count;
25

26

27
/**
28
 * {include [block] name [from file] [, args]}
29
 */
30
class IncludeBlockNode extends StatementNode
31
{
32
        public ExpressionNode $name;
33
        public ?ExpressionNode $from = null;
34
        public ArrayNode $args;
35
        public ModifierNode $modifier;
36
        public int|string|null $layer;
37
        public bool $parent = false;
38
        public bool $optional = false;
39

40
        /** @var Block[][] */
41
        public array $blocks;
42

43

44
        public static function create(Tag $tag, TemplateParser $parser): static
1✔
45
        {
46
                $tag->outputMode = $tag::OutputRemoveIndentation;
1✔
47

48
                $tag->expectArguments();
1✔
49
                $node = new static;
1✔
50
                $node->optional = str_ends_with($tag->name, '?');
1✔
51
                $tag->parser->tryConsumeTokenBeforeUnquotedString('block') ?? $tag->parser->stream->tryConsume('#');
1✔
52
                $node->name = $tag->parser->parseUnquotedStringOrExpression();
1✔
53
                $tokenName = $tag->parser->stream->peek(-1);
1✔
54

55
                $stream = $tag->parser->stream;
1✔
56
                if ($stream->tryConsume('from')) {
1✔
57
                        $node->from = $tag->parser->parseUnquotedStringOrExpression();
1✔
58
                        $tag->parser->stream->tryConsume(',');
1✔
59
                }
60

61
                $stream->tryConsume(',');
1✔
62
                $node->args = $tag->parser->parseArguments();
1✔
63
                $node->modifier = $tag->parser->parseModifier();
1✔
64
                $node->modifier->escape = (bool) $node->modifier->filters;
1✔
65

66
                $node->parent = $tokenName->is('parent');
1✔
67
                if ($node->parent && $node->modifier->filters) {
1✔
68
                        throw new CompileException('Filters are not allowed in {include parent}', $tag->position);
1✔
69

70
                } elseif ($node->parent || $tokenName->is('this')) {
1✔
71
                        $item = $tag->closestTag(
1✔
72
                                [BlockNode::class, DefineNode::class],
1✔
73
                                fn($item) => $item->node?->block && !$item->node->block->isDynamic() && $item->node->block->name !== '',
1✔
74
                        );
75
                        if (!$item) {
1✔
76
                                throw new CompileException("Cannot include $tokenName->text block outside of any block.", $tag->position);
1✔
77
                        }
78

79
                        $node->name = $item->node->block->name;
1✔
80
                }
81

82
                $node->blocks = &$parser->blocks;
1✔
83
                $node->layer = $parser->blockLayer;
1✔
84
                return $node;
1✔
85
        }
86

87

88
        public function print(PrintContext $context): string
1✔
89
        {
90
                $noEscape = $this->modifier->hasFilter('noescape');
1✔
91
                $contentFilter = count($this->modifier->filters) > (int) $noEscape
1✔
92
                        ? $context->format(
1✔
93
                                'function ($s, $type) { $ʟ_fi = new LR\FilterInfo($type); return %modifyContent($s); }',
1✔
94
                                $this->modifier,
1✔
95
                        )
96
                        : ($noEscape || $this->parent ? '' : PhpHelpers::dump($context->getEscaper()->export()));
1✔
97

98
                return $this->from
1✔
99
                        ? $this->printBlockFrom($context, $contentFilter)
1✔
100
                        : $this->printBlock($context, $contentFilter);
1✔
101
        }
102

103

104
        private function printBlock(PrintContext $context, string $contentFilter): string
1✔
105
        {
106
                if ($this->name instanceof Scalar\StringNode || $this->name instanceof Scalar\IntegerNode) {
1✔
107
                        $staticName = (string) $this->name->value;
1✔
108
                        $block = $this->blocks[$this->layer][$staticName] ?? $this->blocks[Template::LayerLocal][$staticName] ?? null;
1✔
109
                }
110

111
                return $context->format(
1✔
112
                        ($this->optional
1✔
NEW
113
                                ? 'if ($this->hasBlock($ʟ_nm = %node)) $this->renderBlock($ʟ_nm, '
×
114
                                : '$this->render' . ($this->parent ? 'ParentBlock' : 'Block') . '(%node, ')
1✔
115
                        . '%node? + '
1✔
116
                        . (isset($block) && !$block->parameters ? 'get_defined_vars()' : '[]')
1✔
117
                        . '%raw) %line;',
1✔
118
                        $this->name,
1✔
119
                        $this->args,
1✔
120
                        $contentFilter ? ", $contentFilter" : '',
1✔
121
                        $this->position,
1✔
122
                );
123
        }
124

125

126
        private function printBlockFrom(PrintContext $context, string $contentFilter): string
1✔
127
        {
128
                return $context->format(
1✔
129
                        '$this->createTemplate(%node, %node? + $this->params, "include", %dump)?->renderToContentType(%raw, %node) %line;',
1✔
130
                        $this->from,
1✔
131
                        $this->args,
1✔
132
                        $this->optional,
1✔
133
                        $contentFilter,
134
                        $this->name,
1✔
135
                        $this->position,
1✔
136
                );
137
        }
138

139

140
        public function &getIterator(): \Generator
1✔
141
        {
142
                yield $this->name;
1✔
143
                if ($this->from) {
1✔
144
                        yield $this->from;
1✔
145
                }
146
                yield $this->args;
1✔
147
                yield $this->modifier;
1✔
148
        }
1✔
149
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc