1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Control.php |
4
|
|
|
* |
5
|
|
|
* @copyright More in license.md |
6
|
|
|
* @license http://www.ipublikuj.eu |
7
|
|
|
* @author Adam Kadlec http://www.ipublikuj.eu |
8
|
|
|
* @package iPublikuj:ConfirmationDialog! |
9
|
|
|
* @subpackage Components |
10
|
|
|
* @since 1.0.0 |
11
|
|
|
* |
12
|
|
|
* @date 12.03.14 |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
declare(strict_types = 1); |
16
|
|
|
|
17
|
|
|
namespace IPub\ConfirmationDialog\Components; |
18
|
|
|
|
19
|
|
|
use Nette; |
20
|
|
|
use Nette\Application; |
21
|
|
|
use Nette\Localization; |
22
|
|
|
use Nette\Utils; |
23
|
|
|
|
24
|
|
|
use IPub; |
25
|
|
|
use IPub\ConfirmationDialog\Exceptions; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Confirmation dialog control |
29
|
|
|
* |
30
|
|
|
* @package iPublikuj:ConfirmationDialog! |
31
|
|
|
* @subpackage Components |
32
|
|
|
*/ |
33
|
1 |
|
final class Control extends BaseControl |
34
|
|
|
{ |
35
|
|
|
/** |
36
|
|
|
* Define class name |
37
|
|
|
*/ |
38
|
|
|
const CLASS_NAME = __CLASS__; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @var IConfirmer |
42
|
|
|
*/ |
43
|
|
|
private $confirmerFactory; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @var Confirmer |
47
|
|
|
*/ |
48
|
|
|
private $confirmer; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @var bool |
52
|
|
|
*/ |
53
|
|
|
private $useAjax = TRUE; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* @param IConfirmer $confirmerFactory |
57
|
|
|
*/ |
58
|
|
|
public function injectFactories(IConfirmer $confirmerFactory) |
59
|
|
|
{ |
60
|
|
|
// Get confirmer component factory |
61
|
1 |
|
$this->confirmerFactory = $confirmerFactory; |
62
|
1 |
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* @param string|NULL $layoutFile |
66
|
|
|
* @param string|NULL $templateFile |
67
|
|
|
*/ |
68
|
|
|
public function __construct( |
69
|
|
|
string $layoutFile = NULL, |
70
|
|
|
string $templateFile = NULL |
71
|
|
|
) { |
72
|
1 |
|
list(, , $parent, $name) = func_get_args() + [NULL, NULL, NULL, NULL]; |
73
|
|
|
|
74
|
1 |
|
parent::__construct($parent, $name); |
75
|
|
|
|
76
|
1 |
|
if ($layoutFile !== NULL) { |
77
|
|
|
$this->setLayoutFile($layoutFile); |
78
|
|
|
} |
79
|
|
|
|
80
|
1 |
|
if ($templateFile !== NULL) { |
81
|
|
|
$this->setTemplateFile($templateFile); |
82
|
|
|
} |
83
|
1 |
|
} |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* Change default dialog layout path |
87
|
|
|
* |
88
|
|
|
* @param string $layoutFile |
89
|
|
|
* |
90
|
|
|
* @return void |
91
|
|
|
*/ |
92
|
|
|
public function setLayoutFile(string $layoutFile) |
93
|
|
|
{ |
94
|
|
|
$this->setTemplateFilePath($layoutFile, self::TEMPLATE_LAYOUT); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* Change default confirmer template path |
99
|
|
|
* |
100
|
|
|
* @param string $layoutFile |
101
|
|
|
* |
102
|
|
|
* @return void |
103
|
|
|
*/ |
104
|
|
|
public function setTemplateFile(string $layoutFile) |
105
|
|
|
{ |
106
|
1 |
|
$this->setTemplateFilePath($layoutFile, self::TEMPLATE_CONFIRMER); |
107
|
1 |
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* @return string |
111
|
|
|
*/ |
112
|
|
|
public function getTemplateFile() : string |
113
|
|
|
{ |
114
|
|
|
// ...try to get default component layout file |
115
|
1 |
|
return $this->templateFile !== NULL ? $this->templateFile : __DIR__ . DIRECTORY_SEPARATOR . 'template' . DIRECTORY_SEPARATOR . 'default.latte'; |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Overrides signal method formatter |
120
|
|
|
* This provide "dynamically named signals" |
121
|
|
|
* |
122
|
|
|
* @param string $signal |
123
|
|
|
* |
124
|
|
|
* @return string |
125
|
|
|
*/ |
126
|
|
|
public static function formatSignalMethod($signal) : string |
127
|
|
|
{ |
128
|
1 |
|
if (Utils\Strings::startsWith($signal, 'confirm')) { |
129
|
1 |
|
return 'handleShowConfirmer'; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
return parent::formatSignalMethod($signal); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Add confirmation handler to "dynamicaly named signals" |
137
|
|
|
* |
138
|
|
|
* @param string $name Confirmation/signal name |
139
|
|
|
* @param callback|Nette\Utils\Callback $handler Callback called when confirmation succeed |
140
|
|
|
* @param callback|string $question Callback ($confirmer, $params) or string containing question text |
141
|
|
|
* @param callback|string $heading Callback ($confirmer, $params) or string containing heading text |
142
|
|
|
* |
143
|
|
|
* @return void |
144
|
|
|
* |
145
|
|
|
* @throws Exceptions\InvalidArgumentException |
146
|
|
|
*/ |
147
|
|
|
public function addConfirmer(string $name, $handler, $question, $heading) |
148
|
|
|
{ |
149
|
|
|
// Confirmer name could be only A-z |
150
|
1 |
|
if (!preg_match('/[A-Za-z_]+/', $name)) { |
151
|
|
|
throw new Exceptions\InvalidArgumentException("Confirmation control name contain invalid characters."); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
// Check confirmer |
155
|
1 |
View Code Duplication |
if ((!$confirmer = $this->getComponent('confirmer-' . $name)) || !$confirmer instanceof Confirmer || $confirmer->isConfigured()) { |
|
|
|
|
156
|
|
|
throw new Exceptions\InvalidArgumentException("Confirmation control '$name' could not be created."); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
// Set confirmer handler |
160
|
1 |
|
$confirmer->setHandler($handler); |
161
|
|
|
// Set confirmer heading |
162
|
1 |
|
$confirmer->setHeading($heading); |
163
|
|
|
// Set confirmer question |
164
|
1 |
|
$confirmer->setQuestion($question); |
165
|
1 |
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* @param string $name |
169
|
|
|
* |
170
|
|
|
* @return Confirmer |
171
|
|
|
* |
172
|
|
|
* @throws Exceptions\InvalidArgumentException |
173
|
|
|
*/ |
174
|
|
|
public function getConfirmer(string $name) : Confirmer |
175
|
|
|
{ |
176
|
|
View Code Duplication |
if ((!$confirmer = $this->getComponent('confirmer-' . $name)) || !$confirmer instanceof Confirmer || !$confirmer->isConfigured()) { |
|
|
|
|
177
|
|
|
throw new Exceptions\InvalidArgumentException("Confirmation control '$name' does not exists."); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
return $confirmer; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* @return void |
185
|
|
|
*/ |
186
|
|
|
public function resetConfirmer() |
187
|
|
|
{ |
188
|
1 |
|
$this->confirmer = NULL; |
189
|
|
|
|
190
|
|
|
// Invalidate dialog snippets |
191
|
1 |
|
$this->redrawControl(); |
192
|
1 |
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* @return Application\UI\Multiplier |
196
|
|
|
* |
197
|
|
|
* @throws Exceptions\InvalidArgumentException |
198
|
|
|
*/ |
199
|
|
|
protected function createComponentConfirmer() : Application\UI\Multiplier |
200
|
|
|
{ |
201
|
1 |
|
return new Application\UI\Multiplier((function () { |
202
|
|
|
// Check if confirmer factory is available |
203
|
1 |
|
if (!$this->confirmerFactory) { |
204
|
|
|
throw new Exceptions\InvalidStateException("Confirmation control factory does not exist."); |
205
|
|
|
} |
206
|
|
|
|
207
|
1 |
|
$confirmer = $this->confirmerFactory->create($this->templateFile); |
208
|
|
|
|
209
|
1 |
|
if ($this->useAjax) { |
210
|
1 |
|
$confirmer->enableAjax(); |
211
|
|
|
|
212
|
|
|
} else { |
213
|
|
|
$confirmer->disableAjax(); |
214
|
|
|
} |
215
|
|
|
|
216
|
1 |
|
return $confirmer; |
217
|
1 |
|
})); |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
/** |
221
|
|
|
* Show dialog for confirmation |
222
|
|
|
* |
223
|
|
|
* @param string $name |
224
|
|
|
* @param array $params |
225
|
|
|
* |
226
|
|
|
* @return void |
227
|
|
|
* |
228
|
|
|
* @throws Exceptions\InvalidArgumentException |
229
|
|
|
* @throws Exceptions\InvalidStateException |
230
|
|
|
*/ |
231
|
|
|
public function showConfirm(string $name, array $params = []) |
232
|
|
|
{ |
233
|
1 |
|
if (!is_string($name)) { |
234
|
|
|
throw new Exceptions\InvalidArgumentException('$name must be string.'); |
235
|
|
|
} |
236
|
|
|
|
237
|
1 |
|
if ((!$this->confirmer = $this['confirmer-' . $name]) || !$this->confirmer->isConfigured()) { |
238
|
|
|
throw new Exceptions\InvalidStateException("Confirmer '$name' do not exist."); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
// Prepare confirmer for displaying |
242
|
1 |
|
$this->confirmer->showConfirm($params); |
243
|
1 |
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* Dynamically named signal receiver |
247
|
|
|
* |
248
|
|
|
* @return void |
249
|
|
|
* |
250
|
|
|
* @throws Exceptions\InvalidArgumentException |
251
|
|
|
* @throws Exceptions\InvalidStateException |
252
|
|
|
*/ |
253
|
|
|
public function handleShowConfirmer() |
254
|
|
|
{ |
255
|
1 |
|
if (!$this->getPresenter() instanceof Application\UI\Presenter) { |
256
|
|
|
throw new Exceptions\InvalidArgumentException('Confirmer is not attached to presenter.'); |
257
|
|
|
} |
258
|
|
|
|
259
|
1 |
|
list(, $signal) = $this->getPresenter()->getSignal(); |
260
|
|
|
|
261
|
1 |
|
$name = Utils\Strings::substring($signal, 7); |
262
|
1 |
|
$name{0} = strtolower($name{0}); |
263
|
|
|
|
264
|
1 |
|
if (!$this['confirmer-' . $name]->isConfigured()) { |
265
|
|
|
throw new Exceptions\InvalidArgumentException('Invalid confirmation control.'); |
266
|
|
|
} |
267
|
|
|
|
268
|
1 |
|
$params = $this->getParameters(); |
269
|
|
|
|
270
|
1 |
|
$this->showConfirm($name, $params); |
271
|
1 |
|
} |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* @return void |
275
|
|
|
*/ |
276
|
|
|
public function enableAjax() |
277
|
|
|
{ |
278
|
|
|
$this->useAjax = TRUE; |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
/** |
282
|
|
|
* @return void |
283
|
|
|
*/ |
284
|
|
|
public function disableAjax() |
285
|
|
|
{ |
286
|
|
|
$this->useAjax = FALSE; |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
/** |
290
|
|
|
* Render control |
291
|
|
|
* |
292
|
|
|
* @return void |
293
|
|
|
* |
294
|
|
|
* @throws Exceptions\InvalidStateException |
295
|
|
|
*/ |
296
|
|
|
public function render() |
297
|
|
|
{ |
298
|
|
|
// Create template |
299
|
1 |
|
$template = parent::render(); |
300
|
|
|
|
301
|
|
|
// Check if control has template |
302
|
1 |
|
if ($template instanceof Nette\Bridges\ApplicationLatte\Template) { |
303
|
|
|
// Assign vars to template |
304
|
1 |
|
$template->confirmer = $this->confirmer; |
305
|
|
|
|
306
|
|
|
// If template was not defined before... |
307
|
1 |
|
if ($template->getFile() === NULL) { |
308
|
|
|
// ...try to get base component template file |
309
|
1 |
|
$layoutFile = $this->layoutFile !== NULL ? $this->layoutFile : __DIR__ . DIRECTORY_SEPARATOR . 'template' . DIRECTORY_SEPARATOR . 'layout.latte'; |
310
|
1 |
|
$template->setFile($layoutFile); |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
// Render component template |
314
|
1 |
|
$template->render(); |
315
|
|
|
|
316
|
|
|
} else { |
317
|
|
|
throw new Exceptions\InvalidStateException('Dialog control is without template.'); |
318
|
|
|
} |
319
|
1 |
|
} |
320
|
|
|
} |
321
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.