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

nette / latte / 15081934954

17 May 2025 05:07AM UTC coverage: 93.691% (+0.05%) from 93.641%
15081934954

push

github

web-flow
Support property hooks in template params (#395)

4 of 12 new or added lines in 1 file covered. (33.33%)

36 existing lines in 4 files now uncovered.

5138 of 5484 relevant lines covered (93.69%)

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

24

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

40

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

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

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

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

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

76
                return $node;
1✔
77
        }
78

79

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

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

97

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

105

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

128

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

148

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

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

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

175

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