Skip to content

Commit c7b02d8

Browse files
committed
data row columns optional order by heading keys
1 parent 7c76890 commit c7b02d8

File tree

2 files changed

+99
-2
lines changed

2 files changed

+99
-2
lines changed

system/View/Table.php

+46-2
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ class Table
8383
*/
8484
public $function;
8585

86+
/**
87+
* Order each inserted row by heading keys
88+
*
89+
* @var bool
90+
*/
91+
public bool $rowKeysSyncWithHeadingKeys = false;
92+
8693
/**
8794
* Set the template from the table config file if it exists
8895
*
@@ -162,6 +169,7 @@ public function makeColumns($array = [], $columnLimit = 0)
162169
// Turn off the auto-heading feature since it's doubtful we
163170
// will want headings from a one-dimensional array
164171
$this->autoHeading = false;
172+
$this->rowKeysSyncWithHeadingKeys = false;
165173

166174
if ($columnLimit === 0) {
167175
return $array;
@@ -207,7 +215,42 @@ public function setEmpty($value)
207215
*/
208216
public function addRow()
209217
{
210-
$this->rows[] = $this->_prepArgs(func_get_args());
218+
$tmpRow = $this->_prepArgs(func_get_args());
219+
220+
if ($this->rowKeysSyncWithHeadingKeys && !empty($this->heading)) {
221+
// each key has an index
222+
$keyIndex = array_flip(array_keys($this->heading));
223+
224+
// figure out which keys need to be added
225+
$missingKeys = array_diff_key($keyIndex, $tmpRow);
226+
227+
// Remove all keys which don't exist in $keyIndex
228+
$tmpRow = array_filter($tmpRow, static fn($k) => array_key_exists($k, $keyIndex), ARRAY_FILTER_USE_KEY);
229+
230+
// add missing keys to row, but use $this->emptyCells
231+
$tmpRow = array_merge($tmpRow, array_map(fn($v) => ['data' => $this->emptyCells], $missingKeys));
232+
233+
// order keys by $keyIndex values
234+
uksort($tmpRow, static fn($k1, $k2) => $keyIndex[$k1] <=> $keyIndex[$k2]);
235+
}
236+
$this->rows[] = $tmpRow;
237+
238+
return $this;
239+
}
240+
241+
/**
242+
* Set to true if each row column should be synced by keys defined in heading.
243+
*
244+
* If a row has a key which does not exist in heading, it will be filtered out
245+
* If a row does not have a key which exists in heading, the field will stay empty
246+
*
247+
* @param bool $orderByKey
248+
*
249+
* @return Table
250+
*/
251+
public function setSyncRowKeysWithHeadingKeys(bool $orderByKey): Table
252+
{
253+
$this->rowKeysSyncWithHeadingKeys = $orderByKey;
211254

212255
return $this;
213256
}
@@ -436,7 +479,8 @@ protected function _setFromArray($data)
436479
}
437480

438481
foreach ($data as &$row) {
439-
$this->rows[] = $this->_prepArgs($row);
482+
$this->addRow($row);
483+
//$this->rows[] = $this->_prepArgs($row);
440484
}
441485
}
442486

tests/system/View/TableTest.php

+53
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,59 @@ public function testInvalidCallback()
763763

764764
$this->assertStringContainsString('<td>Fred</td><td><strong>Blue</strong></td><td>Small</td>', $generated);
765765
}
766+
767+
/**
768+
* @dataProvider orderedColumnUsecases
769+
*/
770+
public function testAddRowAndGenerateWithOrderedColumns(array $heading, array $row, string $expectContainsString): void
771+
{
772+
$this->table->setHeading($heading);
773+
$this->table->setSyncRowKeysWithHeadingKeys(true);
774+
$this->table->addRow($row);
775+
776+
$generated = $this->table->generate();
777+
778+
$this->assertStringContainsString($expectContainsString, $generated);
779+
}
780+
781+
/**
782+
* @dataProvider orderedColumnUsecases
783+
*/
784+
public function testGenerateDataWithOrderedColumns(array $heading, array $row, string $expectContainsString): void
785+
{
786+
$this->table->setHeading($heading);
787+
$this->table->setSyncRowKeysWithHeadingKeys(true);
788+
789+
$generated = $this->table->generate([$row]);
790+
791+
$this->assertStringContainsString($expectContainsString, $generated);
792+
}
793+
794+
public function orderedColumnUsecases(): array
795+
{
796+
return [
797+
[
798+
'heading' => ['id' => 'ID', 'name' => 'Name', 'age' => 'Age'],
799+
'row' => ['name' => 'Max', 'age' => 30, 'id' => 5],
800+
'expectContainsString' => '<td>5</td><td>Max</td><td>30</td>'
801+
],
802+
[
803+
'heading' => ['id' => 'ID', 'age' => 'Age', 'name' => 'Name'],
804+
'row' => ['name' => 'Fred', 'age' => 30, 'id' => 5],
805+
'expectContainsString' => '<td>5</td><td>30</td><td>Fred</td>'
806+
],
807+
[
808+
'heading' => ['id' => 'ID', 'name' => 'Name'],
809+
'row' => ['name' => 'Fred', 'age' => 30, 'id' => 5],
810+
'expectContainsString' => '<td>5</td><td>Fred</td>'
811+
],
812+
[
813+
'heading' => ['id' => 'ID', 'age' => 'Age', 'name' => 'Name'],
814+
'row' => ['name' => 'Fred', 'id' => 5],
815+
'expectContainsString' => '<td>5</td><td></td><td>Fred</td>'
816+
]
817+
];
818+
}
766819
}
767820

768821
// We need this for the _set_from_db_result() test

0 commit comments

Comments
 (0)