Completed
Push — master ( 4815cc...40c1d5 )
by Adam
03:27
created

Grid::isFilterable()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
c 1
b 0
f 0
nc 3
nop 0
dl 0
loc 13
rs 9.4285
1
<?php
2
3
namespace Boduch\Grid;
4
5
use Collective\Html\HtmlBuilder;
6
use Collective\Html\FormBuilder;
7
use Boduch\Grid\RowActions\RowAction;
8
use Boduch\Grid\Source\SourceInterface;
9
use Illuminate\Http\Request;
10
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
11
use Illuminate\Pagination\LengthAwarePaginator;
12
use Illuminate\Pagination\Paginator;
13
14
class Grid
15
{
16
    protected $template = 'laravel-grid::grid';
17
18
    /**
19
     * @var Request
20
     */
21
    protected $request;
22
23
    /**
24
     * @var ValidationFactory
25
     */
26
    protected $validator;
27
28
    /**
29
     * @var HtmlBuilder
30
     */
31
    protected $htmlBuilder;
32
33
    /**
34
     * @var FormBuilder
35
     */
36
    protected $formBuilder;
37
38
    /**
39
     * @var SourceInterface
40
     */
41
    protected $source;
42
43
    /**
44
     * @var Column[]
45
     */
46
    protected $columns = [];
47
48
    /**
49
     * @var int
50
     */
51
    protected $perPage = 15;
52
53
    /**
54
     * @var string
55
     */
56
    protected $emptyMessage = 'Brak danych do wyświetlenia.';
57
58
    /**
59
     * @var Rows
60
     */
61
    protected $rows;
62
63
    /**
64
     * Total number of records.
65
     *
66
     * @var int
67
     */
68
    protected $total = 0;
69
70
    /**
71
     * @var RowAction[]
72
     */
73
    protected $rowActions = [];
74
75
    /**
76
     * @var array
77
     */
78
    protected $defaultOrder = [
79
        'column' => 'id',
80
        'direction' => 'desc'
81
    ];
82
83
    /**
84
     * @var Order
85
     */
86
    protected $order;
87
88
    /**
89
     * @var bool
90
     */
91
    protected $enablePagination = true;
92
93
    /**
94
     * @var callable
95
     */
96
    protected $eachCallback;
97
98
    /**
99
     * @var array
100
     */
101
    protected $data = [];
102
103
    /**
104
     * @param Request $request
105
     * @param ValidationFactory $validator
106
     * @param HtmlBuilder $htmlBuilder
107
     * @param FormBuilder $formBuilder
108
     */
109
    public function __construct(
110
        Request $request,
0 ignored issues
show
Bug introduced by
You have injected the Request via parameter $request. This is generally not recommended as there might be multiple instances during a request cycle (f.e. when using sub-requests). Instead, it is recommended to inject the RequestStack and retrieve the current request each time you need it via getCurrentRequest().
Loading history...
111
        ValidationFactory $validator,
112
        HtmlBuilder $htmlBuilder,
113
        FormBuilder $formBuilder
114
    ) {
115
        $this->request = $request;
116
        $this->validator = $validator;
117
        $this->htmlBuilder = $htmlBuilder;
118
        $this->formBuilder = $formBuilder;
119
120
        $this->makeDefaultOrder();
121
    }
122
123
    public function buildGrid()
124
    {
125
        //
126
    }
127
128
    /**
129
     * @return Request
130
     */
131
    public function getRequest()
132
    {
133
        return $this->request;
134
    }
135
136
    /**
137
     * @return HtmlBuilder
138
     */
139
    public function getHtmlBuilder()
140
    {
141
        return $this->htmlBuilder;
142
    }
143
144
    /**
145
     * @return FormBuilder
146
     */
147
    public function getFormBuilder()
148
    {
149
        return $this->formBuilder;
150
    }
151
152
    /**
153
     * @param SourceInterface $source
154
     * @return $this
155
     */
156
    public function setSource(SourceInterface $source)
157
    {
158
        $this->source = $source;
159
160
        return $this;
161
    }
162
163
    /**
164
     * @param string $name
165
     * @param array $options
166
     * @return $this
167
     */
168
    public function addColumn($name, array $options = [])
169
    {
170
        if ($name instanceof Column) {
171
            $column = $name;
172
        } else {
173
            $column = $this->makeColumn($name, $options);
174
        }
175
176
        $column->setGrid($this);
177
        $this->columns[$column->getName()] = $column;
178
179
        return $this;
180
    }
181
182
    /**
183
     * @return Column[]
184
     */
185
    public function getColumns()
186
    {
187
        return $this->columns;
188
    }
189
190
    /**
191
     * @param Order $order
192
     * @return $this
193
     */
194
    public function setDefaultOrder(Order $order)
195
    {
196
        $this->order = $order;
197
198
        return $this;
199
    }
200
201
    /**
202
     * @return Order
203
     */
204
    public function getOrder()
205
    {
206
        return $this->order;
207
    }
208
209
    /**
210
     * @param int $perPage
211
     * @return $this
212
     */
213
    public function setPerPage($perPage)
214
    {
215
        $this->perPage = $perPage;
216
217
        return $this;
218
    }
219
220
    /**
221
     * @return int
222
     */
223
    public function getPerPage()
224
    {
225
        return $this->perPage;
226
    }
227
228
    /**
229
     * @return string
230
     */
231
    public function getEmptyMessage()
232
    {
233
        return $this->emptyMessage;
234
    }
235
236
    /**
237
     * @param string $emptyMessage
238
     */
239
    public function setEmptyMessage($emptyMessage)
240
    {
241
        $this->emptyMessage = $emptyMessage;
242
    }
243
244
    /**
245
     * @param RowAction $rowAction
246
     * @return $this
247
     */
248
    public function addRowAction(RowAction $rowAction)
249
    {
250
        $rowAction->setGrid($this);
251
        $this->rowActions[] = $rowAction;
252
253
        return $this;
254
    }
255
256
    /**
257
     * @param bool $flag
258
     * @return $this
259
     */
260
    public function setEnablePagination($flag)
261
    {
262
        $this->enablePagination = (bool) $flag;
263
        $this->setPerPage(null);
264
265
        return $this;
266
    }
267
268
    /**
269
     * @return bool
270
     */
271
    public function isPaginationEnabled()
272
    {
273
        return $this->enablePagination;
274
    }
275
276
    /**
277
     * @param callable $callback
278
     */
279
    public function each(callable $callback)
280
    {
281
        $this->eachCallback = $callback;
282
    }
283
284
    /**
285
     * @param array $data
286
     * @return $this
287
     */
288
    public function setData($data)
289
    {
290
        $this->data = $data;
291
292
        return $this;
293
    }
294
295
    /**
296
     * @return string
297
     */
298
    public function render()
299
    {
300
        $rows = $this->getRows();
301
        $pagination = null;
302
303
        if ($this->enablePagination) {
304
            $pagination = $this->getPaginator($rows)->appends($this->request->except('page'))->render();
305
        }
306
307
        return view($this->template, [
308
            'columns'       => $this->columns,
309
            'rows'          => $rows,
310
            'pagination'    => $pagination,
311
            'grid'          => $this,
312
            'is_filterable' => $this->isFilterable()
313
        ], $this->data);
314
    }
315
316
    /**
317
     * Is table filterable?
318
     *
319
     * @return bool
320
     */
321
    public function isFilterable()
322
    {
323
        $hasFilters = false;
324
325
        foreach ($this->columns as $column) {
326
            if ($column->isFilterable()) {
327
                $hasFilters = true;
328
                break;
329
            }
330
        }
331
332
        return $hasFilters;
333
    }
334
335
    /**
336
     * @return Rows
337
     */
338
    public function getRows()
339
    {
340
        if (empty($this->source)) {
341
            throw new \InvalidArgumentException('You MUST set the data grid source by calling setSource() method.');
342
        }
343
344
        if (!empty($this->rows)) {
345
            return $this->rows;
346
        }
347
348
        if ($this->request->has('column') && !empty($this->defaultOrder)) {
349
            $this->order = new Order(
350
                $this->request->get('column', $this->defaultOrder['column']),
351
                $this->request->get('direction', $this->defaultOrder['direction'])
352
            );
353
354
            $validator = $this->getValidatorInstance();
355
356
            if ($validator->fails()) {
357
                $this->makeDefaultOrder();
358
            }
359
        }
360
361
        $data = $this->execute();
362
        $this->rows = new Rows();
363
364
        // special column for action buttons
365
        $actions = new Column(['name' => '__actions__']);
366
        $actions->setGrid($this);
367
368
        foreach ($data as $mixed) {
369
            $row = new Row($mixed);
370
            $row->setGrid($this);
371
372
            foreach ($this->columns as $column) {
373
                $row->addCell(new Cell($column, $mixed));
374
            }
375
376
            $row->addCell(new Action($actions, $this->rowActions, $mixed));
377
378
            if ($this->eachCallback) {
379
                $this->eachCallback->call($this, $row);
380
            }
381
            $this->rows->addRow($row);
382
        }
383
384
        $this->columns[] = $actions;
385
386
        return $this->rows;
387
    }
388
389
    /**
390
     * @param Rows $rows
391
     * @return LengthAwarePaginator
392
     */
393
    protected function getPaginator(Rows $rows)
394
    {
395
        return new LengthAwarePaginator($rows, $this->total, $this->perPage, $this->resolveCurrentPage(), [
396
            'path' => $this->resolveCurrentPath(),
397
        ]);
398
    }
399
400
    /**
401
     * @return mixed
402
     */
403
    protected function execute()
404
    {
405
        $this->source->applyFilters($this->columns, $this->request);
406
407
        if ($this->enablePagination) {
408
            $this->total = $this->source->total();
409
        }
410
411
        return $this->source->execute($this->perPage, $this->resolveCurrentPage(), $this->order);
412
    }
413
414
    /**
415
     * @return int
416
     */
417
    protected function resolveCurrentPage()
418
    {
419
        return Paginator::resolveCurrentPage();
420
    }
421
422
    /**
423
     * @return string
424
     */
425
    protected function resolveCurrentPath()
426
    {
427
        return Paginator::resolveCurrentPath();
428
    }
429
430
    /**
431
     * @return \Illuminate\Contracts\Validation\Validator
432
     */
433
    protected function getValidatorInstance()
434
    {
435
        return $this->validator->make($this->request->all(), $this->getValidatorRules());
436
    }
437
438
    /**
439
     * @return array
440
     */
441
    protected function getValidatorRules()
442
    {
443
        $allowed = [];
444
445
        foreach ($this->columns as $column) {
446
            if ($column->isSortable()) {
447
                $allowed[] = $column->getName();
448
            }
449
        }
450
451
        return [
452
            'column' => 'sometimes|in:' . implode(',', $allowed),
453
            'direction' => 'sometimes|in:asc,desc'
454
        ];
455
    }
456
457
    protected function makeDefaultOrder()
458
    {
459
        $this->order = $this->defaultOrder
460
            ? new Order($this->defaultOrder['column'], $this->defaultOrder['direction'])
461
            : new Order();
462
    }
463
464
    /**
465
     * @param string $name
466
     * @param array $options
467
     * @return Column
468
     */
469
    protected function makeColumn($name, array $options = [])
470
    {
471
        $options = $this->setupColumnOptions($name, $options);
472
473
        return new Column($options);
474
    }
475
476
    /**
477
     * @param string $name
478
     * @param array $options
479
     * @return array
480
     */
481
    protected function setupColumnOptions($name, array $options)
482
    {
483
        $default = ['name' => $name];
484
485
        return array_merge($default, $options);
486
    }
487
488
    /**
489
     * @return string
490
     */
491
    public function __toString()
492
    {
493
        return (string) $this->render();
494
    }
495
}
496