Completed
Push — master ( 6f2db0...206f52 )
by Pavel
02:40
created

Action::getPropertyStringOrCallableGetString()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 22
rs 8.9197
cc 4
eloc 8
nc 4
nop 3
1
<?php
2
3
/**
4
 * @copyright   Copyright (c) 2015 ublaboo <[email protected]>
5
 * @author      Pavel Janda <[email protected]>
6
 * @package     Ublaboo
7
 */
8
9
namespace Ublaboo\DataGrid\Column;
10
11
use Nette\Utils\Html;
12
use Ublaboo\DataGrid\DataGrid;
13
use Ublaboo\DataGrid\Exception\DataGridHasToBeAttachedToPresenterComponentException;
14
use Ublaboo\DataGrid\Exception\DataGridException;
15
use Ublaboo\DataGrid\Exception\DataGridColumnRendererException;
16
use Ublaboo\DataGrid\Row;
17
use Ublaboo\DataGrid\Traits;
18
19
class Action extends Column
20
{
21
22
	use Traits\ButtonIconTrait;
23
24
	/**
25
	 * @var string|callable
26
	 */
27
	protected $title;
28
29
	/**
30
	 * @var string|callable
31
	 */
32
	protected $class;
33
34
	/**
35
	 * @var string|callable
36
	 */
37
	protected $icon;
38
39
	/**
40
	 * @var DataGrid
41
	 */
42
	protected $grid;
43
44
	/**
45
	 * @var string
46
	 */
47
	protected $href;
48
49
	/**
50
	 * @var string
51
	 */
52
	protected $name;
53
54
	/**
55
	 * @var array
56
	 */
57
	protected $params;
58
59
	/**
60
	 * @var array|callable
61
	 */
62
	protected $confirm;
63
64
	/**
65
	 * @var array
66
	 */
67
	protected $data_attributes = [];
68
69
70
	/**
71
	 * @param DataGrid $grid
72
	 * @param string   $href
73
	 * @param string   $name
74
	 * @param array    $params
75
	 */
76
	public function __construct(DataGrid $grid, $href, $name, $params)
77
	{
78
		$this->grid = $grid;
79
		$this->href = $href;
80
		$this->name = $name;
81
		$this->params = $params;
82
83
		$this->class = 'btn btn-xs btn-default';
84
	}
85
86
87
	/**
88
	 * Render row item into template
89
	 * @param  Row   $row
90
	 * @return mixed
91
	 */
92
	public function render(Row $row)
93
	{
94
		/**
95
		 * Renderer function may be used
96
		 */
97
		try {
98
			return $this->useRenderer($row);
99
		} catch (DataGridColumnRendererException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
100
			/**
101
			 * Do not use renderer
102
			 */
103
		}
104
105
		$link = $this->createLink($this->href, $this->getItemParams($row, $this->params));
106
107
		$a = Html::el('a')->href($link);
108
109
		$this->tryAddIcon($a, $this->getIcon($row), $this->getName());
0 ignored issues
show
Bug introduced by
It seems like $this->getIcon($row) targeting Ublaboo\DataGrid\Column\Action::getIcon() can also be of type callable; however, Ublaboo\DataGrid\Traits\...IconTrait::tryAddIcon() does only seem to accept string|null, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
110
111
		if (!empty($this->data_attributes)) {
112
			foreach ($this->data_attributes as $key => $value) {
113
				$a->data($key, $value);
114
			}
115
		}
116
117
		$a->add($this->translate($this->getName()));
118
119
		if ($this->title) { $a->title($this->translate($this->getTitle($row))); }
0 ignored issues
show
Documentation introduced by
$this->getTitle($row) is of type callable|null, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
120
		if ($this->class) { $a->class($this->getClass($row)); }
121
		if ($confirm = $this->getConfirm($row)) { $a->data('datagrid-confirm', $this->translate($confirm)); }
122
123
		return $a;
124
	}
125
126
127
	/**
128
	 * Set attribute title
129
	 * @param string|callable $title
130
	 * @return static
131
	 * @throws DataGridException
132
	 */
133
	public function setTitle($title)
134
	{
135
		$this->checkPropertyStringOrCallable($title, 'title');
136
137
		$this->title = $title;
138
139
		return $this;
140
	}
141
142
143
	/**
144
	 * Get attribute title
145
	 * @param Row $row
146
	 * @return string
147
	 * @throws DataGridException
148
	 */
149
	public function getTitle(Row $row)
150
	{
151
		/**
152
		 * If user callback was used for setting action title, it has to return string
153
		 */
154
		return $this->getPropertyStringOrCallableGetString($row, $this->title, 'title');
155
	}
156
157
158
	/**
159
	 * Set attribute class
160
	 * @param string|callable $class
161
	 * @return static
162
	 * @throws DataGridException
163
	 */
164
	public function setClass($class)
165
	{
166
		$this->checkPropertyStringOrCallable($class, 'class');
167
168
		$this->class = $class;
169
170
		return $this;
171
	}
172
173
174
	/**
175
	 * Get attribute class
176
	 * @param Row $row
177
	 * @return string
178
	 * @throws DataGridException
179
	 */
180
	public function getClass(Row $row)
181
	{
182
		/**
183
		 * If user callback was used for setting action class, it has to return string
184
		 */
185
		return $this->getPropertyStringOrCallableGetString($row, $this->class, 'class');
186
	}
187
188
189
	/**
190
	 * Set icon
191
	 * @param string|callable $icon
192
	 * @return static|callable
193
	 * @throws DataGridException
194
	 */
195
	public function setIcon($icon)
196
	{
197
		$this->checkPropertyStringOrCallable($icon, 'icon');
198
199
		$this->icon = $icon;
200
201
		return $this;
202
	}
203
204
205
	/**
206
	 * Get icon
207
	 * @param Row $row
208
	 * @return string
209
	 * @throws DataGridException
210
	 */
211
	public function getIcon(Row $row)
212
	{
213
		/**
214
		 * If user callback was used for setting action icon, it has to return string
215
		 */
216
		return $this->getPropertyStringOrCallableGetString($row, $this->icon, 'icon');
217
	}
218
219
220
	/**
221
	 * Set confirm dialog
222
	 * @param string|callable $message
223
	 * @param string $column
224
	 * @return static
225
	 * @throws DataGridException
226
	 */
227
	public function setConfirm($message, $column = NULL)
228
	{
229
		$this->checkPropertyStringOrCallable($message, 'confirmation message');
230
231
		$this->confirm = [$message, $column];
232
233
		return $this;
234
	}
235
236
237
	/**
238
	 * Get confirm dialog for particular row item
239
	 * @param Row $row
240
	 * @return string
241
	 * @throws DataGridException
242
	 */
243
	public function getConfirm(Row $row)
244
	{
245
		if (!$this->confirm) {
246
			return NULL;
247
		}
248
249
		$question = $this->confirm[0];
250
251
		/**
252
		 * If user callback was used for setting action confirmation dialog, it has to return string
253
		 */
254
		$question = $this->getPropertyStringOrCallableGetString($row, $question, 'confirmation dialog');
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->getPropertyString...'confirmation dialog'); of type callable|null adds the type callable to the return on line 257 which is incompatible with the return type documented by Ublaboo\DataGrid\Column\Action::getConfirm of type string.
Loading history...
255
256
		if (!$this->confirm[1]) {
257
			return $question;
258
		}
259
260
		return str_replace('%s', $row->getValue($this->confirm[1]), $question);
261
	}
