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

nette / latte / 22368407632

24 Feb 2026 08:17PM UTC coverage: 94.825% (-0.2%) from 95.054%
22368407632

push

github

dg
phpstan

135 of 147 new or added lines in 38 files covered. (91.84%)

186 existing lines in 70 files now uncovered.

5534 of 5836 relevant lines covered (94.83%)

0.95 hits per line

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

96.61
/src/Latte/Essential/Nodes/DefineNode.php
1
<?php declare(strict_types=1);
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
namespace Latte\Essential\Nodes;
9

10
use Latte\Compiler\Block;
11
use Latte\Compiler\Nodes\AreaNode;
12
use Latte\Compiler\Nodes\Php\Expression\AssignNode;
13
use Latte\Compiler\Nodes\Php\Expression\VariableNode;
14
use Latte\Compiler\Nodes\Php\ParameterNode;
15
use Latte\Compiler\Nodes\Php\Scalar;
16
use Latte\Compiler\Nodes\StatementNode;
17
use Latte\Compiler\PrintContext;
18
use Latte\Compiler\Tag;
19
use Latte\Compiler\TemplateParser;
20
use Latte\Compiler\Token;
21
use Latte\Helpers;
22
use Latte\Runtime\Template;
23
use function is_string;
24

25

26
/**
27
 * {define name($params)} ... {/define}
28
 * Defines reusable block with parameters.
29
 */
30
class DefineNode extends StatementNode
31
{
32
        public Block $block;
33
        public AreaNode $content;
34

35

36
        /** @return \Generator<int, ?list<string>, array{AreaNode, ?Tag}, static> */
37
        public static function create(Tag $tag, TemplateParser $parser): \Generator
1✔
38
        {
39
                $tag->expectArguments();
1✔
40
                $layer = $tag->parser->tryConsumeTokenBeforeUnquotedString('local')
1✔
41
                        ? Template::LayerLocal
1✔
42
                        : $parser->blockLayer;
1✔
43
                $tag->parser->stream->tryConsume('#');
1✔
44
                $name = $tag->parser->parseUnquotedStringOrExpression();
1✔
45

46
                $node = $tag->node = new static;
1✔
47
                $node->block = new Block($name, $layer, $tag);
1✔
48
                if (!$node->block->isDynamic()) {
1✔
49
                        $parser->checkBlockIsUnique($node->block);
1✔
50
                        $tag->parser->stream->tryConsume(',');
1✔
51
                        $node->block->parameters = self::parseParameters($tag);
1✔
52
                }
53

54
                [$node->content, $endTag] = yield;
1✔
55
                if ($endTag && $name instanceof Scalar\StringNode) {
1✔
56
                        $endTag->parser->stream->tryConsume($name->value);
1✔
57
                }
58

59
                return $node;
1✔
60
        }
61

62

63
        /** @return ParameterNode[] */
64
        private static function parseParameters(Tag $tag): array
1✔
65
        {
66
                $stream = $tag->parser->stream;
1✔
67
                $params = [];
1✔
68
                while (!$stream->is(Token::End)) {
1✔
69
                        $type = $tag->parser->parseType();
1✔
70

71
                        $save = $stream->getIndex();
1✔
72
                        $expr = $stream->is(Token::Php_Variable) ? $tag->parser->parseExpression() : null;
1✔
73
                        if ($expr instanceof VariableNode && is_string($expr->name)) {
1✔
74
                                $params[] = new ParameterNode($expr, new Scalar\NullNode, $type);
1✔
75
                        } elseif (
76
                                $expr instanceof AssignNode
1✔
77
                                && $expr->var instanceof VariableNode
1✔
78
                                && is_string($expr->var->name)
1✔
79
                        ) {
80
                                $params[] = new ParameterNode($expr->var, $expr->expr, $type);
1✔
81
                        } else {
UNCOV
82
                                $stream->seek($save);
×
UNCOV
83
                                $stream->throwUnexpectedException(addendum: ' in ' . $tag->getNotation());
×
84
                        }
85

86
                        if (!$stream->tryConsume(',')) {
1✔
87
                                break;
1✔
88
                        }
89
                }
90

91
                return $params;
1✔
92
        }
93

94

95
        public function print(PrintContext $context): string
1✔
96
        {
97
                return $this->block->isDynamic()
1✔
98
                        ? $this->printDynamic($context)
1✔
99
                        : $this->printStatic($context);
1✔
100
        }
101

102

103
        private function printStatic(PrintContext $context): string
1✔
104
        {
105
                $context->addBlock($this->block);
1✔
106
                $this->block->content = $this->content->print($context); // must be compiled after is added
1✔
107
                return '';
1✔
108
        }
109

110

111
        private function printDynamic(PrintContext $context): string
1✔
112
        {
113
                $context->addBlock($this->block);
1✔
114
                $this->block->content = $this->content->print($context); // must be compiled after is added
1✔
115

116
                return $context->format(
1✔
117
                        '$this->addBlock(%raw, %dump, [$this->%raw(...)], %dump);',
1✔
118
                        $context->ensureString($this->block->name, 'Block name'),
1✔
119
                        $context->getEscaper()->export(),
1✔
120
                        $this->block->method,
1✔
121
                        $this->block->layer,
1✔
122
                );
123
        }
124

125

126
        public function &getIterator(): \Generator
1✔
127
        {
128
                yield $this->block->name;
1✔
129
                foreach ($this->block->parameters as &$param) {
1✔
130
                        yield $param;
1✔
131
                }
132
                Helpers::removeNulls($this->block->parameters);
1✔
133

134
                yield $this->content;
1✔
135
        }
1✔
136
}
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