Column   F
last analyzed

Complexity

Total Complexity 107

Size/Duplication

Total Lines 776
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 107
eloc 224
dl 0
loc 776
rs 2
c 0
b 0
f 0
ccs 0
cts 419
cp 0

57 Methods

Rating   Name   Duplication   Size   Complexity  
A getVisible() 0 3 1
A __construct() 0 11 3
A setWidth() 0 4 1
A getWidth() 0 3 1
A setHeaderCellAttributes() 0 4 1
A setEmptyCellDisplay() 0 4 1
A getFilter() 0 3 1
A setVisible() 0 4 1
A width() 0 3 1
A getEmptyCellDisplay() 0 5 2
A setMember() 0 3 1
A setKey() 0 4 1
A getMember() 0 3 1
A setGrid() 0 4 1
A setFilter() 0 4 1
A getKey() 0 3 1
A getHeaderCellAttributes() 0 3 1
A renderHeaderCell() 0 10 4
A callFunction() 0 6 2
A hasRequestData() 0 4 1
A renderFilterCellContent() 0 10 3
B renderRowActions() 0 26 7
A setDbField() 0 3 1
A renderFilterCell() 0 10 3
A setTitle() 0 4 1
A setHeaderStyle() 0 4 1
A highlight() 0 3 1
A setFilterFieldConfig() 0 4 1
A setDataCellContentFunction() 0 4 1
A addRowAction() 0 7 1
A getGrid() 0 3 1
A setAsIndex() 0 12 3
A processSearch() 0 6 2
A getDbSortField() 0 6 2
A setMemberConfig() 0 7 3
A getFilterField() 0 6 2
A getDataCellContentFunction() 0 13 4
A renderDataCellContent() 0 14 5
A getIsSortable() 0 3 1
A renderDataCell() 0 8 1
A processSort() 0 4 2
A addRowActionLink() 0 5 1
A getSearchFunction() 0 9 3
A getFieldName() 0 3 1
A setIsSortable() 0 4 1
A getDataCellOptions() 0 7 2
A getDbField() 0 6 2
A getCellData() 0 10 2
A renderHeaderCellContent() 0 11 5
A setSearchFunction() 0 4 1
A getBaseFilterField() 0 6 2
A prepareDisplay() 0 12 4
A getSearch() 0 8 2
A getTitle() 0 7 2
A callRenderDataCellContentFunction() 0 10 3
A setDbSortField() 0 3 1
A callSearchFunction() 0 6 2

How to fix   Complexity   

Complex Class

Complex classes like Column often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Column, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @link http://www.newicon.net/
4
 * @copyright Copyright (c) 2018 Newicon Ltd
5
 * @license http://www.newicon.net/neon/framework/license/
6
 * @author Steve O'Brien <[email protected]>
7
 * @date 1/1/2018 16:13
8
 */
9
10
namespace neon\core\grid\column;
11
12
use neon\core\form\interfaces\IField;
13
use neon\core\helpers\Arr;
14
use \yii\base\Component;
15
use \neon\core\grid\Grid;
16
use yii\data\ActiveDataProvider;
17
use \yii\helpers\Inflector;
18
use \yii\helpers\ArrayHelper;
19
use \neon\core\helpers\Html;
20
use \neon\core\grid\query\IQuery;
21
22
/**
23
 * Class Column
24
 * A grid is made of columns which in turn has a header, filter, and data cells
25
 * for each row of data.  Columns are associated with a form field which is used
26
 * both for filtering and helping to draw the cell data.
27
 *
28
 * @package neon\grid\column
29
 *
30
 * @property string $key readonly
31
 * @property \neon\core\grid\Grid $grid readonly
32
 * @property boolean $searchable
33
 * @property string $title
34
 * @property string $dbField - set this is the database field is different to $key
35
 * @property string $dbSortField - set this for sorting if the sort field is different to $dbField
36
 * @property string $emptyCellDisplay - @see getEmptyCellDisplay - string to display when cell content is empty
37
 * @property IField $member - the corresponding form field component
38
 */
