ConfirmerAttributes   A
last analyzed

Complexity

Total Complexity 39

Size/Duplication

Total Lines 327
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 67.68%

Importance

Changes 0
Metric Value
wmc 39
lcom 1
cbo 8
dl 0
loc 327
ccs 44
cts 65
cp 0.6768
rs 9.28
c 0
b 0
f 0

17 Methods

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