Skip to content

Commit

Permalink
data row columns optional order by heading keys
Browse files Browse the repository at this point in the history
  • Loading branch information
rumpfc committed Apr 3, 2023
1 parent 7c76890 commit c7b02d8
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 2 deletions.
48 changes: 46 additions & 2 deletions system/View/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ class Table
*/
public $function;

/**
* Order each inserted row by heading keys
*
* @var bool
*/
public bool $rowKeysSyncWithHeadingKeys = false;

/**
* Set the template from the table config file if it exists
*
Expand Down Expand Up @@ -162,6 +169,7 @@ public function makeColumns($array = [], $columnLimit = 0)
// Turn off the auto-heading feature since it's doubtful we
// will want headings from a one-dimensional array
$this->autoHeading = false;
$this->rowKeysSyncWithHeadingKeys = false;

if ($columnLimit === 0) {
return $array;
Expand Down Expand Up @@ -207,7 +215,42 @@ public function setEmpty($value)
*/
public function addRow()
{
$this->rows[] = $this->_prepArgs(func_get_args());
$tmpRow = $this->_prepArgs(func_get_args());

if ($this->rowKeysSyncWithHeadingKeys && !empty($this->heading)) {
// each key has an index
$keyIndex = array_flip(array_keys($this->heading));

// figure out which keys need to be added
$missingKeys = array_diff_key($keyIndex, $tmpRow);

// Remove all keys which don't exist in $keyIndex
$tmpRow = array_filter($tmpRow, static fn($k) => array_key_exists($k, $keyIndex), ARRAY_FILTER_USE_KEY);

// add missing keys to row, but use $this->emptyCells
$tmpRow = array_merge($tmpRow, array_map(fn($v) => ['data' => $this->emptyCells], $missingKeys));

// order keys by $keyIndex values
uksort($tmpRow, static fn($k1, $k2) => $keyIndex[$k1] <=> $keyIndex[$k2]);
}
$this->rows[] = $tmpRow;

return $this;
}

/**
* Set to true if each row column should be synced by keys defined in heading.
*
* If a row has a key which does not exist in heading, it will be filtered out
* If a row does not have a key which exists in heading, the field will stay empty
*
* @param bool $orderByKey
*
* @return Table
*/
public function setSyncRowKeysWithHeadingKeys(bool $orderByKey): Table
{
$this->rowKeysSyncWithHeadingKeys = $orderByKey;

return $this;
}
Expand Down Expand Up @@ -436,7 +479,8 @@ protected function _setFromArray($data)
}

foreach ($data as &$row) {
$this->rows[] = $this->_prepArgs($row);
$this->addRow($row);
//$this->rows[] = $this->_prepArgs($row);
}
}

Expand Down
53 changes: 53 additions & 0 deletions tests/system/View/TableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,59 @@ public function testInvalidCallback()

$this->assertStringContainsString('<td>Fred</td><td><strong>Blue</strong></td><td>Small</td>', $generated);
}

/**
* @dataProvider orderedColumnUsecases
*/
public function testAddRowAndGenerateWithOrderedColumns(array $heading, array $row, string $expectContainsString): void
{
$this->table->setHeading($heading);
$this->table->setSyncRowKeysWithHeadingKeys(true);
$this->table->addRow($row);

$generated = $this->table->generate();

$this->assertStringContainsString($expectContainsString, $generated);
}

/**
* @dataProvider orderedColumnUsecases
*/
public function testGenerateDataWithOrderedColumns(array $heading, array $row, string $expectContainsString): void
{
$this->table->setHeading($heading);
$this->table->setSyncRowKeysWithHeadingKeys(true);

$generated = $this->table->generate([$row]);

$this->assertStringContainsString($expectContainsString, $generated);
}

public function orderedColumnUsecases(): array
{
return [
[
'heading' => ['id' => 'ID', 'name' => 'Name', 'age' => 'Age'],
'row' => ['name' => 'Max', 'age' => 30, 'id' => 5],
'expectContainsString' => '<td>5</td><td>Max</td><td>30</td>'
],
[
'heading' => ['id' => 'ID', 'age' => 'Age', 'name' => 'Name'],
'row' => ['name' => 'Fred', 'age' => 30, 'id' => 5],
'expectContainsString' => '<td>5</td><td>30</td><td>Fred</td>'
],
[
'heading' => ['id' => 'ID', 'name' => 'Name'],
'row' => ['name' => 'Fred', 'age' => 30, 'id' => 5],
'expectContainsString' => '<td>5</td><td>Fred</td>'
],
[
'heading' => ['id' => 'ID', 'age' => 'Age', 'name' => 'Name'],
'row' => ['name' => 'Fred', 'id' => 5],
'expectContainsString' => '<td>5</td><td></td><td>Fred</td>'
]
];
}
}

// We need this for the _set_from_db_result() test
Expand Down

0 comments on commit c7b02d8

Please sign in to comment.