Completed
Push — master ( d2ee45...5d494d )
by Adam
04:50 queued 02:51
created

ConfirmerAttributes::getHeading()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 1
cts 1
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
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 injectStorage(Storage\IStorage $storage)
87
	{
88
		// Get data storage for confirmer
89 1
		$this->storage = $storage;
90 1
	}
91
92
	/**
93
	 * Set dialog heading
94
	 *
95
	 * @param string|callable $heading
96
	 *
97
	 * @return void
98
	 *
99
	 * @throws Exceptions\InvalidArgumentException
100
	 */
101
	public function setHeading($heading)
102
	{
103
		// Check variable type
104 1
		if ($this->checkCallableOrString($heading)) {
105
			// Update confirmation heading
106 1
			$this->heading = $heading;
107
		}
108 1
	}
109
110
	/**
111
	 * Get dialog heding
112
	 *
113
	 * @return string|NULL
114
	 *
115
	 * @throws Exceptions\InvalidStateException
116
	 */
117
	public function getHeading()
118
	{
119 1
		return $this->getAttribute('heading');
120
	}
121
122
	/**
123
	 * Set dialog question
124
	 *
125
	 * @param string|callable $question
126
	 *
127
	 * @return void
128
	 *
129
	 * @throws Exceptions\InvalidArgumentException
130
	 */
131
	public function setQuestion($question)
132
	{
133
		// Check variable type
134 1
		if ($this->checkCallableOrString($question)) {
135
			// Update confirmation question
136 1
			$this->question = $question;
137
		}
138 1
	}
139
140
	/**
141
	 * @return string|bool
142
	 *
143
	 * @throws Exceptions\InvalidStateException
144
	 */
145
	public function getQuestion()
146
	{
147 1
		$question = FALSE;
148
149
		// Check if attribute is callable
150 1
		if (is_callable($this->question)) {
151
			$question = $this->callCallableAttribute($this->question);
152
153
			if (!is_bool($question)) {
154
				$question = (string) $question;
155
			}
156
157 1
		} elseif (!is_bool($this->question)) {
158 1
			$question = (string) $this->question;
159
		}
160
161 1
		return $question;
162
	}
163
164
	/**
165
	 * Set dialog icon
166
	 *
167
	 * @param string|callable $icon
168
	 *
169
	 * @return void
170
	 *
171
	 * @throws Exceptions\InvalidArgumentException
172
	 */
173
	public function setIcon($icon)
174
	{
175
		// Check variable type
176
		if ($this->checkCallableOrString($icon)) {
177
			// Update confirmation icon
178
			$this->icon = $icon;
179
		}
180
	}
181
182
	/**
183
	 * @return string|NULL
184
	 *
185
	 * @throws Exceptions\InvalidStateException
186
	 */
187
	public function getIcon()
188
	{
189 1
		return $this->getAttribute('icon');
190
	}
191
192
	/**
193
	 * Set dialog handler
194
	 *
195
	 * @param callable $handler
196
	 *
197
	 * @return void
198
	 *
199
	 * @throws Exceptions\InvalidArgumentException
200
	 */
201
	public function setHandler($handler)
202
	{
203 1
		if (!is_callable($handler)) {
204
			throw new Exceptions\InvalidArgumentException('$handler must be callable.');
205
		}
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()
252
	{
253 1
		$this->useAjax = TRUE;
254 1
	}
255
256
	/**
257
	 * @return void
258
	 */
259
	public function disableAjax()
260
	{
261
		$this->useAjax = FALSE;
262
	}
263
264
	/**
265
	 * @return Application\UI\Form
266
	 */
267
	protected function createComponentForm()
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($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