Completed
Push — master ( e30e5f...00a259 )
by Adam
02:09
created

Control::__construct()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.1406

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 6
cts 8
cp 0.75
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 11
nc 4
nop 3
crap 3.1406
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
 * @author         Adam Kadlec <[email protected]>
34
 */
35 1
final class Control extends BaseControl
36
{
37
	/**
38
	 * @var IConfirmer
39
	 */
40
	private $confirmerFactory;
41
42
	/**
43
	 * @var Confirmer
44
	 */
45
	private $confirmer;
46
47
	/**
48
	 * @var bool
49
	 */
50
	private $useAjax = TRUE;
51
52
	/**
53
	 * @param string|NULL $layoutFile
54
	 * @param string|NULL $templateFile
55
	 * @param IConfirmer $confirmerFactory
56
	 */
57
	public function __construct(
58
		string $layoutFile = NULL,
59
		string $templateFile = NULL,
60
		IConfirmer $confirmerFactory
61
	) {
62 1
		list(, , , $parent, $name) = func_get_args() + [NULL, NULL, NULL, NULL, NULL];
63
64 1
		parent::__construct($parent, $name);
65
66 1
		if ($layoutFile !== NULL) {
67
			$this->setLayoutFile($layoutFile);
68
		}
69
70 1
		if ($templateFile !== NULL) {
71
			$this->setTemplateFile($templateFile);
72
		}
73
74
		// Get confirmer component factory
75 1
		$this->confirmerFactory = $confirmerFactory;
76 1
	}
77
78
	/**
79
	 * Change default dialog layout path
80
	 *
81
	 * @param string $layoutFile
82
	 *
83
	 * @return void
84
	 */
85
	public function setLayoutFile(string $layoutFile)
86
	{
87
		$this->setTemplateFilePath($layoutFile, self::TEMPLATE_LAYOUT);
88
	}
89
90
	/**
91
	 * Change default confirmer template path
92
	 *
93
	 * @param string $layoutFile
94
	 *
95
	 * @return void
96
	 */
97
	public function setTemplateFile(string $layoutFile)
98
	{
99 1
		$this->setTemplateFilePath($layoutFile, self::TEMPLATE_CONFIRMER);
100 1
	}
101
102
	/**
103
	 * @return string
104
	 */
105
	public function getTemplateFile() : string
106
	{
107
		// ...try to get default component layout file
108 1
		return $this->templateFile !== NULL ? $this->templateFile : __DIR__ . DIRECTORY_SEPARATOR . 'template' . DIRECTORY_SEPARATOR . 'default.latte';
109
	}
110
111
	/**
112
	 * Overrides signal method formatter
113
	 * This provide "dynamically named signals"
114
	 *
115
	 * @param string $signal
116
	 *
117
	 * @return string
118
	 */
119
	public static function formatSignalMethod($signal) : string
120
	{
121 1
		if (Utils\Strings::startsWith($signal, 'confirm')) {
122 1
			return 'handleShowConfirmer';
123
		}
124
125
		return parent::formatSignalMethod($signal);
126
	}
127
128
	/**
129
	 * Add confirmation handler to "dynamicaly named signals"
130
	 *
131
	 * @param string $name                           Confirmation/signal name
132
	 * @param callback|Nette\Utils\Callback $handler Callback called when confirmation succeed
133
	 * @param callback|string $question              Callback ($confirmer, $params) or string containing question text
134
	 * @param callback|string $heading               Callback ($confirmer, $params) or string containing heading text
135
	 *
136
	 * @return void
137
	 *
138
	 * @throws Exceptions\InvalidArgumentException
139
	 */
140
	public function addConfirmer(string $name, $handler, $question, $heading)
141
	{
142
		// Confirmer name could be only A-z
143 1
		if (!preg_match('/[A-Za-z_]+/', $name)) {
144
			throw new Exceptions\InvalidArgumentException('Confirmation control name contain invalid characters.');
145
		}
146
147 1
		$confirmer = $this->getConfirmerControl($name);
148
149
		// Check confirmer
150 1
		if ($confirmer->isConfigured()) {
151
			throw new Exceptions\InvalidArgumentException(sprintf('Confirmation control "%s" could not be created.', $name));
152
		}
153
154
		// Set confirmer handler
155 1
		$confirmer->setHandler($handler);
156
		// Set confirmer heading
157 1
		$confirmer->setHeading($heading);
158
		// Set confirmer question
159 1
		$confirmer->setQuestion($question);
160 1
	}
161
162
	/**
163
	 * @param string $name
164
	 *
165
	 * @return Confirmer
166
	 *
167
	 * @throws Exceptions\InvalidArgumentException
168
	 */
169
	public function getConfirmer(string $name) : Confirmer
170
	{
171
		$confirmer = $this->getConfirmerControl($name);
172
173
		// Check confirmer
174
		if (!$confirmer->isConfigured()) {
175
			throw new Exceptions\InvalidArgumentException(sprintf('Confirmation control "%s" does not exists.', $name));
176
		}
177
178
		return $confirmer;
179
	}
180
181
	/**
182
	 * @return void
183
	 */
184
	public function resetConfirmer()
185
	{
186 1
		$this->confirmer = NULL;
187
188
		// Invalidate dialog snippets
189 1
		$this->redrawControl();
190 1
	}
191
192
	/**
193
	 * @return Application\UI\Multiplier
194
	 *
195
	 * @throws Exceptions\InvalidArgumentException
196
	 */
197
	protected function createComponentConfirmer() : Application\UI\Multiplier
198
	{
199 1
		return new Application\UI\Multiplier((function () {
200
			// Check if confirmer factory is available
201 1
			if (!$this->confirmerFactory) {
202
				throw new Exceptions\InvalidStateException('Confirmation control factory does not exist.');
203
			}
204
205 1
			$confirmer = $this->confirmerFactory->create($this->templateFile);
206
207 1
			if ($this->useAjax) {
208 1
				$confirmer->enableAjax();
209
210
			} else {
211
				$confirmer->disableAjax();
212
			}
213
214 1
			return $confirmer;
215 1
		}));
216
	}
217
218
	/**
219
	 * Show dialog for confirmation
220
	 *
221
	 * @param string $name
222
	 * @param array $params
223
	 *
224
	 * @return void
225
	 *
226
	 * @throws Exceptions\InvalidArgumentException
227
	 * @throws Exceptions\InvalidStateException
228
	 */
229
	public function showConfirm(string $name, array $params = [])
230
	{
231 1
		if (!is_string($name)) {
232
			throw new Exceptions\InvalidArgumentException('$name must be string.');
233
		}
234
235 1
		if ((!$this->confirmer = $this['confirmer-' . $name]) || !$this->confirmer->isConfigured()) {
236
			throw new Exceptions\InvalidStateException(sprintf('Confirmer "%s" do not exist.', $name));
237
		}
238
239
		// Prepare confirmer for displaying
240 1
		$this->confirmer->showConfirm($params);
241 1
	}
242
243
	/**
244
	 * Dynamically named signal receiver
245
	 *
246
	 * @return void
247
	 *
248
	 * @throws Exceptions\InvalidArgumentException
249
	 * @throws Exceptions\InvalidStateException
250
	 */
251
	public function handleShowConfirmer()
252
	{
253 1
		if (!$this->getPresenter() instanceof Application\UI\Presenter) {
254
			throw new Exceptions\InvalidArgumentException('Confirmer is not attached to presenter.');
255
		}
256
257 1
		list(, $signal) = $this->getPresenter()->getSignal();
258
259 1
		$name = Utils\Strings::substring($signal, 7);
260 1
		$name{0} = strtolower($name{0});
261
262 1
		if (!$this['confirmer-' . $name]->isConfigured()) {
263
			throw new Exceptions\InvalidArgumentException('Invalid confirmation control.');
264
		}
265
266 1
		$params = $this->getParameters();
267
268 1
		$this->showConfirm($name, $params);
269 1
	}
270
271
	/**
272
	 * @return void
273
	 */
274
	public function enableAjax()
275
	{
276
		$this->useAjax = TRUE;
277
	}
278
279
	/**
280
	 * @return void
281
	 */
282
	public function disableAjax()
283
	{
284
		$this->useAjax = FALSE;
285
	}
286
287
	/**
288
	 * Render control
289
	 *
290
	 * @return void
291
	 *
292
	 * @throws Exceptions\InvalidStateException
293
	 */
294
	public function render()
295
	{
296
		// Create template
297 1
		$template = parent::render();
298
299
		// Check if control has template
300 1
		if ($template instanceof Nette\Bridges\ApplicationLatte\Template) {
301
			// Assign vars to template
302 1
			$template->confirmer = $this->confirmer;
303
304
			// If template was not defined before...
305 1
			if ($template->getFile() === NULL) {
306
				// ...try to get base component template file
307 1
				$layoutFile = $this->layoutFile !== NULL ? $this->layoutFile : __DIR__ . DIRECTORY_SEPARATOR . 'template' . DIRECTORY_SEPARATOR . 'layout.latte';
308 1
				$template->setFile($layoutFile);
309
			}
310
311
			// Render component template
312 1
			$template->render();
313
314
		} else {
315
			throw new Exceptions\InvalidStateException('Dialog control is without template.');
316
		}
317 1
	}
318
319
	/**
320
	 * @param string $name
321
	 *
322
	 * @return Confirmer
323
	 *
324
	 * @throws Exceptions\InvalidArgumentException
325
	 */
326
	private function getConfirmerControl(string $name) : Confirmer
327
	{
328 1
		$confirmer = $this->getComponent('confirmer-' . $name);
329
330 1
		if (!$confirmer instanceof Confirmer) {
331
			throw new Exceptions\InvalidArgumentException(sprintf('Confirmation control "%s" does not exists.', $name));
332
		}
333
334 1
		return $confirmer;
335
	}
336
}
337