39
class Column extends Component implements IColumn
40
{
41
42
	/**
43
	 * @var \neon\core\form\interfaces\IField
44
	 */
45
	private $_member = null;
46
47
	/**
48
	 * Get the form field used to handle the grid columns data
49
	 * Note: member refers to the name of the form field configuration for the column and not necessarily
50
	 * a daedalus member
51
	 * @param IField $member
52
	 */
53
	public function setMember(IField $member)
54
	{
55
		$this->_member = $member;
56
	}
57
58
	/**
59
	 * Get the form field member used to handle the columns data, filters, and grid output.
60
	 * Note: member refers to the name of the form field configuration for the column and not necessarily
61
	 * a daedalus member
62
	 * @return IField|null
63
	 */
64
	public function getMember()
65
	{
66
		return $this->_member;
67
	}
68
69
	/**
70
	 * Display options for a data cell in this column
71
	 * @var array
72
	 */
73
	public $dataCellOptions = [];
74
75
	/**
76
	 * Configuration options for the column filter object
77
	 * @var array
78
	 */
79
	public $filterFieldConfig = [];
80
81
	/**
82
	 * Html options for the column filter object for use in
83
	 *   HTML::tag('td', 'content', $filterCellOptions)
84
	 * @var array
85
	 */
86
	public $filterCellOptions = [];
87
88
	/**
89
	 * Display attributes for the header cell
90
	 * @see setHeaderCellAttributes, getHeaderCellAttributes
91
	 */
92
	protected $_headerCellAttributes = [];
93
94
	/**
95
	 * The string to output when the cell content is empty
96
	 *
97
	 * @var string
98
	 */
99
	private $_emptyCellDisplay = null;
100
101
	/**
102
	 * Get the string to render for the cell if the cells data is empty
103
	 *
104
	 * @return string
105
	 */
106
	public function getEmptyCellDisplay()
107
	{
108
		if ($this->_emptyCellDisplay !== null)
109
			return $this->_emptyCellDisplay;
110
		return $this->getGrid()->emptyCellDisplay;
111
	}
112
113
	/**
114
	 * Set string the column will output when the cell is empty
115
	 *
116
	 * @param string $string
117
	 * @return $this - chainable
118
	 */
119
	public function setEmptyCellDisplay($string)
120
	{
121
		$this->_emptyCellDisplay = $string;
122
		return $this;
123
	}
124
125
126
	/**
127
	 * Set the header cell attributes
128
	 * @param array $attributes
129
	 */
130
	public function setHeaderCellAttributes($attributes)
131
	{
132
		$this->_headerCellAttributes = $attributes;
133
		return $this;
134
	}
135
136
	/**
137
	 * Get the header cell attributes
138
	 */
139
	public function getHeaderCellAttributes()
140
	{
141
		return $this->_headerCellAttributes;
142
	}
143
144
	protected $_width = '';
145
146
	/**
147
	 * @deprecated for @see setWidth
148
	 */
149
	public function width($width)
150
	{
151
		return $this->setWidth($width);
152
	}
153
154
	/**
155
	 * Set the column width
156
	 *
157
	 * @param string $width
158
	 * @return $this
159
	 */
160
	public function setWidth($width)
161
	{
162
		$this->_width = $width;
163
		return $this;
164
	}
165
166
	/**
167
	 * Get the column width
168
	 *
169
	 * @return string
170
	 */
171
	public function getWidth()
172
	{
173
		return $this->_width;
174
	}
175
176
	public function __construct($config=[])
177
	{
178
		parent::__construct($config);
179
		if (!isset($config['key'])) {
180
			throw new \InvalidConfigException('Config must contain "key" property, a string that identified this column $this->key');
0 ignored issues
show
Bug introduced by
The type InvalidConfigException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
181
		}
182
		if (!isset($config['grid'])) {
183
			throw new \InvalidConfigException('Config must contain "grid" property, defining the parent grid this column belongs to');
184
		}
185
		$this->_key = $config['key'];
186
		$this->_grid = $config['grid'];
187
	}
188
189
	/**
190
	 * Whether or not to show the filter
191
	 * @var boolean
192
	 */
193
	protected $_filter = true;
194
195
	/**
196
	 * @inheritDoc
197
	 */
198
	public function getFilter()
199
	{
200
		return $this->_filter;
201
	}
202
203
	/**
204
	 * @inheritDoc
205
	 */
206
	public function setFilter($filter)
207
	{
208
		$this->_filter = $filter;
209
		return $this;
210
	}
211
212
	/**
213
	 * @var string
214
	 */
215
	protected $_key;
216
217
	/**
218
	 * @inheritDoc
219
	 */
220
	public function setKey($key)
221
	{
222
		$this->_key = $key;
223
		return $this;
224
	}
225
226
	/**
227
	 * @inheritDoc
228
	 */
229
	public function getKey()
230
	{
231
		return $this->_key;
232
	}
233
234
	/**
235
	 * A reference to the columns parent Grid object that it belongs to
236
	 * @var \neon\core\grid\Grid;
237
	 */
238
	protected $_grid;
239
240
	/**
241
	 * @inheritDoc
242
	 */
243
	public function setGrid($grid)
244
	{
245
		$this->_grid = $grid;
246
		return $this;
247
	}
248
249
	protected $_visible = true;
250
251
	/**
252
	 * @inheritDoc
253
	 */
254
	public function setVisible($visible)
255
	{
256
		$this->_visible = $visible;
257
		return $this;
258
	}
259
260
	/**
261
	 * @inheritDoc
262
	 */
263
	public function getVisible()
264
	{
265
		return $this->_visible;
266
	}
267
268
	/**
269
	 * @var boolean store the sortable option
270
	 */
271
	protected $_sortable = true;
272
273
	/**
274
	 * @inheritDoc
275
	 */
276
	public function setIsSortable($sortable=true)
277
	{
278
		$this->_sortable = $sortable;
279
		return $this;
280
	}
281
282
	/**
283
	 * @inheritDoc
284
	 */
285
	public function getIsSortable()
286
	{
287
		return $this->_sortable;
288
	}
289
290
	public function setAsIndex($bool=true)
291
	{
292
		$this->grid->setIndexedByColumn($this->key);
293
		// thi is a bit gnarly but tests for yii Active record data providers specifically
294
		if ($this->grid->getDataProvider() instanceof ActiveDataProvider) {
0 ignored issues
show
introduced by
$this->grid->getDataProvider() is always a sub-type of yii\data\ActiveDataProvider.
Loading history...
295
			if ($bool) {
296
				$this->grid->query->indexBy($this->getDbField());
297
			} else {
298
				$this->grid->query->indexBy(null);
299
			}
300
		}
301
		return $this;
302
	}
303
304
	/**
305
	 * @inheritDoc
306
	 */
307
	public function getGrid()
308
	{
309
		return $this->_grid;
310
	}
311
312
	/**
313
	 * Gets the posted search data for this column
314
	 * This can be used to filter the data by this column
315
	 * typical useage:
316
	 *
317
	 * ```php
318
	 * // note we make sure request data exists before using it otherwise we get the default empty form value
319
	 * if ($this->hasRequestData()) {
320
	 *     $val = $this->getSearch();
321
	 *     $this->grid->query->andWhere(['id' => $val]);
322
	 * }
323
	 * ```
324
	 *
325
	 * @return mixed
326
	 */
327
	public function getSearch()
328
	{
329
		$form = $this->getGrid()->getFilterForm();
330
		if ($form->hasField($this->getKey())) {
331
			$value = $form->getField($this->getKey())->getValue();
332
			return $value;
333
		}
334
		return null;
335
	}
336
337
	protected $_dataCellContentFunction;
338
339
	/**
340
	 * @inheritdoc
341
	 */
342
	public function setDataCellContentFunction($callable)
343
	{
344
		$this->_dataCellContentFunction = $callable;
345
		return $this;
346
	}
347
348
	/**
349
	 * @inheritdoc
350
	 */
351
	public function getDataCellContentFunction()
352
	{
353
		// function has been hard set
354
		if ($this->_dataCellContentFunction !== null) {
355
			return $this->_dataCellContentFunction;
356
		}
357
		// check for convention
358
		$functionName = 'render' . $this->key;
359
		if (method_exists($this->grid, $functionName) && $functionName !== 'renderfile') {
360
			return $functionName;
361
		}
362
		// otherwise render the default column render function
363
		return [$this, 'renderDataCellContent'];
364
	}
365
366
	/**
367
	 * @var string
368
	 */
369
	protected $_title = null;
370
371
	/**
372
	 * @inheritdoc
373
	 */
374
	public function setTitle($title)
375
	{
376
		$this->_title = $title;
377
		return $this;
378
	}
379
380
	/**
381
	 * @inheritDoc
382
	 */
383
	public function getTitle()
384
	{
385
		if ($this->_title === null) {
386
			$title = Inflector::humanize($this->getKey());
387
			$this->_title = ucwords(trim($title));
388
		}
389
		return $this->_title;
390
	}
391
392
393
	protected $_searchFunction;
394
395
	/**
396
	 * @inheritDoc
397
	 */
398
	public function setSearchFunction($function)
399
	{
400
		$this->_searchFunction = $function;
401
		return $this;
402
	}
403
404
	/**
405
	 * @inheritDoc
406
	 */
407
	public function getSearchFunction()
408
	{
409
		if ($this->_searchFunction === null) {
410
			$searchFunction = 'search'.ucwords($this->key);
411
			if (method_exists($this->grid, $searchFunction)) {
412
				$this->_searchFunction = $searchFunction;
413
			}
414
		}
415
		return $this->_searchFunction;
416
	}
417
418
	/**
419
	 * The query field used for this column for sorting, filtering
420
	 * and getting the value. If this isn't set, key is used. If you require
421
	 * sorting over a separate field @see setDbSortField
422
	 * @var string
423
	 */
424
	protected $_dbField;
425
426
	/**
427
	 * @inheritDoc
428
	 */
429
	public function setDbField($field){
430
		$this->_dbField = $field;
431
		return $this;
432
	}
433
434
	/**
435
	 * @inheritDoc
436
	 */
437
	public function getDbField(){
438
		if ($this->_dbField === null){
439
			// set to be the key
440
			$this->_dbField = $this->key;
441
		}
442
		return $this->_dbField;
443
	}
444
445
	/**
446
	 * The query field used for sorting. If this isn't set then dbField is
447
	 * used. If that isn't set then key is used
448
	 * @var string
449
	 */
450
	protected $_dbSortField;
451
452
	/**
453
	 * @inheritDoc
454
	 */
455
	public function setDbSortField($field){
456
		$this->_dbSortField = $field;
457
		return $this;
458
	}
459
460
	/**
461
	 * @inheritDoc
462
	 */
463
	public function getDbSortField(){
464
		if ($this->_dbSortField === null){
465
			// set to be the key
466
			$this->_dbSortField = $this->dbField;
467
		}
468
		return $this->_dbSortField;
469
	}
470
471
	/**
472
	 * @var array
473
	 */
474
	protected $_style = [];
475
476
	/**
477
	 * Set header css styles
478
	 * @param array $styles
479
	 * @return $this
480
	 */
481
	public function setHeaderStyle(array $styles)
482
	{
483
		$this->_style = $styles;
484
		return $this;
485
	}
486
487
	/**
488
	 * @inheritDoc
489
	 */
490
	public function renderHeaderCell()
491
	{
492
		$options = $this->getHeaderCellAttributes();
493
		if ($this->grid->hasSort($this->key))
494
			Html::addCssClass($options, ($this->grid->hasSortDescending() ? 'desc' : 'asc'));
495
		if (trim($this->width) != '')
0 ignored issues
show
Bug Best Practice introduced by
The property width does not exist on neon\core\grid\column\Column. Since you implemented __get, consider adding a @property annotation.
Loading history...
496
			Html::addCssStyle($options, ["width" => $this->width]);
497
		Html::addCssStyle($options, $this->_style);
498
499
		return Html::tag('th', $this->renderHeaderCellContent(), $options);
500
	}
501
502
	/**
503
	 * @inheritdoc
504
	 */
505
	public function renderHeaderCellContent()
506
	{
507
		if (!$this->isSortable)
0 ignored issues
show
Bug Best Practice introduced by
The property isSortable does not exist on neon\core\grid\column\Column. Since you implemented __get, consider adding a @property annotation.
Loading history...
508
			return $this->getTitle();
509
		$sort = '';
510
		if ($this->grid->hasSort($this->key)) {
511
			$sort = $this->grid->hasSortDescending() ? ' - ' : ' + ';
512
		}
513
		$sortParam = $this->grid->hasSortDescending() ? $this->key : '-' . $this->key;
514
		$url = neon()->getUrlManager()->createUrl([\Yii::$app->controller->getRoute(), $this->grid->id => ['sort' => $sortParam]]);
515
		return Html::a($this->getTitle() . $sort, $url, ['data-sort'=>$sortParam]);
516
	}
517
518
	/**
519
	 * @inheritdoc
520
	 */
521
	public function renderFilterCell()
522
	{
523
		$content = '';
524
		if ($this->filter !== false) {
0 ignored issues
show
Bug Best Practice introduced by
The property filter does not exist on neon\core\grid\column\Column. Since you implemented __get, consider adding a @property annotation.
Loading history...
525
			$content = $this->renderFilterCellContent();
526
		}
527
		if (trim($this->width) != '') {
0 ignored issues
show
Bug Best Practice introduced by
The property width does not exist on neon\core\grid\column\Column. Since you implemented __get, consider adding a @property annotation.
Loading history...
528
			Html::addCssStyle($this->filterCellOptions, "width:{$this->width};");
529
		}
530
		return Html::tag('td', $content, $this->filterCellOptions);
531
	}
532
533
	/**
534
	 * @inheritdoc
535
	 */
536
	public function renderFilterCellContent()
537
	{
538
		if ($this->filter === false)
0 ignored issues
show
Bug Best Practice introduced by
The property filter does not exist on neon\core\grid\column\Column. Since you implemented __get, consider adding a @property annotation.
Loading history...
539
			return '';
540
		if (!$this->getGrid()->getFilterForm()->hasField($this->getKey()))
541
			return '';
542
		$field = $this->getGrid()->getFilterForm()->getField($this->getKey());
543
		// remove any automatic validators
544
		$field->setValidators([], true);
545
		return $field->run();
546
	}
547
548
	/**
549
	 * Get the base definition of the filter field.
550
	 * Returns the array definition of a form field, an instance of a form field (implementing IField)
551
	 * or a boolean false to indicate no filtering.
552
	 * @return array|false|IField
553
	 */
554
	protected function getBaseFilterField()
555
	{
556
		if ($this->member instanceof IField) {
0 ignored issues
show
introduced by
$this->member is always a sub-type of neon\core\form\interfaces\IField.
Loading history...
557
			return $this->member->getFilterField();
558
		}
559
		return ['class' => 'text', 'name' => $this->getKey()];
560
	}
561
562
563
	/**
564
	 * @inheritdoc
565
	 */
566
	public function getFilterField()
567
	{
568
		$field = $this->getBaseFilterField();
569
		foreach($this->filterFieldConfig as $key => $value)
570
			$field[$key] = $value;
571
		return $field;
572
	}
573
574
	/**
575
	 * @inheritdoc
576
	 */
577
	public function setFilterFieldConfig($config)
578
	{
579
		$this->filterFieldConfig = $config;
580
		return $this;
581
	}
582
583
	public function setMemberConfig($config)
584
	{
585
		foreach($config as $key => $value) {
586
			if (isset($this->member->$key))
587
				$this->member->$key = $value;
588
		}
589
		return $this;
590
	}
591
592
	/**
593
	 * @inheritDoc
594
	 */
595
	public function getCellData($row, $noValue='-')
596
	{
597
		$data = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $data is dead and can be removed.
Loading history...
598
		$key = $this->getKey();
599
		if (isset($row[$key])) {
600
			$data = $row[$key];
601
		} else {
602
			return $noValue;
603
		}
604
		return $data;
605
	}
606
607
	/**
608
	 * @inheritdoc
609
	 */
610
	public function getDataCellOptions($model, $key, $index)
611
	{
612
		$options = $this->dataCellOptions;
613
		if (trim($this->width) != '') {
0 ignored issues
show
Bug Best Practice introduced by
The property width does not exist on neon\core\grid\column\Column. Since you implemented __get, consider adding a @property annotation.
Loading history...
614
			Html::addCssStyle($options, "width:{$this->width};");
615
		}
616
		return $options;
617
	}
618
619
	/**
620
	 * @inheritdoc
621
	 */
622
	public function renderDataCell($model, $key, $index)
623
	{
624
		$cellContent = $this->callRenderDataCellContentFunction($model, $key, $index);
625
		// if row actions:
626
		$cellContent .= $this->renderRowActions($model, $key, $index);
627
		$options = $this->getDataCellOptions($model, $key, $index);
628
		$cell = Html::tag('div', $cellContent, array_merge($options, ['class'=>'neonGrid_cell']));
629
		return Html::tag('td', $cell, $options);
630
	}
631
632
	/**
633
	 * @inheritdoc
634
	 */
635
	public function renderDataCellContent($model, $key, $index)
636
	{
637
		if ($this->getMember() instanceof IField) {
0 ignored issues
show
introduced by
$this->getMember() is always a sub-type of neon\core\form\interfaces\IField.
Loading history...
638
			$cellData = $this->getCellData($model, null);
639
			$this->member->setValueFromDb($cellData);
640
			$display = $this->member->getValueDisplay('grid');
641
			if ($display === null || $display === []) { return $this->emptyCellDisplay; }
0 ignored issues
show
introduced by
The condition $display === array() is always false.
Loading history...
642
			$out = $this->highlight($display, $this->getSearch());
643
			if (is_array($display)) {
0 ignored issues
show
introduced by
The condition is_array($display) is always false.
Loading history...
644
				$display = implode(',', $display);
645
			}
646
			return "<span title=\"".str_replace('"',"'", html_entity_decode(strip_tags($display)))."\">$out</span>";
647
		}
648
		return $this->getCellData($model);
649
	}
650
651
	/**
652
	 * @inheritDoc
653
	 */
654
	public function getFieldName()
655
	{
656
		return $this->getGrid()->getId() . '[' . $this->key . '][search]';
657
	}
658
659
	/**
660
	 * @inheritDoc
661
	 */
662
	public function highlight($stringToHighlight, $search)
663
	{
664
		return Html::highlight($search, $stringToHighlight);
665
	}
666
667
	/**
668
	 * @inheritdoc
669
	 */
670
	public function processSort(IQuery $query, $descending)
671
	{
672
		$sort = $descending ? 'DESC' : 'ASC';
673
		$query->orderBy($this->dbSortField, $sort);
674
	}
675
676
	/**
677
	 * @inheritDoc
678
	 */
679
	public function processSearch(IQuery $query)
680
	{
681
		$postVal = $this->getSearch();
682
		$form = $this->getGrid()->getFilterForm();
683
		if ($form->hasField($this->getKey())) {
684
			$form->getField($this->getKey())->processAsFilter($query, $postVal);
685
		}
686
	}
687
688
	/**
689
	 * Whether search request data exists for the column
690
	 * @return bool
691
	 */
692
	public function hasRequestData()
693
	{
694
		$filterForm = $this->getGrid()->getFilterForm();
695
		return isset($_REQUEST[$this->getGrid()->getId()][$filterForm->getName()][$this->getKey()]);
696
	}
697
698
	/**
699
	 * Calls the render function and passes in the current row $model, $key, $index
700
	 *
701
	 * @param $model
702
	 * @param $key
703
	 * @param $index
704
	 * @return mixed
705
	 * @throws \Exception
706
	 */
707
	public function callRenderDataCellContentFunction($model, $key, $index)
708
	{
709
		if (($cellFunc = $this->getDataCellContentFunction())) {
710
			if (is_string($cellFunc)) {
711
				return $this->grid->$cellFunc($model, $key, $index, $this);
712
			} else {
713
				return call_user_func($cellFunc, $model, $key, $index, $this);
714
			}
715
		}
716
		throw new \Exception('Unable to call a valid data cell render function');
717
	}
718
719
	/**
720
	 * @inheritDoc
721
	 */
722
	public function callSearchFunction()
723
	{
724
		if (($search = $this->getSearchFunction())) {
725
			return $this->callFunction($search, [$this->getSearch(), $this->getGrid()->getQueryBuilder()]);
726
		}
727
		throw new \Exception('Unable to call a valid search function');
728
	}
729
730
	protected $_actions =[];
731
732
	/**
733
	 * @inheritDoc
734
	 */
735
	public function addRowAction($key, $text, $linkOptions=[])
736
	{
737
		$linkOptions['text'] = $text;
738
		$linkOptions['data-action'] = $key;
739
		$linkOptions['href'] = '';
740
		$linkOptions['data-pjax'] = 0;
741
		$this->_actions[$key] = $linkOptions;
742
	}
743
744
	public function addRowActionLink($text, $function)
745
	{
746
		$linkOptions['text'] = $text;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$linkOptions was never initialized. Although not strictly required by PHP, it is generally a good practice to add $linkOptions = array(); before regardless.
Loading history...
747
		$linkOptions['function'] = $function;
748
		$this->_actions[$text] = $linkOptions;
749
	}
750
751
	/**
752
	 * @inheritDoc
753
	 */
754
	public function renderRowActions($model, $key, $index)
755
	{
756
		if (empty($this->_actions)) {
757
			return '';
758
		}
759
		$out = '<div class="neonGrid_rowActions">';
760
		$i = 0;
761
		foreach($this->_actions as $actionKey => $linkOptions) {
762
			if ($i > 0) $out .= ' | ';
763
			if (isset($linkOptions['function'])) {
764
				$func = $linkOptions['function'];
765
				$out .= $this->callFunction($func, [$model, $key, $index]);
766
			} else {
767
768
				if ($this->getGrid()->hasIndexColumn()) {
769
					$key = $this->getGrid()->getIndexColumn()->getKey();
770
					$linkOptions['data-index'] = isset($model[$key]) ? $model[$key] : '';
771
				}
772
773
				$text = ArrayHelper::remove($linkOptions, 'text');
774
				$out .= Html::tag('a', $text, $linkOptions);
775
			}
776
			$i++;
777
		}
778
		$out .= '</div>';
779
		return $out;
780
	}
781
782
	/**
783
	 * @param mixed $function if a string then assumes this is a string function on the parent grid.
784
	 * Can be a callable function or  array [$object, 'functionName']
785
	 * @param array $arguments of arguments
786
	 * @return mixed
787
	 */
788
	public function callFunction($function, $arguments=[])
789
	{
790
		if (is_string($function)) {
791
			return call_user_func_array([$this->grid, $function], $arguments);
792
		} else {
793
			return call_user_func_array($function, $arguments);
794
		}
795
	}
796
797
	/**
798
	 * @inheritdoc
799
	 * Currently the column will respect dataMapFilters applied to the columns form field member
800
	 * Note: member only refers to the name of the form field configuration for the column and not necessarily
801
	 * a daedalus member
802
	 */
803
	public function prepareDisplay()
804
	{
805
		// limit the column results to respect any mapFilters
806
		if (isset($this->member->dataMapFilters)) {
0 ignored issues
show
Bug introduced by
Accessing dataMapFilters on the interface neon\core\form\interfaces\IField suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
807
			$models = $this->getGrid()->dataProvider->getModels();
808
			// extract out non-empty column values only, flatten the data so just an array of keys and remove any duplicates
809
			$columnData = array_unique(Arr::flatten(array_filter(Arr::getColumn($models, $this->key))));
810
			if (count($columnData)) {
811
				$this->member->dataMapFilters = ['uuid' => $columnData];
812
			}
813
			foreach($models as $model) {
814
				$this->member->makeMapRequest($this->getCellData($model, null));
0 ignored issues
show
Bug introduced by
The method makeMapRequest() does not exist on neon\core\form\interfaces\IField. Since it exists in all sub-types, consider adding an abstract or default implementation to neon\core\form\interfaces\IField. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

814
				$this->member->/** @scrutinizer ignore-call */ 
815
                   makeMapRequest($this->getCellData($model, null));
Loading history...
815
			}
816
		}
817
	}
818
}
819