• 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

90.74
/src/Application/UI/Control.php
1
<?php declare(strict_types=1);
1✔
2

3
/**
4
 * This file is part of the Nette Framework (https://nette.org)
5
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6
 */
7

8
namespace Nette\Application\UI;
9

10
use Nette;
11
use function array_shift, class_exists, count, is_a, preg_replace, sprintf, trigger_error;
12

13

14
/**
15
 * Control is renderable Presenter component.
16
 *
17
 * @property-read Nette\Bridges\ApplicationLatte\DefaultTemplate $template
18
 */
19
abstract class Control extends Component implements Renderable
20
{
21
        public bool $snippetMode = false;
22
        private TemplateFactory $templateFactory;
23
        private Template $template;
24

25
        /** @var array<string, bool> */
26
        private array $invalidSnippets = [];
27

28

29
        /********************* template factory ****************d*g**/
30

31

32
        final public function setTemplateFactory(TemplateFactory $templateFactory): static
33
        {
34
                $this->templateFactory = $templateFactory;
×
35
                return $this;
×
36
        }
37

38

39
        final public function getTemplate(): Template
40
        {
41
                if (!isset($this->template)) {
1✔
42
                        $this->template = $this->createTemplate();
1✔
43
                }
44

45
                return $this->template;
1✔
46
        }
47

48

49
        /**
50
         * @template T of Template
51
         * @param ?class-string<T>  $class
52
         * @return ($class is null ? Template : T)
53
         */
54
        protected function createTemplate(?string $class = null): Template
55
        {
56
                $class ??= $this->formatTemplateClass();
×
57
                $templateFactory = $this->templateFactory ?? $this->getPresenter()->getTemplateFactory();
×
58
                return $templateFactory->createTemplate($this, $class);
×
59
        }
60

61

62
        /** @return ?class-string<Template> */
63
        public function formatTemplateClass(): ?string
64
        {
65
                return $this->checkTemplateClass(preg_replace('#Control$#', '', static::class) . 'Template');
1✔
66
        }
67

68

69
        /**
70
         * @internal
71
         * @return ?class-string<Template>
72
         */
73
        protected function checkTemplateClass(string $class): ?string
1✔
74
        {
75
                if (!class_exists($class)) {
1✔
76
                        return null;
1✔
77
                } elseif (!is_a($class, Template::class, allow_string: true)) {
1✔
78
                        trigger_error(sprintf(
1✔
79
                                '%s: class %s was found but does not implement the %s, so it will not be used for the template.',
1✔
80
                                static::class,
1✔
81
                                $class,
1✔
82
                                Template::class,
1✔
83
                        ));
84
                        return null;
1✔
85
                } else {
86
                        return $class;
1✔
87
                }
88
        }
89

90

91
        /**
92
         * Descendant can override this method to customize template compile-time filters.
93
         * @deprecated
94
         */
95
        public function templatePrepareFilters(Template $template): void
96
        {
97
        }
98

99

100
        /**
101
         * Saves the message to template, that can be displayed after redirect.
102
         */
103
        public function flashMessage(string|\stdClass|\Stringable $message, string $type = 'info'): \stdClass
1✔
104
        {
105
                $id = $this->getParameterId('flash');
1✔
106
                $flash = $message instanceof \stdClass ? $message : (object) [
1✔
107
                        'message' => $message,
1✔
108
                        'type' => $type,
1✔
109
                ];
110
                $messages = $this->getPresenter()->getFlashSession()->get($id);
1✔
111
                $messages[] = $flash;
1✔
112
                $this->getTemplate()->flashes = $messages;
1✔
113
                $this->getPresenter()->getFlashSession()->set($id, $messages);
1✔
114
                return $flash;
1✔
115
        }
116

117

118
        /********************* rendering ****************d*g**/
119

120

121
        /**
122
         * Forces control or its snippet to repaint.
123
         */
124
        public function redrawControl(?string $snippet = null, bool $redraw = true): void
1✔
125
        {
126
                if ($redraw) {
1✔
127
                        $this->invalidSnippets[$snippet ?? "\0"] = true;
1✔
128

129
                } elseif ($snippet === null) {
1✔
130
                        $this->invalidSnippets = [];
1✔
131

132
                } else {
133
                        $this->invalidSnippets[$snippet] = false;
1✔
134
                }
135
        }
1✔
136

137

138
        /**
139
         * Is required to repaint the control or its snippet?
140
         */
141
        public function isControlInvalid(?string $snippet = null): bool
1✔
142
        {
143
                if ($snippet !== null) {
1✔
144
                        return $this->invalidSnippets[$snippet] ?? isset($this->invalidSnippets["\0"]);
1✔
145

146
                } elseif (count($this->invalidSnippets) > 0) {
1✔
147
                        return true;
1✔
148
                }
149

150
                $queue = [$this];
1✔
151
                do {
152
                        foreach (array_shift($queue)->getComponents() as $component) {
1✔
153
                                if ($component instanceof Renderable) {
1✔
154
                                        if ($component->isControlInvalid()) {
1✔
155
                                                // $this->invalidSnippets['__child'] = true; // as cache
156
                                                return true;
1✔
157
                                        }
158
                                } elseif ($component instanceof Nette\ComponentModel\IContainer) {
1✔
159
                                        $queue[] = $component;
1✔
160
                                }
161
                        }
162
                } while ($queue);
1✔
163

164
                return false;
1✔
165
        }
166

167

168
        /**
169
         * Returns snippet HTML ID.
170
         */
171
        public function getSnippetId(string $name): string
1✔
172
        {
173
                // HTML 4 ID & NAME: [A-Za-z][A-Za-z0-9:_.-]*
174
                return 'snippet-' . $this->getUniqueId() . '-' . $name;
1✔
175
        }
176
}
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