Completed
Push — master ( 466d8a...4a1721 )
by Adam
04:54
created

ConfirmerAttributes::setHandler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 5
ccs 2
cts 2
cp 1
rs 9.4285
c 1
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * ConfirmerAttributes.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           31.03.14
13
 */
14
15
declare(strict_types = 1);
16
17
namespace IPub\ConfirmationDialog\Components;
18
19
use Nette;
20
use Nette\Application;
21
22
use IPub;
23
use IPub\ConfirmationDialog;
24
use IPub\ConfirmationDialog\Exceptions;
25
use IPub\ConfirmationDialog\Storage;
26
27
/**
28
 * Confirmation dialog confirmer control
29
 *
30
 * @package        iPublikuj:ConfirmationDialog!
31
 * @subpackage     Components
32
 *
33
 * @author         Adam Kadlec <[email protected]>
34
 *
35
 * @property-read string $name
36
 */
37 1
abstract class ConfirmerAttributes extends BaseControl
38
{
39
	/**
40
	 * @var array localization strings
41
	 */
42
	public static $strings = [
43
		'yes'     => 'Yes',
44
		'no'      => 'No',
45
		'expired' => 'Confirmation token has expired. Please try action again.',
46
	];
47
48
	/**
49
	 * @var string
50
	 */
51
	protected $cssClass;
52
53
	/**
54
	 * @var string|callable heading
55
	 */
56
	protected $heading;
57
58
	/**
59
	 * @var string|callable question
60
	 */
61
	protected $question;
62
63
	/**
64
	 * @var string|callable icon
65
	 */
66
	protected $icon;
67
68
	/**
69
	 * @var callable
70
	 */
71
	protected $handler;
72
73
	/**
74
	 * @var bool
75
	 */
76
	protected $useAjax = TRUE;
77
78
	/**
79
	 * @var Storage\IStorage
80
	 */
81
	protected $storage;
82
83
	/**
84
	 * @param Storage\IStorage $storage
85
	 */
86
	public function __construct(Storage\IStorage $storage)
87
	{
88 1
		list(, $parent, $name) = func_get_args() + [NULL, NULL, NULL];
89
90 1
		parent::__construct($parent, $name);
91
92
		// Get data storage for confirmer
93 1
		$this->storage = $storage;
94 1
	}
95
96
	/**
97
	 * Set dialog heading
98
	 *
99
	 * @param string|callable $heading
100
	 *
101
	 * @return void
102
	 *
103
	 * @throws Exceptions\InvalidArgumentException
104
	 */
105
	public function setHeading($heading) : void
106
	{
107
		// Check variable type
108 1
		if ($this->checkCallableOrString($heading)) {
109
			// Update confirmation heading
110 1
			$this->heading = $heading;
111
		}
112 1
	}
113
114
	/**
115
	 * Get dialog heding
116
	 *
117
	 * @return string|NULL
118
	 *
119
	 * @throws Exceptions\InvalidStateException
120
	 */
121
	public function getHeading() : ?string
122
	{
123 1
		return $this->getAttribute('heading');
124
	}
125
126
	/**
127
	 * Set dialog question
128
	 *
129
	 * @param string|callable $question
130
	 *
131
	 * @return void
132
	 *
133
	 * @throws Exceptions\InvalidArgumentException
134
	 */
135
	public function setQuestion($question) : void
136
	{
137
		// Check variable type
138 1
		if ($this->checkCallableOrString($question)) {
139
			// Update confirmation question
140 1
			$this->question = $question;
141
		}
142 1
	}
143
144
	/**
145
	 * @return string|NULL
146
	 *
147
	 * @throws Exceptions\InvalidStateException
148
	 */
149
	public function getQuestion() : ?string
150
	{
151 1
		$question = NULL;
152
153
		// Check if attribute is callable
154 1
		if (is_callable($this->question)) {
155
			$question = $this->callCallableAttribute($this->question);
156
157
			if ($question !== NULL) {
158
				$question = (string) $question;
159
			}
160
161 1
		} elseif ($this->question !== NULL) {
162 1
			$question = (string) $this->question;
163
		}
164
165 1
		return is_bool($question) && $question === FALSE ? NULL : $question;
166
	}
167
168
	/**
169
	 * Set dialog icon
170
	 *
171
	 * @param string|callable $icon
172
	 *
173
	 * @return void
174
	 *
175
	 * @throws Exceptions\InvalidArgumentException
176
	 */
177
	public function setIcon($icon) : void
178
	{
179
		// Check variable type
180
		if ($this->checkCallableOrString($icon)) {
181
			// Update confirmation icon
182
			$this->icon = $icon;
183
		}
184
	}
185
186
	/**
187
	 * @return string|NULL
188
	 *
189
	 * @throws Exceptions\InvalidStateException
190
	 */
191
	public function getIcon() : ?string
192
	{
193 1
		return $this->getAttribute('icon');
194
	}
195
196
	/**
197
	 * Set dialog handler
198
	 *
199
	 * @param callable $handler
200
	 *
201
	 * @return void
202
	 *
203
	 * @throws Exceptions\InvalidArgumentException
204
	 */
205
	public function setHandler(callable $handler) : void
206
	{
207
		// Update confirmation handler
208 1
		$this->handler = $handler;
209 1
	}
210
211
	/**
212
	 * @return callable
213
	 */
214
	public function getHandler() : callable
215
	{
216 1
		return $this->handler;
217
	}
218
219
	/**
220
	 * @param Nette\ComponentModel\IContainer $obj
221
	 * @param array $params
222
	 *
223
	 * @return mixed
224
	 *
225
	 * @throws Exceptions\HandlerNotCallableException
226
	 */
227
	public function callHandler(Nette\ComponentModel\IContainer $obj, array $params)
228
	{
229 1
		$callback = $this->getHandler();
230
231 1
		if ($callback instanceof \Closure) {
232
			$result = call_user_func_array($callback, $params);
233
234 1
		} elseif (method_exists($obj, 'tryCall')) {
235 1
			$result = call_user_func_array([$obj, 'tryCall'], ['method' => $callback[1], 'params' => $params]);
236
237
		} else {
238
			$result = call_user_func_array([$obj, $callback[1]], $params);
239
		}
240
241
		if ($result === FALSE) {
242
			throw new Exceptions\HandlerNotCallableException('Confirm action callback was not successful.');
243
		}
244
245
		return $result;
246
	}
247
248
	/**
249
	 * @return void
250
	 */
251
	public function enableAjax() : void
252
	{
253 1
		$this->useAjax = TRUE;
254 1
	}
255
256
	/**
257
	 * @return void
258
	 */
259
	public function disableAjax() : void
260
	{
261
		$this->useAjax = FALSE;
262
	}
263
264
	/**
265
	 * @return Application\UI\Form
266
	 */
267
	protected function createComponentForm() : Application\UI\Form
268
	{
269
		// Create confirmation form
270 1
		$form = new Application\UI\Form();
271
272
		// Security field
273 1
		$form->addHidden('secureToken');
274
275
		// Form protection
276 1
		$form->addProtection($this->translator ? $this->translator->translate('confirmationDialog.messages.tokenIsExpired') : self::$strings['expired']);
277
278
		// Confirm buttons
279 1
		$form->addSubmit('yes', $this->translator ? $this->translator->translate('confirmationDialog.buttons.bYes') : self::$strings['yes'])
280 1
			->onClick[] = [$this, 'confirmClicked'];
281
282 1
		$form->addSubmit('no', $this->translator ? $this->translator->translate('confirmationDialog.buttons.bNo') : self::$strings['no'])
283 1
			->onClick[] = [$this, 'cancelClicked'];
284
285 1
		return $form;
286
	}
287
288
	/**
289
	 * @param string $token
290
	 *
291
	 * @return array
292
	 *
293
	 * @throws Exceptions\InvalidStateException
294
	 */
295
	protected function getConfirmerValues(string $token) : array
296
	{
297
		// Get values stored in confirmer storage
298 1
		$values = $this->storage->get($token);
299
300
		// Check for correct values
301 1
		if (!is_array($values) || !isset($values['confirmer']) || !isset($values['params'])) {
302
			throw new Exceptions\InvalidStateException('Confirmer is not configured!');
303
		}
304
305 1
		return $values;
306
	}
307
308
	/**
309
	 * @param callable|string $var
310
	 *
311
	 * @return bool
312
	 *
313
	 * @throws Exceptions\InvalidArgumentException
314
	 */
315
	private function checkCallableOrString($var) : bool
316
	{
317 1
		if (!is_callable($var) && !is_string($var)) {
318
			throw new Exceptions\InvalidArgumentException(sprintf('%s must be callback or string.', $var));
319
		}
320
321 1
		return TRUE;
322
	}
323
324
	/**
325
	 * @param callable $attribute
326
	 *
327
	 * @return string
328
	 *
329
	 * @throws Exceptions\InvalidStateException
330
	 */
331
	private function callCallableAttribute(callable $attribute) : string
332
	{
333
		if ($this['form']['secureToken']->value === NULL) {
334
			throw new Exceptions\InvalidStateException('Token is not set!');
335
		}
336
337
		// Get token from form
338
		$token = $this['form']['secureToken']->value;
339
340
		// Get values stored in confirmer storage
341
		$values = $this->getConfirmerValues($token);
342
343
		return call_user_func_array($attribute, [$this, $values['params']]);
344
	}
345
346
	/**
347
	 * @param string $attribute
348
	 *
349
	 * @return string|NULL
350
	 * @throws Exceptions\InvalidStateException
351
	 */
352
	private function getAttribute(string $attribute)
353
	{
354
		// Check if attribute is callable
355 1
		if (is_callable($this->{$attribute})) {
356
			return (string) $this->callCallableAttribute($this->{$attribute});
357
358 1
		} elseif ($this->{$attribute}) {
359 1
			return (string) $this->{$attribute};
360
		}
361
362 1
		return NULL;
363
	}
364
}
365