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

nette / application / 27919019709

21 Jun 2026 10:08PM UTC coverage: 84.111% (+0.05%) from 84.059%
27919019709

push

github

dg
phpstan fix

2038 of 2423 relevant lines covered (84.11%)

0.84 hits per line

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

98.21
/src/Bridges/ApplicationLatte/Nodes/ControlNode.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 Nette\Bridges\ApplicationLatte\Nodes;
9

10
use Latte;
11
use Latte\Compiler\Escaper;
12
use Latte\Compiler\Nodes\Php\ArrayItemNode;
13
use Latte\Compiler\Nodes\Php\Expression\ArrayNode;
14
use Latte\Compiler\Nodes\Php\ExpressionNode;
15
use Latte\Compiler\Nodes\Php\ModifierNode;
16
use Latte\Compiler\Nodes\Php\Scalar\StringNode;
17
use Latte\Compiler\Nodes\StatementNode;
18
use Latte\Compiler\PrintContext;
19
use Latte\Compiler\Tag;
20
use Nette\Utils\Strings;
21

22

23
/**
24
 * {control name[:method] [,] [params]}
25
 * Renders a component by calling its render() method.
26
 */
27
class ControlNode extends StatementNode
28
{
29
        public ExpressionNode $name;
30
        public ?ExpressionNode $method = null;
31
        public ArrayNode $args;
32
        public ?bool $escape = null;
33

34

35
        public static function create(Tag $tag): static
1✔
36
        {
37
                $tag->outputMode = $tag::OutputRemoveIndentation;
1✔
38
                $tag->expectArguments();
1✔
39
                $stream = $tag->parser->stream;
1✔
40
                $node = new static;
1✔
41
                $node->name = $tag->parser->parseUnquotedStringOrExpression(colon: false);
1✔
42
                if ($stream->tryConsume(':')) {
1✔
43
                        $node->method = $tag->parser->parseExpression();
1✔
44
                }
45

46
                $stream->tryConsume(',');
1✔
47
                $start = $stream->getIndex();
1✔
48
                $node->args = $tag->parser->parseArguments();
1✔
49
                $start -= $stream->getIndex();
1✔
50
                $depth = $wrap = null;
1✔
51
                for (; $start < 0; $start++) {
1✔
52
                        $token = $stream->peek($start);
1✔
53
                        match (true) {
54
                                $token->is('[') => $depth++,
1✔
55
                                $token->is(']') => $depth--,
1✔
56
                                $token->is('=>') && !$depth => $wrap = true,
1✔
57
                                default => null,
1✔
58
                        };
59
                }
60

61
                if ($wrap) {
1✔
62
                        $node->args = new ArrayNode([new ArrayItemNode($node->args)]);
1✔
63
                }
64

65
                $modifier = $tag->parser->parseModifier();
1✔
66
                foreach ($modifier->filters as $filter) {
1✔
67
                        match ($filter->name->name) {
1✔
68
                                'noescape' => $node->escape = false,
1✔
69
                                default => throw new Latte\CompileException('Only modifier |noescape is allowed here.', $tag->position),
×
70
                        };
71
                }
72

73
                return $node;
1✔
74
        }
75

76

77
        public function print(PrintContext $context): string
1✔
78
        {
79
                if ($this->escape === null && $context->getEscaper()->getState() !== Escaper::HtmlText) {
1✔
80
                        $this->escape = true;
1✔
81
                }
82

83
                $method = match (true) {
1✔
84
                        !$this->method => 'render',
1✔
85
                        $this->method instanceof StringNode && Strings::match($this->method->value, '#^\w*$#D') => 'render' . ucfirst($this->method->value),
1✔
86
                        default => "{'render' . " . $this->method->print($context) . '}',
1✔
87
                };
88

89
                $fetchCode = $context->format(
1✔
90
                        $this->name instanceof StringNode
1✔
91
                                ? '$ʟ_tmp = $this->global->uiControl->getComponent(%node);'
1✔
92
                                : 'if (!is_object($ʟ_tmp = %node)) $ʟ_tmp = $this->global->uiControl->getComponent($ʟ_tmp);',
1✔
93
                        $this->name,
1✔
94
                );
95

96
                if ($this->escape) {
1✔
97
                        return $context->format(
1✔
98
                                <<<'XX'
99
                                        %raw
1✔
100
                                        if ($ʟ_tmp instanceof Nette\Application\UI\Renderable) $ʟ_tmp->redrawControl(null, false);
101
                                        ob_start(fn() => '');
102
                                        $ʟ_tmp->%raw(%args) %line;
103
                                        $ʟ_fi = new LR\FilterInfo(%dump); echo %modifyContent(ob_get_clean());
104

105

106
                                        XX,
107
                                $fetchCode,
108
                                $method,
109
                                $this->args,
1✔
110
                                $this->position,
1✔
111
                                Latte\ContentType::Html,
1✔
112
                                new ModifierNode([], $this->escape),
1✔
113
                        );
114

115
                } else {
116
                        return $context->format(
1✔
117
                                <<<'XX'
118
                                        %raw
1✔
119
                                        if ($ʟ_tmp instanceof Nette\Application\UI\Renderable) $ʟ_tmp->redrawControl(null, false);
120
                                        $ʟ_tmp->%raw(%args) %line;
121

122

123
                                        XX,
124
                                $fetchCode,
125
                                $method,
126
                                $this->args,
1✔
127
                                $this->position,
1✔
128
                        );
129
                }
130
        }
131

132

133
        public function &getIterator(): \Generator
1✔
134
        {
135
                yield $this->name;
1✔
136
                if ($this->method) {
1✔
137
                        yield $this->method;
1✔
138
                }
139
                yield $this->args;
1✔
140
        }
1✔
141
}
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