Skip to content

Commit 6b9e24d

Browse files
authored
Merge pull request #1 from peckadesign/can-switch-datamodel
Can change grid datamodel
2 parents ef9e02a + eab3226 commit 6b9e24d

5 files changed

+173
-7
lines changed

src/DataGrid.php

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@
3636
use Ublaboo\DataGrid\Column\MultiAction;
3737
use Ublaboo\DataGrid\Components\DataGridPaginator\DataGridPaginator;
3838
use Ublaboo\DataGrid\DataSource\IDataSource;
39+
use Ublaboo\DataGrid\Exception\CannotChangeDataModelException;
3940
use Ublaboo\DataGrid\Exception\DataGridColumnNotFoundException;
4041
use Ublaboo\DataGrid\Exception\DataGridException;
4142
use Ublaboo\DataGrid\Exception\DataGridFilterNotFoundException;
4243
use Ublaboo\DataGrid\Exception\DataGridHasToBeAttachedToPresenterComponentException;
44+
use Ublaboo\DataGrid\Exception\InitializingDataModelCallbacksException;
4345
use Ublaboo\DataGrid\Export\Export;
4446
use Ublaboo\DataGrid\Export\ExportCsv;
4547
use Ublaboo\DataGrid\Filter\Filter;
@@ -237,7 +239,7 @@ class DataGrid extends Control
237239
protected $toolbarButtons = [];
238240

239241
/**
240-
* @var DataModel|null
242+
* @var DataModelInterface|null
241243
*/
242244
protected $dataModel;
243245

