1 <?php
2
3 4 5 6 7 8 9 10
11
12 namespace Grido\Components\Columns;
13
14 use Grido\Helpers;
15
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
35 abstract class Column extends \Grido\Components\Component
36 {
37 const ID = 'columns';
38
39 const VALUE_IDENTIFIER = '%value';
40
41 const ORDER_ASC = 'asc';
42 const ORDER_DESC = 'desc';
43
44
45 protected $sort;
46
47
48 protected $column;
49
50
51 protected $cellPrototype;
52
53
54 protected $cellCallback;
55
56
57 protected $headerPrototype;
58
59
60 protected $customRender;
61
62
63 protected $customRenderVariables = array();
64
65
66 protected $customRenderExport;
67
68
69 protected $sortable = FALSE;
70
71
72 protected $replacements = array();
73
74 75 76 77 78
79 public function __construct($grid, $name, $label)
80 {
81 $this->addComponentToGrid($grid, Helpers::formatColumnName($name));
82
83 $this->type = get_class($this);
84 $this->label = $label;
85 }
86
87 88 89 90
91 public function setSortable($sortable = TRUE)
92 {
93 $this->sortable = (bool) $sortable;
94 return $this;
95 }
96
97 98 99 100
101 public function setReplacement(array $replacement)
102 {
103 $this->replacements = $this->replacements + $replacement;
104 return $this;
105 }
106
107 108 109 110
111 public function setColumn($column)
112 {
113 $this->column = $column;
114 return $this;
115 }
116
117 118 119 120
121 public function setDefaultSort($dir)
122 {
123 $this->grid->setDefaultSort(array($this->getName() => $dir));
124 return $this;
125 }
126
127 128 129 130 131
132 public function setCustomRender($callback, $variables = array())
133 {
134 $this->customRender = $callback;
135 $this->customRenderVariables = $variables;
136
137 return $this;
138 }
139
140 141 142 143
144 public function setCustomRenderExport($callback)
145 {
146 $this->customRenderExport = $callback;
147 return $this;
148 }
149
150 151 152 153
154 public function setCellCallback($callback)
155 {
156 $this->cellCallback = $callback;
157 return $this;
158 }
159
160
161
162 163 164 165 166
167 public function getCellPrototype($row = NULL)
168 {
169 $td = $this->cellPrototype;
170
171 if ($td === NULL) {
172 $td = $this->cellPrototype = \Nette\Utils\Html::el('td')
173 ->setClass(array('grid-cell-' . $this->getName()));
174 }
175
176 if ($this->cellCallback && $row !== NULL) {
177 $td = clone $td;
178 $td = callback($this->cellCallback)->invokeArgs(array($row, $td));
179 }
180
181 return $td;
182 }
183
184 185 186 187
188 public function getHeaderPrototype()
189 {
190 if ($this->headerPrototype === NULL) {
191 $this->headerPrototype = \Nette\Utils\Html::el('th')
192 ->setClass(array('column', 'grid-header-' . $this->getName()));
193 }
194
195 if ($this->isSortable() && $this->getSort()) {
196 $this->headerPrototype->class[] = $this->getSort() == self::ORDER_DESC
197 ? 'desc'
198 : 'asc';
199 }
200
201 return $this->headerPrototype;
202 }
203
204 205 206 207
208 public function getColumn()
209 {
210 return $this->column ? $this->column : $this->getName();
211 }
212
213 214 215 216
217 public function getSort()
218 {
219 if ($this->sort === NULL) {
220 $name = $this->getName();
221
222 $sort = isset($this->grid->sort[$name])
223 ? $this->grid->sort[$name]
224 : NULL;
225
226 $this->sort = $sort === NULL ? NULL : $sort;
227 }
228
229 return $this->sort;
230 }
231
232 233 234 235
236 public function getCustomRender()
237 {
238 return $this->customRender;
239 }
240
241 242 243 244
245 public function getCustomRenderVariables()
246 {
247 return $this->customRenderVariables;
248 }
249
250 251 252 253
254 public function getLabel()
255 {
256 return is_string($this->label)
257 ? $this->translate($this->label)
258 : $this->label;
259 }
260
261
262
263 264 265 266
267 public function isSortable()
268 {
269 return $this->sortable;
270 }
271
272 273 274 275
276 public function hasFilter()
277 {
278 return (bool) $this->grid->getFilter($this->getName(), FALSE);
279 }
280
281
282
283 284 285 286 287
288 public function render($row)
289 {
290 if (is_callable($this->customRender)) {
291 return callback($this->customRender)->invokeArgs(array($row));
292 }
293
294 $value = $this->getValue($row);
295 return $this->formatValue($value);
296 }
297
298 299 300 301 302
303 public function renderExport($row)
304 {
305 if (is_callable($this->customRenderExport)) {
306 return callback($this->customRenderExport)->invokeArgs(array($row));
307 }
308
309 $value = $this->getValue($row);
310 return strip_tags($this->applyReplacement($value));
311 }
312
313 314 315 316 317
318 protected function getValue($row)
319 {
320 $column = $this->getColumn();
321 if (is_string($column)) {
322 return $this->propertyAccessor->getProperty($row, Helpers::unformatColumnName($column));
323
324 } elseif (is_callable($column)) {
325 return callback($column)->invokeArgs(array($row));
326
327 } else {
328 throw new \InvalidArgumentException('Column must be string or callback.');
329 }
330 }
331
332 333 334 335
336 protected function applyReplacement($value)
337 {
338 return (is_scalar($value) || $value === NULL) && isset($this->replacements[$value])
339 ? is_string($value)
340 ? str_replace(static::VALUE_IDENTIFIER, $value, $this->replacements[$value])
341 : $this->replacements[$value]
342 : $value;
343 }
344
345 346 347 348
349 protected function formatValue($value)
350 {
351 $value = is_string($value)
352 ? \Nette\Templating\Helpers::escapeHtml($value)
353 : $value;
354
355 return $this->applyReplacement($value);
356 }
357
358
359
360 361 362
363 public function setFilterText()
364 {
365 return $this->grid->addFilterText($this->getName(), $this->label);
366 }
367
368 369 370
371 public function setFilterDate()
372 {
373 return $this->grid->addFilterDate($this->getName(), $this->label);
374 }
375
376 377 378
379 public function setFilterDateRange()
380 {
381 return $this->grid->addFilterDateRange($this->getName(), $this->label);
382 }
383
384 385 386
387 public function setFilterCheck()
388 {
389 return $this->grid->addFilterCheck($this->getName(), $this->label);
390 }
391
392 393 394 395
396 public function setFilterSelect(array $items = NULL)
397 {
398 return $this->grid->addFilterSelect($this->getName(), $this->label, $items);
399 }
400
401 402 403
404 public function setFilterNumber()
405 {
406 return $this->grid->addFilterNumber($this->getName(), $this->label);
407 }
408
409 410 411 412
413 public function setFilterCustom(\Nette\Forms\IControl $formControl)
414 {
415 return $this->grid->addFilterCustom($this->getName(), $formControl);
416 }
417 }
418