HtmlTable   F
last analyzed

Complexity

Total Complexity 83

Size/Duplication

Total Lines 577
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 170
c 2
b 0
f 0
dl 0
loc 577
rs 2
wmc 83

53 Methods

Rating   Name   Duplication   Size   Complexity  
A addMergeRow() 0 2 1
A getBody() 0 2 1
A colCenter() 0 2 1
A colAlign() 0 12 4
A setRowValues() 0 3 1
A getPart() 0 8 3
A setValues() 0 3 1
A setColWidth() 0 5 3
A compile_once() 0 4 2
A hasActiveRowSelector() 0 2 1
A setFooterValues() 0 2 1
A getFooter() 0 2 1
A getRowCount() 0 2 1
A applyCells() 0 3 1
A refresh() 0 4 2
A applyRows() 0 3 1
A getInnerScript() 0 2 1
A run() 0 11 4
A onNewRow() 0 3 1
A setColWidths() 0 13 5
A colLeft() 0 2 1
A getHeader() 0 2 1
A addRow() 0 4 1
A __construct() 0 15 1
A refreshTR() 0 3 1
A colRight() 0 2 1
A hideColumn() 0 9 3
A setInnerScript() 0 2 1
A colRightFromRight() 0 2 1
A fromDatabaseObject() 0 12 4
A setColValues() 0 3 1
A newRow() 0 2 1
A setCompileParts() 0 5 1
A hasPart() 0 2 1
A colLeftFromRight() 0 2 1
A conditionalCellFormat() 0 3 1
A addColVariations() 0 2 1
A setRowCount() 0 3 1
A setHeaderValues() 0 2 1
A setColAlignmentFromRight() 0 19 4
A mergeIdentiqualValues() 0 4 1
A _getFirstPart() 0 5 2
A getRow() 0 2 1
A setFocusable() 0 2 1
A compile() 0 7 2
A getCell() 0 2 1
A getActiveRowClass() 0 5 2
A conditionalRowFormat() 0 3 1
A setActiveRowSelector() 0 3 1
A setColAlignment() 0 19 4
A getActiveRowSelector() 0 2 1
A onActiveRowChange() 0 3 1
A colCenterFromRight() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like HtmlTable 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 HtmlTable, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace Ajax\semantic\html\collections\table;
3
4
use Ajax\semantic\html\base\HtmlSemDoubleElement;
5
use Ajax\semantic\html\content\table\HtmlTableContent;
6
use Ajax\semantic\html\base\constants\Variation;
7
use Ajax\JsUtils;
8
use Ajax\service\JArray;
9
use Ajax\semantic\html\content\table\HtmlTR;
10
use Ajax\semantic\html\collections\table\traits\TableTrait;
11
use Ajax\semantic\html\content\table\HtmlTD;
12
use Ajax\semantic\html\base\constants\TextAlignment;
13
use Ajax\common\html\BaseHtml;
14
15
/**
16
 * Semantic HTML Table component
17
 *
18
 * @author jc
19
 *
20
 */