262
263
264
	/**
265
	 * Setting data attributes
266
	 * @param string $key
267
	 * @param mixed $value
268
	 * @return static
269
	 */
270
	public function setDataAttribute($key, $value)
271
	{
272
		$this->data_attributes[$key] = $value;
273
		
274
		return $this;
275
	}
276
277
278
	/**
279
	 * Check whether given property is string or callable
280
	 * @param  mixed $property
281
	 * @return void
282
	 * @throws DataGridException
283
	 */
284
	protected function checkPropertyStringOrCallable($property, $name)
285
	{
286
		if (!is_string($property) && !is_callable($property) && !is_null($property)) {
287
			throw new DataGridException(
288
				"Action {$name} has to be either string or a callback returning string"
289
			);
290
		}
291
	}
292
293
294
	/**
295
	 * Check whether given property is string or callable
296
	 * 	in that case call callback and check property and return it
297
	 * @param  Row                  $row
298
	 * @param  string|callable|null $property
299
	 * @param  string               $name
300
	 * @return string
301
	 * @throws DataGridException
302
	 */
303
	public function getPropertyStringOrCallableGetString(Row $row, $property, $name)
304
	{
305
		/**
306
		 * String
307
		 */
308
		if (is_string($property)) {
309
			return $property;
310
		}
311
312
		/**
313
		 * Callable
314
		 */
315
		if (is_callable($property)) {
316
			$value = call_user_func($property, $row->getItem());
317
318
			if (!is_string($value)) {
319
				throw new DataGridException("Action {$name} callback has to return a string");
320
			}
321
		}
322
323
		return $property;
324
	}
325
326
327
	/**
328
	 * Translator helper
329
	 * @param  string $message
330
	 * @return string
331
	 */
332
	protected function translate($message)
333
	{
334
		return $this->grid->getTranslator()->translate($message);
335
	}
336
337
}
338