@@ -494,7 +496,7 @@ public function render(): void
494496
/**
495497
* Check whether datagrid has set some columns, initiated data source, etc
496498
*/
497-
if (!($this->dataModel instanceof DataModel)) {
499+
if (!($this->dataModel instanceof DataModelInterface)) {
498500
throw new DataGridException('You have to set a data source first.');
499501
}
500502

@@ -623,7 +625,7 @@ public function setRowCallback(callable $callback): self
623625
*/
624626
public function setPrimaryKey(string $primaryKey): self
625627
{
626-
if ($this->dataModel instanceof DataModel) {
628+
if ($this->dataModel instanceof DataModelInterface) {
627629
throw new DataGridException('Please set datagrid primary key before setting datasource.');
628630
}
629631

@@ -637,14 +639,26 @@ public function setPrimaryKey(string $primaryKey): self
637639
* @param mixed $source
638640
* @return static
639641
* @throws InvalidArgumentException
642+
* @throws InitializingDataModelCallbacksException
640643
*/
641644
public function setDataSource($source): self
642645
{
643646
$this->dataModel = new DataModel($source, $this->primaryKey);
644647

645-
$this->dataModel->onBeforeFilter[] = [$this, 'beforeDataModelFilter'];
646-
$this->dataModel->onAfterFilter[] = [$this, 'afterDataModelFilter'];
647-
$this->dataModel->onAfterPaginated[] = [$this, 'afterDataModelPaginated'];
648+
$this->initializeCallbacks();
649+
650+
return $this;
651+
}
652+
653+
654+
/**
655+
* @throws InitializingDataModelCallbacksException
656+
*/
657+
public function setDataModel(DataModelInterface $dataModel): self
658+
{
659+
$this->dataModel = $dataModel;
660+
661+
$this->initializeCallbacks();
648662

649663
return $this;
650664
}
@@ -3324,4 +3338,16 @@ private function getPresenterInstance(): Presenter
33243338
return $this->getPresenter();
33253339
}
33263340

3341+
3342+
private function initializeCallbacks(): void
3343+
{
3344+
if ($this->dataModel === null) {
3345+
throw new InitializingDataModelCallbacksException();
3346+
}
3347+
3348+
$this->dataModel->onBeforeFilter[] = [$this, 'beforeDataModelFilter'];
3349+
$this->dataModel->onAfterFilter[] = [$this, 'afterDataModelFilter'];
3350+
$this->dataModel->onAfterPaginated[] = [$this, 'afterDataModelPaginated'];
3351+
}
3352+
33273353
}

src/DataModel.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
* @method onAfterFilter(IDataSource $dataSource)
3232
* @method onAfterPaginated(IDataSource $dataSource)
3333
*/
34-
final class DataModel
34+
final class DataModel implements DataModelInterface
3535
{
3636

3737
use SmartObject;

src/DataModelInterface.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php declare(strict_types = 1);
2+
namespace Ublaboo\DataGrid;
3+
4+
5+
use Ublaboo\DataGrid\Components\DataGridPaginator\DataGridPaginator;
6+
use Ublaboo\DataGrid\DataSource\IDataSource;
7+
use Ublaboo\DataGrid\Utils\Sorting;
8+
9+
/**
10+
* @method onBeforeFilter(IDataSource $dataSource)
11+
* @method onAfterFilter(IDataSource $dataSource)
12+
* @method onAfterPaginated(IDataSource $dataSource)
13+
*/
14+
interface DataModelInterface
15+
{
16+
17+
public function getDataSource(): IDataSource;
18+
19+
20+
public function filterData(?DataGridPaginator $paginatorComponent, Sorting $sorting, array $filters): iterable;
21+
22+
23+
/**
24+
* @return mixed
25+
*/
26+
public function filterRow(array $condition);
27+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Ublaboo\DataGrid\Exception;
4+
5+
use Throwable;
6+
7+
class InitializingDataModelCallbacksException extends DataGridException
8+
{
9+
public function __construct(?Throwable $previous = null)
10+
{
11+
parent::__construct("Cannot set callbacks before data model is set.", 0, $previous);
12+
}
13+
}

src/RestBasedDataModel.php

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace Ublaboo\DataGrid;
6+
7+
use Nette\SmartObject;
8+
use Ublaboo\DataGrid\Components\DataGridPaginator\DataGridPaginator;
9+
use Ublaboo\DataGrid\DataSource\IDataSource;
10+
use Ublaboo\DataGrid\Utils\Sorting;
11+
12+
/**
13+
* @method onBeforeFilter(IDataSource $dataSource)
14+
* @method onAfterFilter(IDataSource $dataSource)
15+
* @method onAfterPaginated(IDataSource $dataSource)
16+
*/
17+
final class RestBasedDataModel implements DataModelInterface
18+
{
19+
20+
use SmartObject;
21+
22+
/**
23+
* @var array|callable[]
24+
*/
25+
public $onBeforeFilter = [];
26+
27+
/**
28+
* @var array|callable[]
29+
*/
30+
public $onAfterFilter = [];
31+
32+
/**
33+
* @var array|callable[]
34+
*/
35+
public $onAfterPaginated = [];
36+
37+
/**
38+
* @var IDataSource
39+
*/
40+
private $dataSource;
41+
42+
43+
public function __construct(IDataSource $source)
44+
{
45+
$this->dataSource = $source;
46+
}
47+
48+
49+
public function getDataSource(): IDataSource
50+
{
51+
return $this->dataSource;
52+
}
53+
54+
55+
public function filterData(
56+
?DataGridPaginator $paginatorComponent,
57+
Sorting $sorting,
58+
array $filters
59+
): iterable
60+
{
61+
$this->onBeforeFilter($this->dataSource);
62+
63+
$this->dataSource->filter($filters);
64+
65+
$this->onAfterFilter($this->dataSource);
66+
67+
/**
68+
* Paginator is optional
69+
*/
70+
if ($paginatorComponent !== null) {
71+
$paginator = $paginatorComponent->getPaginator();
72+
73+
$this->dataSource->sort($sorting)->limit(
74+
$paginator->getOffset(),
75+
$paginator->getItemsPerPage()
76+
);
77+
78+
$this->onAfterPaginated($this->dataSource);
79+
80+
$data = $this->dataSource->getData();
81+
$paginator->setItemCount($this->dataSource->getCount());
82+
83+
return $data;
84+
}
85+
86+
return $this->dataSource->sort($sorting)->getData();
87+
}
88+
89+
90+
/**
91+
* @return mixed
92+
*/
93+
public function filterRow(array $condition)
94+
{
95+
$this->onBeforeFilter($this->dataSource);
96+
$this->onAfterFilter($this->dataSource);
97+
98+
return $this->dataSource->filterOne($condition)->getData();
99+
}
100+
}

0 commit comments

Comments
 (0)