diff --git a/README.md b/README.md index fe65db2..16f8c7d 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,42 @@ $dataSource = $this->queryObjectDataSourceFactory->create($qo, "id") } }) ->setFilterCallback(function ($queryObject, array $filter) { - foreach ($filter as $field => $value) { - $queryObject->{'by' . $field}($value); + foreach ($filter as $field => $value) { + switch ($column) { + case 'dateRange': + $queryObject->byDateRange(QueryObjectDataSource::parseFilterDateRange($fieldSet)); + break; + case 'date': + $queryObject->byDate(QueryObjectDataSource::parseFilterDate($fieldSet)); + break; + default: + $queryObject->{'by' . $field}($value); + } } + }) + ->setLimitCallback(function ($offset, $limit, $defaultCallback) use ($query, $itemRepository) { + // This callback is not necessary, but you can do your stuff with $offset and $limit here. + + $defaultCallback(); // Run the default action }); $grid->setDataSource($queryObjectDataSource); ``` + +You can use per column condition and sortable callbacks as well: +```php +$datagrid->addColumnText('email', 'entity.user.email') + ->setSortable() + ->setSortableCallback(function (UserQueryObject $userQuery, $email) { + $userQuery->orderByEmail($email); + }) + ->setFilterText() + ->setCondition(function (UserQueryObject $userQuery, $email) { + $userQuery->searchInEmail($email); + }); +``` + +If you implement \ADT\QueryObjectDataSource\IQueryObject on your QueryObject, +those methods will be called when there is no per column callbacks provided. +Function `searchIn($column, $value)` will be called on text fields and +`equalIn($column, $value)` on other column types. diff --git a/composer.json b/composer.json index 4ee6f23..8dc58f1 100644 --- a/composer.json +++ b/composer.json @@ -8,11 +8,14 @@ "GPL-2.0", "GPL-3.0" ], + "require": { + "php": ">=7.1" + }, "require-dev": { - "kdyby/doctrine": "^3.1", - "ublaboo/datagrid": "^5.0", - "nette/utils": "^2.4", - "nette/di": "^2.4" + "kdyby/doctrine": "^3.1 || ~4.0", + "ublaboo/datagrid": "^5.0 || ~6.0", + "nette/utils": "^2.4 || ~3.0", + "nette/di": "^2.4 || ~3.0" }, "autoload": { "psr-4": { diff --git a/src/DI/QueryObjectDataSourceExtension.php b/src/DI/QueryObjectDataSourceExtension.php index a24552f..3f236aa 100644 --- a/src/DI/QueryObjectDataSourceExtension.php +++ b/src/DI/QueryObjectDataSourceExtension.php @@ -6,9 +6,13 @@ class QueryObjectDataSourceExtension extends \Nette\DI\CompilerExtension { public function loadConfiguration() { - $this->getContainerBuilder() - ->addDefinition($this->prefix('factory')) - ->setImplement(\ADT\QueryObjectDataSource\IQueryObjectDataSourceFactory::class); + $builder = $this->getContainerBuilder(); + if (method_exists($builder, 'addFactoryDefinition')) { + $definition = $builder->addFactoryDefinition($this->prefix('factory')); + } else { + $definition = $builder->addDefinition($this->prefix('factory')); + } + $definition->setImplement(\ADT\QueryObjectDataSource\IQueryObjectDataSourceFactory::class); } } \ No newline at end of file diff --git a/src/IQueryObject.php b/src/IQueryObject.php new file mode 100644 index 0000000..a2cefd5 --- /dev/null +++ b/src/IQueryObject.php @@ -0,0 +1,14 @@ +limitCallback = $callback; + return $this; + } + protected function getResultSet() { if (!$this->resultSet) { $this->resultSet = $this->repo @@ -71,7 +97,7 @@ protected function getResultSet() { * Get count of data * @return int */ - public function getCount() { + public function getCount(): int { return $this->repo ->fetch($this->queryObject) ->getTotalCount(); @@ -81,31 +107,47 @@ public function getCount() { * Get the data * @return array */ - public function getData() { + public function getData(): array { + if ($this->data) { + return $this->data; + } return $this->getResultSet()->toArray(); } + /** + * Set the data + * @return $this + */ + public function setData($data) { + $this->data = $data; + return $this; + } + /** * Filter data * @param array $filters * @return static */ - public function filter(array $filters) { + public function filter(array $filters): void { foreach ($filters as $filter) { if ($filter->isValueSet()) { - if ($filter->hasConditionCallback()) { - \Nette\Utils\Callback::invokeArgs( - $filter->getConditionCallback(), [ $this->queryObject, $filter->getValue() ] - ); + if ($filter->getConditionCallback()) { + call_user_func($filter->getConditionCallback(), $this->queryObject, $filter->getValue()); + } else { + if ($this->queryObject instanceof IQueryObject) { + if ($filter instanceof FilterText) { + $this->queryObject->searchIn($filter->getKey(), $filter->getValue()); + } else { + $this->queryObject->equalIn($filter->getKey(), $filter->getValue()); + } + } } } } if (is_callable($this->filterCallback)) { - $this->filterCallback($this->queryObject, $filters); + call_user_func_array($this->filterCallback, [$this->queryObject, $filters]); } - - return $this; } /** @@ -113,10 +155,10 @@ public function filter(array $filters) { * @param array $filter * @return static */ - public function filterOne(array $filter) { + public function filterOne(array $filter): IDataSource { if (is_callable($this->filterOneCallback)) { - $this->filterOneCallback($this->queryObject, $filter); + call_user_func_array($this->filterOneCallback, [$this->queryObject, $filter]); } return $this; @@ -128,8 +170,17 @@ public function filterOne(array $filter) { * @param int $limit * @return static */ - public function limit($offset, $limit) { - $this->getResultSet()->applyPaging($offset, $limit); + public function limit($offset, $limit): IDataSource { + $defaultCallback = function () use ($offset, $limit) { + $this->getResultSet()->applyPaging($offset, $limit); + }; + + if (is_callable($this->limitCallback)) { + call_user_func_array($this->limitCallback, [$offset, $limit, $defaultCallback]); + + } else { + $defaultCallback(); + } return $this; } @@ -139,15 +190,76 @@ public function limit($offset, $limit) { * @param \Ublaboo\DataGrid\Utils\Sorting $sorting * @return static */ - public function sort(\Ublaboo\DataGrid\Utils\Sorting $sorting) { + public function sort(\Ublaboo\DataGrid\Utils\Sorting $sorting): IDataSource { + if (is_callable($sorting->getSortCallback())) { + call_user_func( + $sorting->getSortCallback(), + $this->queryObject, + array_values($sorting->getSort())[0] + ); + + } else { + + $sort = $sorting->getSort(); + + if (!empty($sort) && ($this->queryObject instanceof IQueryObject)) { + foreach ($sort as $column => $order) { + $this->queryObject->orderBy($column, $order); + } + } + } + if (is_callable($this->sortCallback)) { - $this->sortCallback($this->queryObject, $sorting); + call_user_func_array($this->sortCallback, [$this->queryObject, $sorting]); } return $this; } + /** + * @param FilterDateRange $filter + * @return array + */ + public static function parseFilterDateRange(FilterDateRange $filter) { + + $conditions = $filter->getCondition(); + + $value_from = $conditions[$filter->getColumn()]['from']; + $value_to = $conditions[$filter->getColumn()]['to']; + + if ($value_from) { + $date_from = DateTimeHelper::tryConvertToDate($value_from, [$filter->getPhpFormat()]); + $date_from->setTime(0, 0, 0); + } else { + $date_from = NULL; + } + + if ($value_to) { + $date_to = DateTimeHelper::tryConvertToDate($value_to, [$filter->getPhpFormat()]); + $date_to->setTime(23, 59, 59); + } else { + $date_to = NULL; + } + + return [ + 'from' => $date_from, + 'to' => $date_to, + ]; + } + + /** + * @param FilterDate $filter + * @return \DateTime|null + */ + public static function parseFilterDate(FilterDate $filter) { + foreach ($filter->getCondition() as $column => $value) { + $date = DateTimeHelper::tryConvertToDateTime($value, [$filter->getPhpFormat()]); + $date->setTime(0, 0, 0); + return $date; + } + } + public function getQueryObject() { return $this->queryObject; }