Passed
Push — master ( 727fe8...731c7d )
by Jean-Christophe
02:56
created

DataTable::setRowClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Ajax\semantic\widgets\datatable;
4
5
use Ajax\common\Widget;
6
use Ajax\JsUtils;
7
use Ajax\semantic\html\collections\table\HtmlTable;
8
use Ajax\semantic\html\elements\HtmlInput;
9
use Ajax\semantic\html\modules\checkbox\HtmlCheckbox;
10
use Ajax\semantic\html\base\constants\Direction;
11
use Ajax\service\JArray;
12
use Ajax\semantic\widgets\base\InstanceViewer;
13
use Ajax\semantic\html\collections\table\traits\TableTrait;
14
use Ajax\semantic\html\collections\HtmlMessage;
15
use Ajax\semantic\html\base\traits\BaseTrait;
16
use Ubiquity\utils\base\UString;
0 ignored issues
show
Bug introduced by
The type Ubiquity\utils\base\UString 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...
17
18
/**
19
 * DataTable widget for displaying list of objects
20
 * @version 1.0
21
 * @author jc
22
 * @since 2.2
23
 *
24
 */
25
class DataTable extends Widget {
26
	use TableTrait,DataTableFieldAsTrait,HasCheckboxesTrait,BaseTrait;
27
	protected $_searchField;
28
	protected $_urls;
29
	protected $_pagination;
30
	protected $_compileParts;
31
	protected $_deleteBehavior;
32
	protected $_editBehavior;
33
	protected $_displayBehavior;
34
	protected $_visibleHover=false;
35
	protected $_targetSelector;
36
	protected $_refreshSelector;
37
	protected $_emptyMessage;
38
	protected $_json;
39
	protected $_rowClass="_element";
40
	protected $_sortable;
41
	protected $_hiddenColumns;
42
	protected $_colWidths;
43
44
45
	public function __construct($identifier,$model,$modelInstance=NULL) {
46
		parent::__construct($identifier, $model,$modelInstance);
47
		$this->_init(new InstanceViewer($identifier), "table", new HtmlTable($identifier, 0,0), false);
48
		$this->_urls=[];
49
		$this->_emptyMessage=new HtmlMessage("","nothing to display");
50
		$this->_emptyMessage->setIcon("info circle");
51
	}
52
53
	public function run(JsUtils $js){
54
		$offset=$js->scriptCount();
55
		if($this->_hasCheckboxes && isset($js)){
56
			$this->_runCheckboxes($js);
57
		}
58
		if($this->_visibleHover){
59
			$js->execOn("mouseover", "#".$this->identifier." tr", "$(event.target).closest('tr').find('.visibleover').css('visibility', 'visible');",["preventDefault"=>false,"stopPropagation"=>true]);
60
			$js->execOn("mouseout", "#".$this->identifier." tr", "$(event.target).closest('tr').find('.visibleover').css('visibility', 'hidden');",["preventDefault"=>false,"stopPropagation"=>true]);
61
		}
62
		if(\is_array($this->_deleteBehavior))
63
			$this->_generateBehavior("delete",$this->_deleteBehavior, $js);
64
		if(\is_array($this->_editBehavior))
65
			$this->_generateBehavior("edit",$this->_editBehavior,$js);
66
		if(\is_array($this->_displayBehavior)){
67
			$this->_generateBehavior("display",$this->_displayBehavior,$js);
68
		}
69
		parent::run($js);
70
		if(isset($this->_pagination))
71
			$this->_associatePaginationBehavior($js,$offset);
72
		$this->_associateSearchFieldBehavior($js,$offset);
73
			
74
	}
75
76
	protected function _generateBehavior($op,$params,JsUtils $js){
77
		if(isset($this->_urls[$op])){
78
			$params=\array_merge($params,["attr"=>"data-ajax"]);
79
			$js->ajaxOnClick("#".$this->identifier." ._".$op, $this->_urls[$op],$this->getTargetSelector($op),$params);
80
		}
81
	}
82
83
	/**
84
	 * {@inheritDoc}
85
	 * @see TableTrait::getTable()
86
	 */
87
	protected function getTable() {
88
		return $this->content["table"];
89
	}
90
91
92
	public function compile(JsUtils $js=NULL,&$view=NULL){
93
		if(!$this->_generated){
94
			if(isset($this->_buttonsColumn)){
95
				$this->_instanceViewer->sortColumnContent($this->_buttonsColumn, $this->_buttons);
96
			}
97
			$this->_instanceViewer->setInstance($this->_model);
98
			$captions=$this->_instanceViewer->getCaptions();
99
			$table=$this->content["table"];
100
			if($this->_hasCheckboxes){
101
				$this->_generateMainCheckbox($captions);
102
			}
103
			$table->setRowCount(0, \sizeof($captions));
104
			$this->_generateHeader($table,$captions);
105
106
			if(isset($this->_compileParts))
107
				$table->setCompileParts($this->_compileParts);
108
109
			$this->_generateContent($table);
110
111
			$this->compileExtraElements($table, $captions);
112
			$this->_compileSearchFieldBehavior($js);
113
114
			$this->content=JArray::sortAssociative($this->content, [PositionInTable::BEFORETABLE,"table",PositionInTable::AFTERTABLE]);
115
			$this->_compileForm();
116
			$this->_applyStyleAttributes($table);
117
			$this->_generated=true;
118
		}
119
		return parent::compile($js,$view);
120
	}
121
122
	protected function compileExtraElements($table,$captions){
123
124
		if($this->_hasCheckboxes && $table->hasPart("thead")){
125
			$table->getHeader()->getCell(0, 0)->addClass("no-sort");
126
		}
127
128
		if(isset($this->_toolbar)){
129
			$this->_setToolbarPosition($table, $captions);
130
		}
131
		if(isset($this->_pagination) && $this->_pagination->getVisible()){
132
			$this->_generatePagination($table);
133
		}
134
	}
135
136
	protected function _applyStyleAttributes($table){
137
		if(isset($this->_hiddenColumns))
138
			$this->_hideColumns();
139
			if(isset($this->_colWidths)){
140
				foreach ($this->_colWidths as $colIndex=>$width){
141
					$table->setColWidth($colIndex,$width);
142
				}
143
			}
144
	}
145
146
	protected function _hideColumns(){
147
		foreach ($this->_hiddenColumns as $colIndex){
148
			$this->_self->hideColumn($colIndex);
149
		}
150
		return $this;
151
	}
152
153
	protected function _generateHeader(HtmlTable $table,$captions){
154
		$table->setHeaderValues($captions);
155
		if(isset($this->_sortable)){
156
			$table->setSortable($this->_sortable);
157
		}
158
	}
159
160
161
162
	protected function _generateContent($table){
163
		$objects=$this->_modelInstance;
164
		if(isset($this->_pagination)){
165
			$objects=$this->_pagination->getObjects($this->_modelInstance);
166
		}
167
			InstanceViewer::setIndex(0);
168
			$fields=$this->_instanceViewer->getSimpleProperties();
169
			$table->fromDatabaseObjects($objects, function($instance) use($table,$fields){
170
				return $this->_generateRow($instance, $fields,$table);
171
			});
172
		if($table->getRowCount()==0){
173
			$result=$table->addRow();
174
			$result->mergeRow();
175
			$result->setValues([$this->_emptyMessage]);
176
		}
177
	}
178
179
	protected function _generateRow($instance,$fields,&$table,$checkedClass=null){
180
		$this->_instanceViewer->setInstance($instance);
181
		InstanceViewer::$index++;
182
		$values= $this->_instanceViewer->getValues();
183
		$id=$this->_instanceViewer->getIdentifier();
184
		$dataAjax=$id;
185
		$id=$this->cleanIdentifier($id);
186
		if($this->_hasCheckboxes){
187
			$ck=new HtmlCheckbox("ck-".$this->identifier."-".$id,"");
188
			$checked=false;
189
			if(isset($this->_checkedCallback)){
190
				$func=$this->_checkedCallback;
191
				$checked=$func($instance);
192
			}
193
			$ck->setChecked($checked);
194
			$ck->setOnChange("event.stopPropagation();");
195
			$field=$ck->getField();
196
			$field->setProperty("value",$dataAjax);
197
			$field->setProperty("name", "selection[]");
198
			if(isset($checkedClass))
199
				$field->setClass($checkedClass);
200
			\array_unshift($values, $ck);
201
		}
202
		$result=$table->newRow();
203
		$result->setIdentifier($this->identifier."-tr-".$id);
204
		$result->setProperty("data-ajax",$dataAjax);
205
		$result->setValues($values);
206
		$result->addToProperty("class",$this->_rowClass);
207
		$result->setPropertyValues("data-field", $fields);
208
		return $result;
209
	}
210
211
	protected function _generatePagination($table){
212
		if(isset($this->_toolbar)){
213
			if($this->_toolbarPosition==PositionInTable::FOOTER)
214
				$this->_toolbar->setFloated("left");
215
		}
216
		$footer=$table->getFooter();
217
		$footer->mergeCol();
218
		$footer->addValues($this->_pagination->generateMenu($this->identifier));
219
	}
220
221
	protected function _associatePaginationBehavior(JsUtils $js=NULL,$offset=null){
222
		if(isset($this->_urls["refresh"])){
223
			$this->_pagination->getMenu()->postOnClick($this->_urls["refresh"],"{'p':$(this).attr('data-page'),'_model':'".UString::doubleBackSlashes($this->_model)."'}",$this->getRefreshSelector(),["preventDefault"=>false,"jqueryDone"=>"replaceWith","hasLoader"=>false,"jsCallback"=>'$("#'.$this->identifier.'").trigger("pageChange");$("#'.$this->identifier.'").trigger("activeRowChange");']);
224
		}
225
	}
226
	
227
	protected function _compileSearchFieldBehavior(JsUtils $js=NULL){
228
		if(isset($this->_searchField) && isset($js) && isset($this->_urls["refresh"])){
229
			$this->_searchField->postOn("change", $this->_urls["refresh"],"{'s':$(self).val(),'_model':'".UString::doubleBackSlashes($this->_model)."'}","#".$this->identifier." tbody",["preventDefault"=>false,"jqueryDone"=>"replaceWith","hasLoader"=>"internal","jsCallback"=>'$("#'.$this->identifier.'").trigger("searchTerminate",[$(self).val()]);']);
230
		}
231
	}
232
	protected function _associateSearchFieldBehavior(JsUtils $js=NULL,$offset=null){
233
		
234
	}
235
236
	protected function _getFieldName($index){
237
		$fieldName=parent::_getFieldName($index);
238
		if(\is_object($fieldName))
239
			$fieldName="field-".$index;
240
		return $fieldName."[]";
241
	}
242
243
	protected function _getFieldCaption($index){
244
		return null;
245
	}
246
247
	protected function _setToolbarPosition($table,$captions=NULL){
248
		switch ($this->_toolbarPosition){
249
			case PositionInTable::BEFORETABLE:
250
			case PositionInTable::AFTERTABLE:
251
				if(isset($this->_compileParts)===false){
252
					$this->content[$this->_toolbarPosition]=$this->_toolbar;
253
				}
254
				break;
255
			case PositionInTable::HEADER:
256
			case PositionInTable::FOOTER:
257
			case PositionInTable::BODY:
258
				$this->addToolbarRow($this->_toolbarPosition,$table, $captions);
259
				break;
260
		}
261
	}
262
263
	/**
264
	 * Associates a $callback function after the compilation of the field at $index position
265
	 * The $callback function can take the following arguments : $field=>the compiled field, $instance : the active instance of the object, $index: the field position
266
	 * @param int $index postion of the compiled field
267
	 * @param callable $callback function called after the field compilation
268
	 * @return DataTable
269
	 */
270
	public function afterCompile($index,$callback){
271
		$this->_instanceViewer->afterCompile($index,$callback);
272
		return $this;
273
	}
274
275
	private function addToolbarRow($part,$table,$captions){
276
		$hasPart=$table->hasPart($part);
277
		if($hasPart){
278
			$row=$table->getPart($part)->addRow(\sizeof($captions));
279
		}else{
280
			$row=$table->getPart($part)->getRow(0);
281
		}
282
		$row->mergeCol();
283
		$row->setValues([$this->_toolbar]);
284
	}
285
286
	/**
287
	 * {@inheritDoc}
288
	 * @see Widget::getHtmlComponent()
289
	 * @return HtmlTable
290
	 */
291
	public function getHtmlComponent(){
292
		return $this->content["table"];
293
	}
294
295
	public function getUrls() {
296
		return $this->_urls;
297
	}
298
299
	/**
300
	 * Sets the associative array of urls for refreshing, updating or deleting
301
	 * think of defining the update zone with the setTargetSelector method
302
	 * @param string|array $urls associative array with keys refresh: for refreshing with search field or pagination, edit : for updating a row, delete: for deleting a row
303
	 * @return DataTable
304
	 */
305
	public function setUrls($urls) {
306
		if(\is_array($urls)){
307
			$this->_urls["refresh"]=JArray::getValue($urls, "refresh",0);
308
			$this->_urls["edit"]=JArray::getValue($urls, "edit",1);
309
			$this->_urls["delete"]=JArray::getValue($urls, "delete",2);
310
			$this->_urls["display"]=JArray::getValue($urls, "display",3);
311
		}else{
312
			$this->_urls=["refresh"=>$urls,"edit"=>$urls,"delete"=>$urls,"display"=>$urls];
313
		}
314
		return $this;
315
	}
316
317
	/**
318
	 * Paginates the DataTable element with a Semantic HtmlPaginationMenu component
319
	 * @param number $page the active page number
320
	 * @param number $total_rowcount the total number of items
321
	 * @param number $items_per_page The number of items per page
322
	 * @param number $pages_visibles The number of visible pages in the Pagination component
323
	 * @return DataTable
324
	 */
325
	public function paginate($page,$total_rowcount,$items_per_page=10,$pages_visibles=null){
326
		$this->_pagination=new Pagination($items_per_page,$pages_visibles,$page,$total_rowcount);
327
		return $this;
328
	}
329
330
	/**
331
	 * Auto Paginates the DataTable element with a Semantic HtmlPaginationMenu component
332
	 * @param number $page the active page number
333
	 * @param number $items_per_page The number of items per page
334
	 * @param number $pages_visibles The number of visible pages in the Pagination component
335
	 * @return DataTable
336
	 */
337
	public function autoPaginate($page=1,$items_per_page=10,$pages_visibles=4){
338
		$this->_pagination=new Pagination($items_per_page,$pages_visibles,$page);
339
		return $this;
340
	}
341
342
343
344
	/**
345
	 * @param array $compileParts
346
	 * @return DataTable
347
	 */
348
	public function refresh($compileParts=["tbody"]){
349
		$this->_compileParts=$compileParts;
350
		return $this;
351
	}
352
353
354
	/**
355
	 * Adds a search input in toolbar
356
	 * @param string $position
357
	 * @return \Ajax\common\html\HtmlDoubleElement
358
	 */
359
	public function addSearchInToolbar($position=Direction::RIGHT){
360
		return $this->addInToolbar($this->getSearchField())->setPosition($position);
361
	}
362
363
	public function getSearchField(){
364
		if(isset($this->_searchField)===false){
365
			$this->_searchField=new HtmlInput("search-".$this->identifier,"search","","Search...");
366
			$this->_searchField->addIcon("search",Direction::RIGHT);
367
		}
368
		return $this->_searchField;
369
	}
370
371
	/**
372
	 * The callback function called after the insertion of each row when fromDatabaseObjects is called
373
	 * callback function takes the parameters $row : the row inserted and $object: the instance of model used
374
	 * @param callable $callback
375
	 * @return DataTable
376
	 */
377
	public function onNewRow($callback) {
378
		$this->content["table"]->onNewRow($callback);
379
		return $this;
380
	}
381
382
	/**
383
	 * Returns a form corresponding to the Datatable
384
	 * @return \Ajax\semantic\html\collections\form\HtmlForm
385
	 */
386
	public function asForm(){
387
		return $this->getForm();
388
	}
389
390
391
392
	protected function getTargetSelector($op) {
393
		$result=$this->_targetSelector;
394
		if(!isset($result[$op]))
395
			$result="#".$this->identifier;
396
		return $result[$op];
397
	}
398
399
	/**
400
	 * Sets the response element selector for Edit and Delete request with ajax
401
	 * @param string|array $_targetSelector string or associative array ["edit"=>"edit_selector","delete"=>"delete_selector"]
402
	 * @return DataTable
403
	 */
404
	public function setTargetSelector($_targetSelector) {
405
		if(!\is_array($_targetSelector)){
406
			$_targetSelector=["edit"=>$_targetSelector,"delete"=>$_targetSelector];
407
		}
408
		$this->_targetSelector=$_targetSelector;
409
		return $this;
410
	}
411
412
	public function getRefreshSelector() {
413
		if(isset($this->_refreshSelector))
414
			return $this->_refreshSelector;
415
		return "#".$this->identifier." tbody";
416
	}
417
418
	/**
419
	 * @param string $_refreshSelector
420
	 * @return DataTable
421
	 */
422
	public function setRefreshSelector($_refreshSelector) {
423
		$this->_refreshSelector=$_refreshSelector;
424
		return $this;
425
	}
426
427
	/**
428
	 * {@inheritDoc}
429
	 * @see \Ajax\common\Widget::show()
430
	 */
431
	public function show($modelInstance){
432
		if(\is_array($modelInstance)){
433
			if(isset($modelInstance[0]) && \is_array(array_values($modelInstance)[0]))
434
				$modelInstance=\json_decode(\json_encode($modelInstance), FALSE);
435
		}
436
		$this->_modelInstance=$modelInstance;
437
	}
438
439
	public function getRowClass() {
440
		return $this->_rowClass;
441
	}
442
443
	/**
444
	 * Sets the default row class (tr class)
445
	 * @param string $_rowClass
446
	 * @return DataTable
447
	 */
448
	public function setRowClass($_rowClass) {
449
		$this->_rowClass=$_rowClass;
450
		return $this;
451
	}
452
453
	/**
454
	 * Sets the message displayed when there is no record
455
	 * @param mixed $_emptyMessage
456
	 * @return DataTable
457
	 */
458
	public function setEmptyMessage($_emptyMessage) {
459
		$this->_emptyMessage=$_emptyMessage;
460
		return $this;
461
	}
462
463
	public function setSortable($colIndex=NULL) {
464
		$this->_sortable=$colIndex;
465
		return $this;
466
	}
467
468
	public function setActiveRowSelector($class="active",$event="click",$multiple=false){
469
		$this->_self->setActiveRowSelector($class,$event,$multiple);
470
		return $this;
471
	}
472
473
	public function hideColumn($colIndex){
474
		if(!\is_array($this->_hiddenColumns))
475
			$this->_hiddenColumns=[];
476
		$this->_hiddenColumns[]=$colIndex;
477
		return $this;
478
	}
479
480
	public function setColWidth($colIndex,$width){
481
		$this->_colWidths[$colIndex]=$width;
482
		return $this;
483
	}
484
	public function setColWidths($_colWidths) {
485
		$this->_colWidths = $_colWidths;
486
		return $this;
487
	}
488
489
	public function setColAlignment($colIndex,$alignment){
490
		$this->content["table"]->setColAlignment($colIndex,$alignment);
491
		return $this;
492
	}
493
	
494
	public function trigger($event,$params="[]"){
495
		return $this->getHtmlComponent()->trigger($event,$params);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getHtmlComponent(...rigger($event, $params) targeting Ajax\common\html\BaseHtml::trigger() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
496
	}
497
	
498
	public function onActiveRowChange($jsCode){
499
		$this->getHtmlComponent()->onActiveRowChange($jsCode);
500
		return $this;
501
	}
502
	/**
503
	 * @return mixed
504
	 */
505
	public function getDeleteBehavior() {
506
		return $this->_deleteBehavior;
507
	}
508
509
	/**
510
	 * @return mixed
511
	 */
512
	public function getEditBehavior() {
513
		return $this->_editBehavior;
514
	}
515
516
	/**
517
	 * @return mixed
518
	 */
519
	public function getDisplayBehavior() {
520
		return $this->_displayBehavior;
521
	}
522
	/**
523
	 * @param mixed $_displayBehavior
524
	 */
525
	public function setDisplayBehavior($_displayBehavior) {
526
		$this->_displayBehavior = $_displayBehavior;
527
	}
528
529
530
}
531