diff --git a/src/DataSources/ArrayDataSource.php b/src/DataSources/ArrayDataSource.php index f6590df..ba585e6 100644 --- a/src/DataSources/ArrayDataSource.php +++ b/src/DataSources/ArrayDataSource.php @@ -7,9 +7,11 @@ use CzProject\Assert\Assert; use Inteve\DataGrid\DataPaging; use Inteve\DataGrid\DataSourceResult; + use Inteve\DataGrid\FilterCondition; use Inteve\DataGrid\IColumn; use Inteve\DataGrid\IDataSource; use Inteve\DataGrid\IFilter; + use Nette\Utils\Strings; class ArrayDataSource implements IDataSource @@ -62,30 +64,117 @@ public function getRowId($row) public function getData(array $columns, array $filters, array $sorts, DataPaging $paging) { - if (!empty($filters)) { + if (!empty($sorts)) { throw new \Inteve\DataGrid\Exception('Not implemented yet.'); } - if (!empty($sorts)) { - throw new \Inteve\DataGrid\Exception('Not implemented yet.'); + $data = $this->rows; + + // filtering + foreach ($filters as $filter) { + if (!$filter->isActive()) { + continue; + } + + $data = $this->filterData($data, $filter->prepareCondition()); } - // pager - $data = NULL; + $totalCount = count($data); + // pager if ($paging->hasOffset() && $paging->hasLimit()) { // offset + limit - $data = array_slice($this->rows, $paging->getOffset(), $paging->getLimit(), FALSE /*preserve keys*/); + $data = array_slice($data, $paging->getOffset(), $paging->getLimit(), FALSE /*preserve keys*/); } elseif (!$paging->hasOffset() && $paging->hasLimit()) { // only limit - $data = array_slice($this->rows, 0, $paging->getLimit(), FALSE /*preserve keys*/); + $data = array_slice($data, 0, $paging->getLimit(), FALSE /*preserve keys*/); } elseif (!$paging->hasOffset() && !$paging->hasLimit()) { // all - $data = $this->rows; + $data = $data; } else { // only offset - $data = array_slice($this->rows, $paging->getOffset(), NULL, FALSE /*preserve keys*/); + $data = array_slice($data, $paging->getOffset(), NULL, FALSE /*preserve keys*/); + } + + return new DataSourceResult($data, $totalCount); + } + + + /** + * @param array|object> $rows + * @param FilterCondition|FilterCondition[] $conditions + * @return array|object> + */ + protected function filterData(array $rows, $conditions) + { + if (!is_array($conditions)) { + $conditions = [$conditions]; + } + + foreach ($conditions as $condition) { + if (count($condition->getModifiers()) > 0) { + throw new \Inteve\DataGrid\Exception('Modifiers are not implemented yet.'); + } + } + + $matchedRows = []; + + foreach ($rows as $row) { + $hasMatch = FALSE; + + foreach ($conditions as $condition) { + $rowValue = $this->fetchValue($row, $condition->getField()); + $filterValue = $condition->getValue(); + $comparison = $condition->getComparison(); + + if ($comparison === IFilter::EQUAL) { + if (is_null($filterValue)) { + $hasMatch = $hasMatch || ($rowValue === NULL); + + } elseif (is_array($filterValue)) { + $hasMatch = $hasMatch || in_array($rowValue, $filterValue, TRUE); + + } else { + $hasMatch = $hasMatch || ($rowValue === $filterValue); + } + + } elseif ($comparison === IFilter::LIKE) { + if (is_scalar($rowValue) && is_scalar($filterValue)) { + $hasMatch = $hasMatch || Strings::contains( + Strings::lower((string) $rowValue), + Strings::lower((string) $filterValue) + ); + } + + } else { + throw new \Inteve\DataGrid\InvalidArgumentException("Unknow comparison '$comparison'."); + } + } + + if ($hasMatch) { + $matchedRows[] = $row; + } + } + + return $matchedRows; + } + + + /** + * @param array|object $row + * @param string $column + * @return mixed + */ + protected function fetchValue($row, $column) + { + if (is_object($row)) { + return $row->{$column}; + } + + if (!array_key_exists($column, $row)) { + throw new \Inteve\DataGrid\InvalidArgumentException("Missing column '$column' in row. + "); } - return new DataSourceResult($data, count($this->rows)); + return $row[$column]; } }