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

Confirmer::render()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 29
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 4.0058

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 13
cts 14
cp 0.9286
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 15
nc 4
nop 0
crap 4.0058
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
use Nette\Forms;
22
use Nette\Localization;
23
24
use IPub;
25
use IPub\ConfirmationDialog;
26
use IPub\ConfirmationDialog\Exceptions;
27
28
/**
29
 * Confirmation dialog confirmer control
30
 *
31
 * @package        iPublikuj:ConfirmationDialog!
32
 * @subpackage     Components
33
 *
34
 * @author         Adam Kadlec <[email protected]>
35
 *
36
 * @property-read string $name
37
 * @property-read string $cssClass
38
 * @property-read string $useAjax
39
 */
40 1
final class Confirmer extends ConfirmerAttributes
41
{
42
	/**
43
	 * @var Control|Nette\ComponentModel\IContainer
44
	 */
45
	private $dialog;
46
47
	/**
48
	 * @param NULL|string $templateFile
49
	 */
50
	public function __construct(string $templateFile = NULL)
51
	{
52 1
		list(, $parent, $name) = func_get_args() + [NULL, NULL, NULL];
53
54 1
		parent::__construct($parent, $name);
55
56 1
		if ($templateFile !== NULL) {
57
			$this->setTemplateFile($templateFile);
58
		}
59 1
	}
60
61
	/**
62
	 * Show current confirmer
63
	 *
64
	 * @param array $params
65
	 * 
66
	 * @return void
67
	 */
68
	public function showConfirm(array $params = [])
69
	{
70
		// Generate protection token
71 1
		$token = $this->generateToken();
72
73
		// Set generated token to form
74 1
		$this['form']['secureToken']->value = $token;
75
76
		// Store token to storage
77 1
		$this->storage->set($token, [
78 1
			'confirmer' => $this->getName(),
79 1
			'params'    => $params,
80
		]);
81
82 1
		if ($this->getQuestion() !== FALSE) {
83
			// Invalidate confirmer snippets
84 1
			$this->redrawControl();
85
			// Invalidate dialog snippets
86 1
			$this->getDialog()->redrawControl();
87
		}
88 1
	}
89
90
	/**
91
	 * Confirm YES clicked
92
	 *
93
	 * @param Forms\Controls\SubmitButton $button
94
	 * 
95
	 * @return void
96
	 *
97
	 * @throws Exceptions\HandlerNotCallableException
98
	 * @throws Exceptions\InvalidStateException
99
	 */
100
	public function confirmClicked(Forms\Controls\SubmitButton $button)
101
	{
102
		// Get submitted values from form
103 1
		$values = $button->getForm(TRUE)->getValues();
104
105
		// Get token from post
106 1
		$token = $values->secureToken;
107
108
		try {
109
			// Get values stored in confirmer storage
110 1
			$values = $this->getConfirmerValues($token);
111
			// Remove storage data for current confirmer
112 1
			$this->storage->clear($token);
113
114 1
			$this->getDialog()->resetConfirmer();
115
116 1
			$control = $this->getDialog()->getParent();
117
118 1
			if ($control === NULL) {
119
				throw new Exceptions\InvalidStateException('Confirmer is not attached to parent control.');
120
			}
121
122 1
			$this->callHandler($control, $values['params']);
123
124 1
		} catch (Exceptions\InvalidStateException $ex) {
125
			if (self::$strings['expired'] != '' && $this->getPresenter() instanceof Application\UI\Presenter) {
126
				$this->getPresenter()->flashMessage(self::$strings['expired']);
127
128
			} else {
129
				throw $ex;
130
			}
131
		}
132
133
		$this->refreshPage();
134
	}
135
136
	/**
137
	 * Confirm NO clicked
138
	 * 
139
	 * @return void
140
	 *
141
	 * @param Forms\Controls\SubmitButton $button
142
	 */
143
	public function cancelClicked(Forms\Controls\SubmitButton $button)
144
	{
145
		// Get submitted values from form
146 1
		$values = $button->getForm(TRUE)->getValues();
147
148
		// Get token from post
149 1
		$token = $values->secureToken;
150
151 1
		if ($this->getConfirmerValues($token)) {
152 1
			$this->storage->clear($token);
153
		}
154
155 1
		$this->getDialog()->resetConfirmer();
156
157 1
		$this->refreshPage();
158
	}
159
160
	/**
161
	 * Check if confirmer is fully configured
162
	 *
163
	 * @return bool
164
	 */
165
	public function isConfigured() : bool
166
	{
167 1
		if ((is_string($this->heading) || is_callable($this->heading)) &&
168 1
			(is_string($this->question) || is_callable($this->question)) &&
169 1
			is_callable($this->handler)
170
		) {
171 1
			return TRUE;
172
		}
173
174 1
		return FALSE;
175
	}
176
177
	/**
178
	 * Render confirmer
179
	 * 
180
	 * @return void
181
	 *
182
	 * @throws Exceptions\InvalidStateException
183
	 */
184
	public function render()
185
	{
186
		// Create template
187 1
		$template = parent::render();
188
189
		// Check if control has template
190 1
		if ($template instanceof Nette\Bridges\ApplicationLatte\Template) {
191
			// Assign vars to template
192 1
			$template->add('name', $this->name);
193 1
			$template->add('class', $this->cssClass);
194 1
			$template->add('icon', $this->getIcon());
195 1
			$template->add('question', $this->getQuestion());
196 1
			$template->add('heading', $this->getHeading());
197 1
			$template->add('useAjax', $this->useAjax);
198
199
			// If template was not defined before...
200 1
			if ($template->getFile() === NULL) {
201
				// ...try to get base component template file
202 1
				$templateFile = !empty($this->templateFile) ? $this->templateFile : $this->getDialog()->getTemplateFile();
203 1
				$template->setFile($templateFile);
204
			}
205
206
			// Render component template
207 1
			$template->render();
208
209
		} else {
210
			throw new Exceptions\InvalidStateException('Confirmer control is without template.');
211
		}
212 1
	}
213
214
	/**
215
	 * Change default confirmer template path
216
	 *
217
	 * @param string $layoutFile
218
	 * 
219
	 * @return void
220
	 */
221
	public function setTemplateFile(string $layoutFile)
222
	{
223
		$this->setTemplateFilePath($layoutFile, self::TEMPLATE_CONFIRMER);
224
	}
225
226
	/**
227
	 * Get parent dialog control
228
	 *
229
	 * @return Control
230
	 *
231
	 * @throws Exceptions\InvalidStateException
232
	 */
233
	protected function getDialog() : Control
234
	{
235
		// Check if confirm dialog was loaded before...
236 1
		if (!$this->dialog) {
237
			// ...if not try to lookup for it
238 1
			$multiplier = $this->getParent();
239
240
			// Check if confirmer is in multiplier
241 1
			if ($multiplier instanceof Application\UI\Multiplier) {
242 1
				$this->dialog = $multiplier->getParent();
243
244
				// Check if parent is right
245 1
				if (!$this->dialog instanceof Control) {
246 1
					throw new Exceptions\InvalidStateException('Confirmer is not attached to parent control!');
247
				}
248
249
			} else {
250
				throw new Exceptions\InvalidStateException('Confirmer is not attached to multiplier!');
251
			}
252
		}
253
254 1
		return $this->dialog;
255
	}
256
257
	/**
258
	 * Generate unique token key
259
	 *
260
	 * @return string
261
	 */
262
	private function generateToken() : string
263
	{
264 1
		return base_convert(md5(uniqid('confirm' . $this->getName(), TRUE)), 16, 36);
265
	}
266
267
	/**
268
	 * @return void
269
	 */
270
	private function refreshPage()
271
	{
272
		// Check if request is done via ajax...
273 1
		if ($this->getPresenter() instanceof Application\UI\Presenter && !$this->getPresenter()->isAjax()) {
274
			// ...if not redirect to actual page
275 1
			$this->getPresenter()->redirect('this');
276
		}
277
	}
278
}
279