21
class HtmlTable extends HtmlSemDoubleElement {
22
	use TableTrait;
23
24
	private $_colCount;
25
26
	private $_compileParts;
27
28
	private $_footer;
29
30
	private $_afterCompileEvents;
31
32
	private $_activeRowSelector;
33
34
	private $_focusable = false;
0 ignored issues
show
introduced by
The private property $_focusable is not used, and could be removed.
Loading history...
35
36
	/**
37
	 *
38
	 * @return ActiveRow
39
	 */
40
	public function getActiveRowSelector() {
41
		return $this->_activeRowSelector;
42
	}
43
44
	protected $_innerScript;
45
46
	public function __construct($identifier, $rowCount, $colCount) {
47
		parent::__construct($identifier, "table", "ui table");
48
		$this->content = array();
49
		$this->setRowCount($rowCount, $colCount);
50
		$this->_variations = [
51
			Variation::CELLED,
52
			Variation::PADDED,
53
			Variation::COMPACT
54
		];
55
		$this->_compileParts = [
56
			"thead",
57
			"tbody",
58
			"tfoot"
59
		];
60
		$this->_afterCompileEvents = [];
61
	}
62
63
	/**
64
	 * Returns/create eventually a part of the table corresponding to the $key : thead, tbody or tfoot
65
	 *
66
	 * @param string $key
67
	 * @return HtmlTableContent
68
	 */
69
	public function getPart($key) {
70
		if (\array_key_exists($key, $this->content) === false) {
71
			$this->content[$key] = new HtmlTableContent("", $key);
72
			if ($key !== "tbody") {
73
				$this->content[$key]->setRowCount(1, $this->_colCount);
74
			}
75
		}
76
		return $this->content[$key];
77
	}
78
79
	protected function _getFirstPart() {
80
		if (isset($this->content["thead"])) {
81
			return $this->content["thead"];
82
		}
83
		return $this->content["tbody"];
84
	}
85
86
	/**
87
	 * Returns/create eventually the body of the table
88
	 *
89
	 * @return HtmlTableContent
90
	 */
91
	public function getBody() {
92
		return $this->getPart("tbody");
93
	}
94
95
	/**
96
	 * Returns the number of rows (TR)
97
	 *
98
	 * @return int
99
	 */
100
	public function getRowCount() {
101
		return $this->getPart("tbody")->count();
102
	}
103
104
	/**
105
	 * Returns/create eventually the header of the table
106
	 *
107
	 * @return HtmlTableContent
108
	 */
109
	public function getHeader() {
110
		return $this->getPart("thead");
111
	}
112
113
	/**
114
	 * Returns/create eventually the footer of the table
115
	 *
116
	 * @return \Ajax\semantic\html\content\table\HtmlTableContent
117
	 */
118
	public function getFooter() {
119
		return $this->getPart("tfoot");
120
	}
121
122
	/**
123
	 * Checks if the part corresponding to $key exists
124
	 *
125
	 * @param string $key
126
	 * @return boolean
127
	 */
128
	public function hasPart($key) {
129
		return \array_key_exists($key, $this->content) === true;
130
	}
131
132
	/**
133
	 *
134
	 * @param int $rowCount
135
	 * @param int $colCount
136
	 * @return HtmlTableContent
137
	 */
138
	public function setRowCount($rowCount, $colCount) {
139
		$this->_colCount = $colCount;
140
		return $this->getBody()->setRowCount($rowCount, $colCount);
141
	}
142
143
	/**
144
	 * Returns the cell (HtmlTD) at position $row,$col
145
	 *
146
	 * @param int $row
147
	 * @param int $col
148
	 * @return HtmlTD
149
	 */
150
	public function getCell($row, $col) {
151
		return $this->getBody()->getCell($row, $col);
152
	}
153
154
	/**
155
	 * Retuns the row at $rowIndex
156
	 *
157
	 * @param int $rowIndex
158
	 * @return HtmlTR
159
	 */
160
	public function getRow($rowIndex) {
161
		return $this->getBody()->getRow($rowIndex);
162
	}
163
164
	/**
165
	 * Adds a new row and sets $values to his cols
166
	 *
167
	 * @param array $values
168
	 * @return HtmlTR
169
	 */
170
	public function addRow($values = array()) {
171
		$row = $this->getBody()->addRow($this->_colCount);
172
		$row->setValues(\array_values($values));
173
		return $row;
174
	}
175
176
	/**
177
	 * adds and returns a new row
178
	 *
179
	 * @return HtmlTR
180
	 */
181
	public function newRow() {
182
		return $this->getBody()->newRow($this->_colCount);
183
	}
184
185
	/**
186
	 * Sets the tbody values
187
	 *
188
	 * @param array $values
189
	 *        	values in an array of array
190
	 * @return HtmlTable
191
	 */
192
	public function setValues($values = array()) {
193
		$this->getBody()->setValues($values);
194
		return $this;
195
	}
196
197
	/**
198
	 * Sets the header values
199
	 *
200
	 * @param array $values
201
	 * @return HtmlTableContent
202
	 */
203
	public function setHeaderValues($values = array()) {
204
		return $this->getHeader()->setValues($values);
205
	}
206
207
	/**
208
	 * Sets the footer values
209
	 *
210
	 * @param array $values
211
	 * @return HtmlTableContent
212
	 */
213
	public function setFooterValues($values = array()) {
214
		return $this->getFooter()->setValues($values);
215
	}
216
217
	/**
218
	 * Sets values to the col at index $colIndex
219
	 *
220
	 * @param int $colIndex
221
	 * @param array $values
222
	 * @return HtmlTable
223
	 */
224
	public function setColValues($colIndex, $values = array()) {
225
		$this->getBody()->setColValues($colIndex, $values);
226
		return $this;
227
	}
228
229
	/**
230
	 * Sets values to the row at index $rowIndex
231
	 *
232
	 * @param int $rowIndex
233
	 * @param array $values
234
	 * @return HtmlTable
235
	 */
236
	public function setRowValues($rowIndex, $values = array()) {
237
		$this->getBody()->setRowValues($rowIndex, $values);
238
		return $this;
239
	}
240
241
	public function addColVariations($colIndex, $variations = array()) {
242
		return $this->getBody()->addColVariations($colIndex, $variations);
243
	}
244
245
	/**
246
	 * Sets the col alignment to center
247
	 *
248
	 * @param int $colIndex
249
	 * @return HtmlTable
250
	 */
251
	public function colCenter($colIndex) {
252
		return $this->colAlign($colIndex, "colCenter");
253
	}
254
255
	/**
256
	 * Sets the col alignment to right
257
	 *
258
	 * @param int $colIndex
259
	 * @return HtmlTable
260
	 */
261
	public function colRight($colIndex) {
262
		return $this->colAlign($colIndex, "colRight");
263
	}
264
265
	/**
266
	 * Sets col alignment to left
267
	 *
268
	 * @param int $colIndex
269
	 * @return HtmlTable
270
	 */
271
	public function colLeft($colIndex) {
272
		return $this->colAlign($colIndex, "colLeft");
273
	}
274
275
	/**
276
	 * Sets the col alignment to center
277
	 *
278
	 * @param int $colIndex
279
	 * @return HtmlTable
280
	 */
281
	public function colCenterFromRight($colIndex) {
282
		return $this->colAlign($colIndex, "colCenterFromRight");
283
	}
284
285
	/**
286
	 * Sets the col alignment to right
287
	 *
288
	 * @param int $colIndex
289
	 * @return HtmlTable
290
	 */
291
	public function colRightFromRight($colIndex) {
292
		return $this->colAlign($colIndex, "colRightFromRight");
293
	}
294
295
	/**
296
	 * Sets col alignment to left
297
	 *
298
	 * @param int $colIndex
299
	 * @return HtmlTable
300
	 */
301
	public function colLeftFromRight($colIndex) {
302
		return $this->colAlign($colIndex, "colLeftFromRight");
303
	}
304
305
	public function setColAlignment($colIndex, $alignment) {
306
		switch ($alignment) {
307
			case TextAlignment::LEFT:
308
				$function = "colLeft";
309
				break;
310
311
			case TextAlignment::RIGHT:
312
				$function = "colRight";
313
				break;
314
315
			case TextAlignment::CENTER:
316
				$function = "colCenter";
317
				break;
318
319
			default:
320
				$function = "colLeft";
321
		}
322
		$this->colAlign($colIndex, $function);
323
		return $this;
324
	}
325
326
	public function setColAlignmentFromRight($colIndex, $alignment) {
327
		switch ($alignment) {
328
			case TextAlignment::LEFT:
329
				$function = "colLeftFromRight";
330
				break;
331
332
			case TextAlignment::RIGHT:
333
				$function = "colRightFromRight";
334
				break;
335
336
			case TextAlignment::CENTER:
337
				$function = "colCenterFromRight";
338
				break;
339
340
			default:
341
				$function = "colLeftFromRight";
342
		}
343
		$this->colAlign($colIndex, $function);
344
		return $this;
345
	}
346
347
	private function colAlign($colIndex, $function) {
348
		if (\is_array($colIndex)) {
349
			foreach ($colIndex as $cIndex) {
350
				$this->colAlign($cIndex, $function);
351
			}
352
		} else {
353
			if ($this->hasPart("thead")) {
354
				$this->getHeader()->$function($colIndex);
355
			}
356
			$this->getBody()->$function($colIndex);
357
		}
358
		return $this;
359
	}
360
361
	/**
362
	 * Applies a format on each cell when $callback returns true
363
	 *
364
	 * @param callable $callback
365
	 *        	function with the cell as parameter, must return a boolean
366
	 * @param string $format
367
	 *        	css class to apply
368
	 * @return HtmlTable
369
	 */
370
	public function conditionalCellFormat($callback, $format) {
371
		$this->getBody()->conditionalCellFormat($callback, $format);
372
		return $this;
373
	}
374
375
	/**
376
	 * Applies a format on each row when $callback returns true
377
	 *
378
	 * @param callable $callback
379
	 *        	function with the row as parameter, must return a boolean
380
	 * @param string $format
381
	 *        	css class to apply
382
	 * @return HtmlTable
383
	 */
384
	public function conditionalRowFormat($callback, $format) {
385
		$this->getBody()->conditionalRowFormat($callback, $format);
386
		return $this;
387
	}
388
389
	/**
390
	 * Applies a callback function on each cell
391
	 *
392
	 * @param callable $callback
393
	 * @return HtmlTable
394
	 */
395
	public function applyCells($callback) {
396
		$this->getBody()->applyCells($callback);
397
		return $this;
398
	}
399
400
	/**
401
	 * Applies a callback function on each row
402
	 *
403
	 * @param callable $callback
404
	 * @return HtmlTable
405
	 */
406
	public function applyRows($callback) {
407
		$this->getBody()->applyRows($callback);
408
		return $this;
409
	}
410
411
	/**
412
	 *
413
	 * {@inheritdoc}
414
	 *
415
	 * @see HtmlSemDoubleElement::compile()
416
	 */
417
	public function compile(JsUtils $js = NULL, &$view = NULL) {
418
		if (\sizeof($this->_compileParts) < 3) {
419
			$this->_template = "%content%";
420
			$this->refresh($js);
421
		}
422
		$this->content = JArray::sortAssociative($this->content, $this->_compileParts);
423
		return parent::compile($js, $view);
424
	}
425
426
	protected function compile_once(JsUtils $js = NULL, &$view = NULL) {
427
		parent::compile_once($js, $view);
428
		if ($this->propertyContains("class", "sortable")) {
429
			$this->addEvent("execute", "$('#" . $this->identifier . "').tablesort().data('tablesort').sort($('th.default-sort'));");
430
		}
431
	}
432
433
	/**
434
	 *
435
	 * {@inheritdoc}
436
	 *
437
	 * @see BaseHtml::fromDatabaseObject()
438
	 */
439
	public function fromDatabaseObject($object, $function) {
440
		$result = $function($object);
441
		if (\is_array($result)) {
442
			$result = $this->addRow($function($object));
443
		} else {
444
			$result = $this->getBody()->_addRow($result);
445
		}
446
		if (isset($this->_afterCompileEvents["onNewRow"])) {
447
			if (\is_callable($this->_afterCompileEvents["onNewRow"]))
448
				$this->_afterCompileEvents["onNewRow"]($result, $object);
449
		}
450
		return $result;
451
	}
452
453
	/**
454
	 * Sets the parts of the Table to compile
455
	 *
456
	 * @param array $parts
457
	 *        	array of thead,tbody,tfoot
458
	 * @return HtmlTable
459
	 */
460
	public function setCompileParts($parts = [
461
		"tbody"
462
	]) {
463
		$this->_compileParts = $parts;
464
		return $this;
465
	}
466
467
	public function refreshTR() {
468
		$this->setCompileParts();
469
		$this->getPart("tbody")->refreshTR();
470
	}
471
472
	public function refresh($js) {
473
		$this->_footer = $this->getFooter();
474
		if (isset($js)) {
475
			$js->exec('$("#' . $this->identifier . ' tfoot").replaceWith("' . \addslashes($this->_footer) . '");', true);
476
		}
477
	}
478
479
	public function run(JsUtils $js) {
480
		if (! $this->_runned) {
481
			if (isset($this->_activeRowSelector)) {
482
				$this->_activeRowSelector->run();
483
			}
484
		}
485
		$result = parent::run($js);
486
		if (isset($this->_footer))
487
			$this->_footer->run($js);
488
		$this->_runned = true;
489
		return $result;
490
	}
491
492
	/**
493
	 * The callback function called after the insertion of each row when fromDatabaseObjects is called
494
	 * callback function takes the parameters $row : the row inserted and $object: the instance of model used
495
	 *
496
	 * @param callable $callback
497
	 * @return HtmlTable
498
	 */
499
	public function onNewRow($callback) {
500
		$this->_afterCompileEvents["onNewRow"] = $callback;
501
		return $this;
502
	}
503
504
	/**
505
	 * Defines how a row is selectable
506
	 *
507
	 * @param string $class
508
	 * @param string $event
509
	 * @param boolean $multiple
510
	 * @return HtmlTable
511
	 */
512
	public function setActiveRowSelector($class = "active", $event = "click", $multiple = false) {
513
		$this->_activeRowSelector = new ActiveRow($this, $class, $event, $multiple);
514
		return $this;
515
	}
516
517
	public function getActiveRowClass() {
518
		if (isset($this->_activeRowSelector)) {
519
			return $this->_activeRowSelector->getClass();
520
		}
521
		return 'active';
522
	}
523
524
	public function hasActiveRowSelector() {
525
		return isset($this->_activeRowSelector);
526
	}
527
528
	public function hideColumn($colIndex) {
529
		if (isset($this->content["thead"])) {
530
			$this->content["thead"]->hideColumn($colIndex);
531
		}
532
		$this->content["tbody"]->hideColumn($colIndex);
533
		if (isset($this->content["tfoot"])) {
534
			$this->content["tfoot"]->hideColumn($colIndex);
535
		}
536
		return $this;
537
	}
538
539
	public function setColWidth($colIndex, $width) {
540
		$part = $this->_getFirstPart();
541
		if ($part !== null && $part->count() > 0)
542
			$part->getCell(0, $colIndex)->setWidth($width);
543
		return $this;
544
	}
545
546
	public function setColWidths($widths) {
547
		$part = $this->_getFirstPart();
548
		if ($part !== null && $part->count() > 0) {
549
			$count = $part->getColCount();
550
			if (! \is_array($widths)) {
551
				$widths = \array_fill(0, $count, $widths);
552
			}
553
			$max = \min(\sizeof($widths), $count);
554
			for ($i = 0; $i < $max; $i ++) {
555
				$part->getCell(0, $i)->setWidth($widths[$i]);
556
			}
557
		}
558
		return $this;
559
	}
560
561
	public function mergeIdentiqualValues($colIndex, $function = "strip_tags") {
562
		$body = $this->getBody();
563
		$body->mergeIdentiqualValues($colIndex, $function);
564
		return $this;
565
	}
566
567
	/**
568
	 *
569
	 * @return mixed
570
	 */
571
	public function getInnerScript() {
572
		return $this->_innerScript;
573
	}
574
575
	/**
576
	 *
577
	 * @param mixed $_innerScript
578
	 */
579
	public function setInnerScript($_innerScript) {
580
		$this->_innerScript = $_innerScript;
581
	}
582
583
	public function onActiveRowChange($jsCode) {
584
		$this->on("activeRowChange", $jsCode);
585
		return $this;
586
	}
587
588
	public function addMergeRow($colCount, $value = null) {
589
		return $this->getBody()->addMergeRow($colCount, $value);
590
	}
591
592
	/**
593
	 *
594
	 * @param bool $focusable
595
	 */
596
	public function setFocusable(bool $focusable): void {
597
		$this->getBody()->setFocusable($focusable);
598
	}
599
}
600