Completed
Push — master ( b57c0a...d441ef )
by Adam
02:49 queued 14s
created

ConfirmerAttributes::setHandler()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
ccs 3
cts 4
cp 0.75
rs 9.6666
cc 2
eloc 4
nc 2
nop 1
crap 2.0625
1
<?php
2
/**
3
 * Confirmer.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
 * @property-read string $name
34
 */
35 1
abstract class ConfirmerAttributes extends BaseControl
36
{
37
	/**
38
	 * @var array localization strings
39
	 */
40
	public static $strings = [
41
		'yes'     => 'Yes',
42
		'no'      => 'No',
43
		'expired' => 'Confirmation token has expired. Please try action again.',
44
	];
45
46
	/**
47
	 * @var string
48
	 */
49
	protected $cssClass;
50
51
	/**
52
	 * @var string|callable heading
53
	 */
54
	protected $heading;
55
56
	/**
57
	 * @var string|callable question
58
	 */
59
	protected $question;
60
61
	/**
62
	 * @var string|callable icon
63
	 */
64
	protected $icon;
65
66
	/**
67
	 * @var callable
68
	 */
69
	protected $handler;
70
71
	/**
72
	 * @var bool
73
	 */
74
	protected $useAjax = TRUE;
75
76
	/**
77
	 * @var Storage\IStorage
78
	 */
79
	protected $storage;
80
81
	/**
82
	 * @param Storage\IStorage $storage
83
	 */
84
	public function injectStorage(Storage\IStorage $storage)
85
	{
86
		// Get data storage for confirmer
87 1
		$this->storage = $storage;
88 1
	}
89
90
	/**
91
	 * Set dialog heading
92
	 *
93
	 * @param string|callable $heading
94
	 *
95
	 * @return void
96
	 *
97
	 * @throws Exceptions\InvalidArgumentException
98
	 */
99
	public function setHeading($heading)
100
	{
101
		// Check variable type
102 1
		if ($this->checkCallableOrString($heading)) {
103
			// Update confirmation heading
104 1
			$this->heading = $heading;
105
		}
106 1
	}
107
108
	/**
109
	 * Get dialog heding
110
	 *
111
	 * @return string|NULL
112
	 *
113
	 * @throws Exceptions\InvalidStateException
114
	 */
115 View Code Duplication
	public function getHeading()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
116
	{
117
		// Check if attribute is callable
118 1
		if (is_callable($this->heading)) {
119
			return (string) $this->callCallableAttribute($this->heading);
120
121 1
		} elseif ($this->heading) {
122 1
			return (string) $this->heading;
123
		}
124
125
		return NULL;
126
	}
127
128
	/**
129
	 * Set dialog question
130
	 *
131
	 * @param string|callable $question
132
	 *
133
	 * @return void
134
	 *
135
	 * @throws Exceptions\InvalidArgumentException
136
	 */
137
	public function setQuestion($question)
138
	{
139
		// Check variable type
140 1
		if ($this->checkCallableOrString($question)) {
141
			// Update confirmation question
142 1
			$this->question = $question;
143
		}
144 1
	}
145
146
	/**
147
	 * @return string|bool
148
	 *
149
	 * @throws Exceptions\InvalidStateException
150
	 */
151
	public function getQuestion()
152
	{
153 1
		$question = FALSE;
154
155
		// Check if attribute is callable
156 1
		if (is_callable($this->question)) {
157
			$question = $this->callCallableAttribute($this->question);
158
159
			if (!is_bool($question)) {
160
				$question = (string) $question;
161
			}
162
163 1
		} elseif (!is_bool($this->question)) {
164 1
			$question = (string) $this->question;
165
		}
166
167 1
		return $question;
168
	}
169
170
	/**
171
	 * Set dialog icon
172
	 *
173
	 * @param string|callable $icon
174
	 *
175
	 * @return void
176
	 *
177
	 * @throws Exceptions\InvalidArgumentException
178
	 */
179
	public function setIcon($icon)
180
	{
181
		// Check variable type
182
		if ($this->checkCallableOrString($icon)) {
183
			// Update confirmation icon
184
			$this->icon = $icon;
185
		}
186
	}
187
188
	/**
189
	 * @return string|NULL
190
	 *
191
	 * @throws Exceptions\InvalidStateException
192
	 */
193 View Code Duplication
	public function getIcon()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
194
	{
195
		// Check if attribute is callable
196 1
		if (is_callable($this->icon)) {
197
			return (string) $this->callCallableAttribute($this->icon);
198
199 1
		} elseif ($this->icon) {
200
			return (string) $this->icon;
201
		}
202
203 1
		return NULL;
204
	}
205
206
	/**
207
	 * Set dialog handler
208
	 *
209
	 * @param callable $handler
210
	 *
211
	 * @return void
212
	 *
213
	 * @throws Exceptions\InvalidArgumentException
214
	 */
215
	public function setHandler($handler)
216
	{
217 1
		if (!is_callable($handler)) {
218
			throw new Exceptions\InvalidArgumentException('$handler must be callable.');
219
		}
220
221
		// Update confirmation handler
222 1
		$this->handler = $handler;
223 1
	}
224
225
	/**
226
	 * @return callable
227
	 */
228
	public function getHandler() : callable
229
	{
230 1
		return $this->handler;
231
	}
232
233
	/**
234
	 * @param Nette\ComponentModel\IContainer $obj
235
	 * @param array $params
236
	 *
237
	 * @return mixed
238
	 *
239
	 * @throws Exceptions\HandlerNotCallableException
240
	 */
241
	public function callHandler(Nette\ComponentModel\IContainer $obj, array $params)
242
	{
243 1
		$callback = $this->getHandler();
244
245 1
		if ($callback instanceof \Closure) {
246
			$result = call_user_func_array($callback, $params);
247
248 1
		} elseif (method_exists($obj, 'tryCall')) {
249 1
			$result = call_user_func_array([$obj, 'tryCall'], ['method' => $callback[1], 'params' => $params]);
250
251
		} else {
252
			$result = call_user_func_array([$obj, $callback[1]], $params);
253
		}
254
255
		if ($result === FALSE) {
256
			throw new Exceptions\HandlerNotCallableException('Confirm action callback was not successful.');
257
		}
258
259
		return $result;
260
	}
261
262
	/**
263
	 * @return void
264
	 */
265
	public function enableAjax()
266
	{
267 1
		$this->useAjax = TRUE;
268 1
	}
269
270
	/**
271
	 * @return void
272
	 */
273
	public function disableAjax()
274
	{
275
		$this->useAjax = FALSE;
276
	}
277
278
	/**
279
	 * @return Application\UI\Form
280
	 */
281
	protected function createComponentForm()
282
	{
283
		// Create confirmation form
284 1
		$form = new Application\UI\Form();
285
286
		// Security field
287 1
		$form->addHidden('secureToken');
288
289
		// Form protection
290 1
		$form->addProtection($this->translator ? $this->translator->translate('confirmationDialog.messages.tokenIsExpired') : self::$strings['expired']);
291
292
		// Confirm buttons
293 1
		$form->addSubmit('yes', $this->translator ? $this->translator->translate('confirmationDialog.buttons.bYes') : self::$strings['yes'])
294 1
			->onClick[] = [$this, 'confirmClicked'];
295
296 1
		$form->addSubmit('no', $this->translator ? $this->translator->translate('confirmationDialog.buttons.bNo') : self::$strings['no'])
297 1
			->onClick[] = [$this, 'cancelClicked'];
298
299 1
		return $form;
300
	}
301
302
	/**
303
	 * @param callable|string $var
304
	 *
305
	 * @return bool
306
	 *
307
	 * @throws Exceptions\InvalidArgumentException
308
	 */
309
	protected function checkCallableOrString($var) : bool
310
	{
311 1
		if (!is_callable($var) && !is_string($var)) {
312
			throw new Exceptions\InvalidArgumentException(sprintf('%s must be callback or string.', $var));
313
		}
314
315 1
		return TRUE;
316
	}
317
318
	/**
319
	 * @param callable $attribute
320
	 *
321
	 * @return string
322
	 *
323
	 * @throws Exceptions\InvalidStateException
324
	 */
325
	protected function callCallableAttribute($attribute) : string
326
	{
327
		if ($this['form']['secureToken']->value === NULL) {
328
			throw new Exceptions\InvalidStateException('Token is not set!');
329
		}
330
331
		// Get token from form
332
		$token = $this['form']['secureToken']->value;
333
334
		// Get values stored in confirmer storage
335
		$values = $this->getConfirmerValues($token);
336
337
		return call_user_func_array($attribute, [$this, $values['params']]);
338
	}
339
340
	/**
341
	 * @param string $token
342
	 *
343
	 * @return array
344
	 *
345
	 * @throws Exceptions\InvalidStateException
346
	 */
347
	protected function getConfirmerValues(string $token) : array
348
	{
349
		// Get values stored in confirmer storage
350 1
		$values = $this->storage->get($token);
351
352
		// Check for correct values
353 1
		if (!is_array($values) || !isset($values['confirmer']) || !isset($values['params'])) {
354
			throw new Exceptions\InvalidStateException('Confirmer is not configured!');
355
		}
356
357 1
		return $values;
358
	}
359
}
360