Completed
Push — master ( 02e633...4815cc )
by Adam
02:37
created

Grid::getHtmlBuilder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
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
    const DEFAULT_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
        $paginator = null;
302
303
        if ($this->enablePagination) {
304
            $paginator = $this->getPaginator($rows)->appends($this->request->except('page'))->render();
305
        }
306
307
        return view(self::DEFAULT_TEMPLATE, [
308
            'columns'       => $this->columns,
309
            'rows'          => $rows,
310
            'pagination'    => $paginator,
311
            'grid'          => $this,
312
            'has_filters'   => $this->hasFilters()
313
        ], $this->data);
314
    }
315
316
    /**
317
     * @return bool
318
     */
319
    public function hasFilters()
320
    {
321
        $hasFilters = false;
322
323
        foreach ($this->columns as $column) {
324
            if ($column->isFilterable()) {
325
                $hasFilters = true;
326
                break;
327
            }
328
        }
329
330
        return $hasFilters;
331
    }
332
333
    /**
334
     * @return Rows
335
     */
336
    public function getRows()
337
    {
338
        if (empty($this->source)) {
339
            throw new \InvalidArgumentException('You MUST set the data grid source by calling setSource() method.');
340
        }
341
342
        if (!empty($this->rows)) {
343
            return $this->rows;
344
        }
345
346
        if ($this->request->has('column') && !empty($this->defaultOrder)) {
347
            $this->order = new Order(
348
                $this->request->get('column', $this->defaultOrder['column']),
349
                $this->request->get('direction', $this->defaultOrder['direction'])
350
            );
351
352
            $validator = $this->getValidatorInstance();
353
354
            if ($validator->fails()) {
355
                $this->makeDefaultOrder();
356
            }
357
        }
358
359
        $data = $this->execute();
360
        $this->rows = new Rows();
361
362
        // special column for action buttons
363
        $actions = new Column(['name' => '__actions__']);
364
        $actions->setGrid($this);
365
366
        foreach ($data as $mixed) {
367
            $row = new Row($mixed);
368
            $row->setGrid($this);
369
370
            foreach ($this->columns as $column) {
371
                $row->addCell(new Cell($column, $mixed));
372
            }
373
374
            $row->addCell(new Action($actions, $this->rowActions, $mixed));
375
376
            if ($this->eachCallback) {
377
                $this->eachCallback->call($this, $row);
378
            }
379
            $this->rows->addRow($row);
380
        }
381
382
        $this->columns[] = $actions;
383
384
        return $this->rows;
385
    }
386
387
    /**
388
     * @param Rows $rows
389
     * @return LengthAwarePaginator
390
     */
391
    protected function getPaginator(Rows $rows)
392
    {
393
        return new LengthAwarePaginator($rows, $this->total, $this->perPage, $this->resolveCurrentPage(), [
394
            'path' => $this->resolveCurrentPath(),
395
        ]);
396
    }
397
398
    /**
399
     * @return mixed
400
     */
401
    protected function execute()
402
    {
403
        $this->source->applyFilters($this->columns, $this->request);
404
405
        if ($this->enablePagination) {
406
            $this->total = $this->source->total();
407
        }
408
409
        return $this->source->execute($this->perPage, $this->resolveCurrentPage(), $this->order);
410
    }
411
412
    /**
413
     * @return int
414
     */
415
    protected function resolveCurrentPage()
416
    {
417
        return Paginator::resolveCurrentPage();
418
    }
419
420
    /**
421
     * @return string
422
     */
423
    protected function resolveCurrentPath()
424
    {
425
        return Paginator::resolveCurrentPath();
426
    }
427
428
    /**
429
     * @return \Illuminate\Contracts\Validation\Validator
430
     */
431
    protected function getValidatorInstance()
432
    {
433
        return $this->validator->make($this->request->all(), $this->getValidatorRules());
434
    }
435
436
    /**
437
     * @return array
438
     */
439
    protected function getValidatorRules()
440
    {
441
        $allowed = [];
442
443
        foreach ($this->columns as $column) {
444
            if ($column->isSortable()) {
445
                $allowed[] = $column->getName();
446
            }
447
        }
448
449
        return [
450
            'column' => 'sometimes|in:' . implode(',', $allowed),
451
            'direction' => 'sometimes|in:asc,desc'
452
        ];
453
    }
454
455
    protected function makeDefaultOrder()
456
    {
457
        $this->order = $this->defaultOrder
458
            ? new Order($this->defaultOrder['column'], $this->defaultOrder['direction'])
459
            : new Order();
460
    }
461
462
    /**
463
     * @param string $name
464
     * @param array $options
465
     * @return Column
466
     */
467
    protected function makeColumn($name, array $options = [])
468
    {
469
        $options = $this->setupColumnOptions($name, $options);
470
471
        return new Column($options);
472
    }
473
474
    /**
475
     * @param string $name
476
     * @param array $options
477
     * @return array
478
     */
479
    protected function setupColumnOptions($name, array $options)
480
    {
481
        $default = ['name' => $name];
482
483
        return array_merge($default, $options);
484
    }
485
486
    /**
487
     * @return string
488
     */
489
    public function __toString()
490
    {
491
        return (string) $this->render();
492
    }
493
}
494