1: <?php
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:
12:
13: /**
14: * Control is renderable Presenter component.
15: *
16: * @property-read ITemplate $template
17: */
18: abstract class Control extends Component implements IRenderable
19: {
20: /** @var ITemplateFactory */
21: private $templateFactory;
22:
23: /** @var ITemplate */
24: private $template;
25:
26: /** @var array */
27: private $invalidSnippets = [];
28:
29: /** @var bool */
30: public $snippetMode;
31:
32:
33: /********************* template factory ****************d*g**/
34:
35:
36: public function setTemplateFactory(ITemplateFactory $templateFactory)
37: {
38: $this->templateFactory = $templateFactory;
39: }
40:
41:
42: /**
43: * @return ITemplate
44: */
45: public function getTemplate()
46: {
47: if ($this->template === NULL) {
48: $value = $this->createTemplate();
49: if (!$value instanceof ITemplate && $value !== NULL) {
50: $class2 = get_class($value); $class = get_class($this);
51: throw new Nette\UnexpectedValueException("Object returned by $class::createTemplate() must be instance of Nette\\Application\\UI\\ITemplate, '$class2' given.");
52: }
53: $this->template = $value;
54: }
55: return $this->template;
56: }
57:
58:
59: /**
60: * @return ITemplate
61: */
62: protected function createTemplate()
63: {
64: $templateFactory = $this->templateFactory ?: $this->getPresenter()->getTemplateFactory();
65: return $templateFactory->createTemplate($this);
66: }
67:
68:
69: /**
70: * Descendant can override this method to customize template compile-time filters.
71: * @param ITemplate
72: * @return void
73: */
74: public function templatePrepareFilters($template)
75: {
76: }
77:
78:
79: /**
80: * Saves the message to template, that can be displayed after redirect.
81: * @param string
82: * @param string
83: * @return \stdClass
84: */
85: public function flashMessage($message, $type = 'info')
86: {
87: $id = $this->getParameterId('flash');
88: $messages = $this->getPresenter()->getFlashSession()->$id;
89: $messages[] = $flash = (object) [
90: 'message' => $message,
91: 'type' => $type,
92: ];
93: $this->getTemplate()->flashes = $messages;
94: $this->getPresenter()->getFlashSession()->$id = $messages;
95: return $flash;
96: }
97:
98:
99: /********************* rendering ****************d*g**/
100:
101:
102: /**
103: * Forces control or its snippet to repaint.
104: * @return void
105: */
106: public function redrawControl($snippet = NULL, $redraw = TRUE)
107: {
108: if ($redraw) {
109: $this->invalidSnippets[$snippet === NULL ? "\0" : $snippet] = TRUE;
110:
111: } elseif ($snippet === NULL) {
112: $this->invalidSnippets = [];
113:
114: } else {
115: $this->invalidSnippets[$snippet] = FALSE;
116: }
117: }
118:
119:
120: /** @deprecated */
121: function invalidateControl($snippet = NULL)
122: {
123: trigger_error(__METHOD__ . '() is deprecated; use $this->redrawControl($snippet) instead.', E_USER_DEPRECATED);
124: $this->redrawControl($snippet);
125: }
126:
127: /** @deprecated */
128: function validateControl($snippet = NULL)
129: {
130: trigger_error(__METHOD__ . '() is deprecated; use $this->redrawControl($snippet, FALSE) instead.', E_USER_DEPRECATED);
131: $this->redrawControl($snippet, FALSE);
132: }
133:
134:
135: /**
136: * Is required to repaint the control or its snippet?
137: * @param string snippet name
138: * @return bool
139: */
140: public function isControlInvalid($snippet = NULL)
141: {
142: if ($snippet === NULL) {
143: if (count($this->invalidSnippets) > 0) {
144: return TRUE;
145:
146: } else {
147: $queue = [$this];
148: do {
149: foreach (array_shift($queue)->getComponents() as $component) {
150: if ($component instanceof IRenderable) {
151: if ($component->isControlInvalid()) {
152: // $this->invalidSnippets['__child'] = TRUE; // as cache
153: return TRUE;
154: }
155:
156: } elseif ($component instanceof Nette\ComponentModel\IContainer) {
157: $queue[] = $component;
158: }
159: }
160: } while ($queue);
161:
162: return FALSE;
163: }
164:
165: } elseif (isset($this->invalidSnippets[$snippet])) {
166: return $this->invalidSnippets[$snippet];
167: } else {
168: return isset($this->invalidSnippets["\0"]);
169: }
170: }
171:
172:
173: /**
174: * Returns snippet HTML ID.
175: * @param string snippet name
176: * @return string
177: */
178: public function getSnippetId($name = NULL)
179: {
180: // HTML 4 ID & NAME: [A-Za-z][A-Za-z0-9:_.-]*
181: return 'snippet-' . $this->getUniqueId() . '-' . $name;
182: }
183:
184: }
185: