Completed
Push — master ( d441ef...56480f )
by Adam
03:05
created

ConfirmerAttributes::getAttribute()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3.072

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 12
ccs 4
cts 5
cp 0.8
rs 9.4285
cc 3
eloc 6
nc 3
nop 1
crap 3.072
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
	public function getHeading()
116
	{
117 1
		return $this->getAttribute('heading');
118
	}
119
120
	/**
121
	 * Set dialog question
122
	 *
123
	 * @param string|callable $question
124
	 *
125
	 * @return void
126
	 *
127
	 * @throws Exceptions\InvalidArgumentException
128
	 */
129
	public function setQuestion($question)
130
	{
131
		// Check variable type
132 1
		if ($this->checkCallableOrString($question)) {
133
			// Update confirmation question
134 1
			$this->question = $question;
135
		}
136 1
	}
137
138
	/**
139
	 * @return string|bool
140
	 *
141
	 * @throws Exceptions\InvalidStateException
142
	 */
143
	public function getQuestion()
144
	{
145 1
		$question = FALSE;
146
147
		// Check if attribute is callable
148 1
		if (is_callable($this->question)) {
149
			$question = $this->callCallableAttribute($this->question);
150
151
			if (!is_bool($question)) {
152
				$question = (string) $question;
153
			}
154
155 1
		} elseif (!is_bool($this->question)) {
156 1
			$question = (string) $this->question;
157
		}
158
159 1
		return $question;
160
	}
161
162
	/**
163
	 * Set dialog icon
164
	 *
165
	 * @param string|callable $icon
166
	 *
167
	 * @return void
168
	 *
169
	 * @throws Exceptions\InvalidArgumentException
170
	 */
171
	public function setIcon($icon)
172
	{
173
		// Check variable type
174
		if ($this->checkCallableOrString($icon)) {
175
			// Update confirmation icon
176
			$this->icon = $icon;
177
		}
178
	}
179
180
	/**
181
	 * @return string|NULL
182
	 *
183
	 * @throws Exceptions\InvalidStateException
184
	 */
185
	public function getIcon()
186
	{
187 1
		return $this->getAttribute('icon');
188
	}
189
190
	/**
191
	 * Set dialog handler
192
	 *
193
	 * @param callable $handler
194
	 *
195
	 * @return void
196
	 *
197
	 * @throws Exceptions\InvalidArgumentException
198
	 */
199
	public function setHandler($handler)
200
	{
201 1
		if (!is_callable($handler)) {
202
			throw new Exceptions\InvalidArgumentException('$handler must be callable.');
203
		}
204
205
		// Update confirmation handler
206 1
		$this->handler = $handler;
207 1
	}
208
209
	/**
210
	 * @return callable
211
	 */
212
	public function getHandler() : callable
213
	{
214 1
		return $this->handler;
215
	}
216
217
	/**
218
	 * @param Nette\ComponentModel\IContainer $obj
219
	 * @param array $params
220
	 *
221
	 * @return mixed
222
	 *
223
	 * @throws Exceptions\HandlerNotCallableException
224
	 */
225
	public function callHandler(Nette\ComponentModel\IContainer $obj, array $params)
226
	{
227 1
		$callback = $this->getHandler();
228
229 1
		if ($callback instanceof \Closure) {
230
			$result = call_user_func_array($callback, $params);
231
232 1
		} elseif (method_exists($obj, 'tryCall')) {
233 1
			$result = call_user_func_array([$obj, 'tryCall'], ['method' => $callback[1], 'params' => $params]);
234
235
		} else {
236
			$result = call_user_func_array([$obj, $callback[1]], $params);
237
		}
238
239
		if ($result === FALSE) {
240
			throw new Exceptions\HandlerNotCallableException('Confirm action callback was not successful.');
241
		}
242
243
		return $result;
244
	}
245
246
	/**
247
	 * @return void
248
	 */
249
	public function enableAjax()
250
	{
251 1
		$this->useAjax = TRUE;
252 1
	}
253
254
	/**
255
	 * @return void
256
	 */
257
	public function disableAjax()
258
	{
259
		$this->useAjax = FALSE;
260
	}
261
262
	/**
263
	 * @return Application\UI\Form
264
	 */
265
	protected function createComponentForm()
266
	{
267
		// Create confirmation form
268 1
		$form = new Application\UI\Form();
269
270
		// Security field
271 1
		$form->addHidden('secureToken');
272
273
		// Form protection
274 1
		$form->addProtection($this->translator ? $this->translator->translate('confirmationDialog.messages.tokenIsExpired') : self::$strings['expired']);
275
276
		// Confirm buttons
277 1
		$form->addSubmit('yes', $this->translator ? $this->translator->translate('confirmationDialog.buttons.bYes') : self::$strings['yes'])
278 1
			->onClick[] = [$this, 'confirmClicked'];
279
280 1
		$form->addSubmit('no', $this->translator ? $this->translator->translate('confirmationDialog.buttons.bNo') : self::$strings['no'])
281 1
			->onClick[] = [$this, 'cancelClicked'];
282
283 1
		return $form;
284
	}
285
286
	/**
287
	 * @param callable|string $var
288
	 *
289
	 * @return bool
290
	 *
291
	 * @throws Exceptions\InvalidArgumentException
292
	 */
293
	protected function checkCallableOrString($var) : bool
294
	{
295 1
		if (!is_callable($var) && !is_string($var)) {
296
			throw new Exceptions\InvalidArgumentException(sprintf('%s must be callback or string.', $var));
297
		}
298
299 1
		return TRUE;
300
	}
301
302
	/**
303
	 * @param callable $attribute
304
	 *
305
	 * @return string
306
	 *
307
	 * @throws Exceptions\InvalidStateException
308
	 */
309
	protected function callCallableAttribute($attribute) : string
310
	{
311
		if ($this['form']['secureToken']->value === NULL) {
312
			throw new Exceptions\InvalidStateException('Token is not set!');
313
		}
314
315
		// Get token from form
316
		$token = $this['form']['secureToken']->value;
317
318
		// Get values stored in confirmer storage
319
		$values = $this->getConfirmerValues($token);
320
321
		return call_user_func_array($attribute, [$this, $values['params']]);
322
	}
323
324
	/**
325
	 * @param string $token
326
	 *
327
	 * @return array
328
	 *
329
	 * @throws Exceptions\InvalidStateException
330
	 */
331
	protected function getConfirmerValues(string $token) : array
332
	{
333
		// Get values stored in confirmer storage
334 1
		$values = $this->storage->get($token);
335
336
		// Check for correct values
337 1
		if (!is_array($values) || !isset($values['confirmer']) || !isset($values['params'])) {
338
			throw new Exceptions\InvalidStateException('Confirmer is not configured!');
339
		}
340
341 1
		return $values;
342
	}
343
344
	/**
345
	 * @param string $attribute
346
	 *
347
	 * @return string|NULL
348
	 * @throws Exceptions\InvalidStateException
349
	 */
350
	private function getAttribute(string $attribute)
351
	{
352
		// Check if attribute is callable
353 1
		if (is_callable($this->{$attribute})) {
354
			return (string) $this->callCallableAttribute($this->{$attribute});
355
356 1
		} elseif ($this->{$attribute}) {
357 1
			return (string) $this->{$attribute};
358
		}
359
360 1
		return NULL;
361
	}
362
}
363