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

nette / latte / 22359082277

24 Feb 2026 04:03PM UTC coverage: 93.959% (+0.05%) from 93.907%
22359082277

push

github

dg
fixed operator ! priority

5273 of 5612 relevant lines covered (93.96%)

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 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\CompileException;
11
use Latte\Compiler\Nodes\AreaNode;
12
use Latte\Compiler\Nodes\Php\Expression;
13
use Latte\Compiler\Nodes\Php\ExpressionNode;
14
use Latte\Compiler\Nodes\Php\Scalar\StringNode;
15
use Latte\Compiler\Nodes\StatementNode;
16
use Latte\Compiler\Position;
17
use Latte\Compiler\PrintContext;
18
use Latte\Compiler\Tag;
19
use Latte\Compiler\TagParser;
20
use Latte\Compiler\TemplateParser;
21
use function in_array;
22

23

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

39

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

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

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

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

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

75
                return $node;
1✔
76
        }
77

78

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

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

96

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

104

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

127

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

147

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

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

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

174

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