Completed
Push — master ( c14a57...b2a365 )
by Pavel
04:09
created

DataGrid::setConfigurationOptions()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 1
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
4
namespace Pfilsx\DataGrid\Grid;
5
6
7
use Pfilsx\DataGrid\Grid\Columns\AbstractColumn;
8
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
9
use Doctrine\Common\Collections\Criteria;
10
use Symfony\Component\Routing\RouterInterface;
11
use Twig\Environment;
12
use Twig\Template;
13
14
/**
15
 * Class DataGrid
16
 * @package Pfilsx\DataGrid\Grid
17
 * @internal
18
 */
19
class DataGrid
20
{
21
    /**
22
     * @var AbstractColumn[]
23
     */
24
    protected $columns = [];
25
    /**
26
     * @var bool
27
     */
28
    protected $hasFilters = false;
29
    /**
30
     * @var bool
31
     */
32
    protected $showTitles = true;
33
    /**
34
     * @var ServiceEntityRepository
35
     */
36
    protected $repository;
37
38
    /**
39
     * @var Template
40
     */
41
    protected $template;
42
    /**
43
     * @var RouterInterface
44
     */
45
    protected $router;
46
    /**
47
     * @var Environment
48
     */
49
    protected $twig;
50
51
    protected $noDataMessage = 'No data found';
52
53
    protected $sort = [];
54
55
    protected $limit = null;
56
57
    protected $page = 1;
58
59
    protected $maxPage;
60
61
    protected $pagination = false;
62
63
    protected $paginationOptions = [
64
        'limit' => 10
65
    ];
66
67
68
    /**
69
     * @var Criteria
70
     */
71
    protected $filtersCriteria;
72
73
    /**
74
     * DataGrid constructor.
75
     * @param ServiceEntityRepository $repository
76
     * @param array $columns
77
     * @param array $options
78
     * @internal
79
     */
80
    public function __construct(ServiceEntityRepository $repository, array $columns, array $options = [])
81
    {
82
        $this->repository = $repository;
83
        $this->columns = $columns;
84
        $this->twig = $options['twig'];
85
        $this->setConfigurationOptions($options);
86
87
        foreach ($columns as $column) {
88
            if ($column->hasFilter() && $column->isVisible()) {
89
                $this->hasFilters = true;
90
                break;
91
            }
92
        }
93
94
        if ($this->hasPagination()) {
95
            $this->rebuildPaginationOptions();
96
        }
97
    }
98
99
    /**
100
     * @internal
101
     * @param $options
102
     */
103
    protected function setConfigurationOptions($options)
104
    {
105
        foreach ($options as $key => $value) {
106
            $setter = 'set' . ucfirst($key);
107
            if (method_exists($this, $setter)) {
108
                $this->$setter($value);
109
            }
110
        }
111
    }
112
113
    public function getShowTitles()
114
    {
115
        return $this->showTitles;
116
    }
117
118
    protected function setShowTitles($value)
119
    {
120
        $this->showTitles = (bool)$value;
121
    }
122
123
    public function getRepository()
124
    {
125
        return $this->repository;
126
    }
127
128
    public function getColumns()
129
    {
130
        return $this->columns;
131
    }
132
133
    public function hasFilters()
134
    {
135
        return $this->hasFilters;
136
    }
137
138
    public function getData()
139
    {
140
        $this->filtersCriteria
141
            ->orderBy($this->sort)
142
            ->setMaxResults($this->hasPagination() ? $this->limit : null)
143
            ->setFirstResult($this->hasPagination() ? ($this->page - 1) * $this->limit : null);
144
        return $this->repository->matching($this->filtersCriteria);
145
    }
146
147
    /**
148
     * @return Template
149
     */
150
    public function getTemplate()
151
    {
152
        return $this->template;
153
    }
154
155
    /**
156
     * @internal
157
     * @param string $path
158
     * @throws \Twig\Error\LoaderError
159
     * @throws \Twig\Error\RuntimeError
160
     * @throws \Twig\Error\SyntaxError
161
     */
162
    public function setTemplate(string $path)
163
    {
164
        $template = $this->twig->loadTemplate($path);
165
        $this->template = $template;
166
    }
167
168
    public function getRouter()
169
    {
170
        return $this->router;
171
    }
172
173
    protected function setRouter(RouterInterface $router)
174
    {
175
        $this->router = $router;
176
    }
177
178
    public function getNoDataMessage()
179
    {
180
        return $this->noDataMessage;
181
    }
182
183
    protected function setNoDataMessage(string $message)
184
    {
185
        $this->noDataMessage = $message;
186
    }
187
188
    protected function setSort(array $sort)
189
    {
190
        list($attribute, $direction) = $sort;
191
        foreach ($this->columns as $column) {
192
            if ($column->hasSort() && $column->getAttribute() == $attribute) {
193
                $column->setSort($direction);
194
                $this->sort = [$attribute => $direction];
195
                break;
196
            }
197
        }
198
    }
199
200
    protected function setPage(int $page)
201
    {
202
        $this->page = $page;
203
    }
204
205
    protected function setPagination(bool $value)
206
    {
207
        $this->pagination = $value;
208
    }
209
210
    public function hasPagination()
211
    {
212
        return $this->pagination && is_numeric($this->paginationOptions['limit']);
213
    }
214
215
    protected function setPaginationOptions(array $options)
216
    {
217
        $this->paginationOptions = array_merge($this->paginationOptions, $options);
218
    }
219
220
    public function getPaginationOptions()
221
    {
222
        return $this->paginationOptions;
223
    }
224
225
    protected function setFiltersCriteria(Criteria $criteria)
226
    {
227
        $this->filtersCriteria = $criteria;
228
    }
229
230
    /**
231
     * @internal
232
     */
233
    protected function rebuildPaginationOptions()
234
    {
235
        $this->limit = $this->paginationOptions['limit'];
236
        $total = $this->repository->matching($this->filtersCriteria)->count();
237
        $this->maxPage = (int)ceil($total / $this->limit);
238
        $this->page = $this->page != null && $this->page > 0 && $this->page <= $this->maxPage
239
            ? $this->page : 1;
240
241
        $this->paginationOptions['pages'] = $this->calculatePages();
242
        $this->paginationOptions['currentPage'] = $this->page;
243
    }
244
245
    protected function calculatePages()
246
    {
247
        if ($this->maxPage == 0) {
248
            return [1];
249
        }
250
        if ($this->maxPage <= 10) {
251
            return range(1, $this->maxPage);
252
        }
253
        if ($this->page < 5) {
254
            return array_merge(range(1, 6), [null, $this->maxPage]);
255
        }
256
        if ($this->page > $this->maxPage - 4) {
257
            return array_merge([1, null], range($this->maxPage - 5, $this->maxPage));
258
        }
259
        return array_merge([1, null], range($this->page - 2, $this->page + 2), [null, $this->maxPage]);
260
    }
261
}
262