• 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.67
/src/Latte/Essential/Nodes/IfNode.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\Nodes\AreaNode;
14
use Latte\Compiler\Nodes\Php\Expression;
15
use Latte\Compiler\Nodes\Php\ExpressionNode;
16
use Latte\Compiler\Nodes\Php\Scalar\StringNode;
17
use Latte\Compiler\Nodes\StatementNode;
18
use Latte\Compiler\Position;
19
use Latte\Compiler\PrintContext;
20
use Latte\Compiler\Tag;
21
use Latte\Compiler\TagParser;
22
use Latte\Compiler\TemplateParser;
23
use function in_array;
24

25

26
/**
27
 * {if $cond} & {elseif $cond} & {else}
28
 * {if} & {/if $cond}
29
 * {ifset $var} & {elseifset $var}
30
 * {ifset block} & {elseifset block}
31
 */
32
class IfNode extends StatementNode
33
{
34
        public ExpressionNode $condition;
35
        public AreaNode $then;
36
        public ?AreaNode $else = null;
37
        public ?Position $elseLine = null;
38
        public bool $capture = false;
39
        public bool $ifset = false;
40

41

42
        /** @return \Generator<int, ?array, array{AreaNode, ?Tag}, static> */
43
        public static function create(Tag $tag, TemplateParser $parser): \Generator
1✔
44
        {
45
                $node = $tag->node = new static;
1✔
46
                $node->ifset = in_array($tag->name, ['ifset', 'elseifset'], true);
1✔
47
                $node->capture = !$tag->isNAttribute() && $tag->name === 'if' && $tag->parser->isEnd();
1✔
48
                $node->position = $tag->position;
1✔
49
                if (!$node->capture) {
1✔
50
                        $node->condition = $node->ifset
1✔
51
                                ? self::buildCondition($tag->parser)
1✔
52
                                : $tag->parser->parseExpression();
1✔
53
                }
54

55
                [$node->then, $nextTag] = yield $node->capture
1✔
56
                        ? ['else']
1✔
57
                        : ['else', 'elseif', 'elseifset'];
1✔
58

59
                if ($nextTag?->name === 'else') {
1✔
60
                        if ($nextTag->parser->stream->is('if')) {
1✔
61
                                throw new CompileException('Arguments are not allowed in {else}, did you mean {elseif}?', $nextTag->position);
1✔
62
                        }
63
                        $node->elseLine = $nextTag->position;
1✔
64
                        [$node->else, $nextTag] = yield;
1✔
65

66
                } elseif ($nextTag?->name === 'elseif' || $nextTag?->name === 'elseifset') {
1✔
67
                        if ($node->capture) {
1✔
UNCOV
68
                                throw new CompileException('Tag ' . $nextTag->getNotation() . ' is unexpected here.', $nextTag->position);
×
69
                        }
70
                        $node->else = yield from self::create($nextTag, $parser);
1✔
71
                }
72

73
                if ($node->capture) {
1✔
74
                        $node->condition = $nextTag->parser->parseExpression();
1✔
75
                }
76

77
                return $node;
1✔
78
        }
79

80

81
        private static function buildCondition(TagParser $parser): ExpressionNode
1✔
82
        {
83
                $list = [];
1✔
84
                do {
85
                        $block = $parser->tryConsumeTokenBeforeUnquotedString('block') ?? $parser->stream->tryConsume('#');
1✔
86
                        $name = $parser->parseUnquotedStringOrExpression();
1✔
87
                        $list[] = $block || $name instanceof StringNode
1✔
88
                                ? new Expression\AuxiliaryNode(
1✔
89
                                        fn(PrintContext $context, ExpressionNode $name) => '$this->hasBlock(' . $name->print($context) . ')',
1✔
90
                                        [$name],
1✔
91
                                )
92
                                : new Expression\IssetNode([$name]);
1✔
93
                } while ($parser->stream->tryConsume(','));
1✔
94

95
                return Expression\BinaryOpNode::nest('&&', ...$list);
1✔
96
        }
97

98

99
        public function print(PrintContext $context): string
1✔
100
        {
101
                return $this->capture
1✔
102
                        ? $this->printCapturing($context)
1✔
103
                        : $this->printCommon($context);
1✔
104
        }
105

106

107
        private function printCommon(PrintContext $context): string
1✔
108
        {
109
                if ($this->else) {
1✔
110
                        return $context->format(
1✔
111
                                ($this->else instanceof self
1✔
112
                                        ? "if (%node) %line { %node } else%node\n"
1✔
113
                                        : "if (%node) %line { %node } else %4.line { %3.node }\n"),
1✔
114
                                $this->condition,
1✔
115
                                $this->position,
1✔
116
                                $this->then,
1✔
117
                                $this->else,
1✔
118
                                $this->elseLine,
1✔
119
                        );
120
                }
121
                return $context->format(
1✔
122
                        "if (%node) %line { %node }\n",
1✔
123
                        $this->condition,
1✔
124
                        $this->position,
1✔
125
                        $this->then,
1✔
126
                );
127
        }
128

129

130
        private function printCapturing(PrintContext $context): string
1✔
131
        {
132
                if ($this->else) {
1✔
133
                        return $context->format(
1✔
134
                                <<<'XX'
135
                                        ob_start(fn() => '') %line;
1✔
136
                                        try {
137
                                                %node
138
                                                ob_start(fn() => '') %line;
139
                                                try {
140
                                                        %node
141
                                                } finally {
142
                                                        $ʟ_ifB = ob_get_clean();
143
                                                }
144
                                        } finally {
145
                                                $ʟ_ifA = ob_get_clean();
146
                                        }
147
                                        echo (%node) ? $ʟ_ifA : $ʟ_ifB %0.line;
148

149

150
                                        XX,
151
                                $this->position,
1✔
152
                                $this->then,
1✔
153
                                $this->elseLine,
1✔
154
                                $this->else,
1✔
155
                                $this->condition,
1✔
156
                        );
157
                }
158

159
                return $context->format(
1✔
160
                        <<<'XX'
161
                                ob_start(fn() => '') %line;
1✔
162
                                try {
163
                                        %node
164
                                } finally {
165
                                        $ʟ_ifA = ob_get_clean();
166
                                }
167
                                if (%node) %0.line { echo $ʟ_ifA; }
168

169
                                XX,
170
                        $this->position,
1✔
171
                        $this->then,
1✔
172
                        $this->condition,
1✔
173
                );
174
        }
175

176

177
        public function &getIterator(): \Generator
1✔
178
        {
179
                yield $this->condition;
1✔
180
                yield $this->then;
1✔
181
                if ($this->else) {
1✔
182
                        yield $this->else;
1✔
183
                }
184
        }
1✔
185
}
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