Completed
Pull Request — master (#218)
by
unknown
02:30
created

Model::setPaginate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 13
nc 2
nop 0
dl 0
loc 22
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
namespace Encore\Admin\Grid;
4
5
use Illuminate\Database\Eloquent\Model as EloquentModel;
6
use Illuminate\Database\Eloquent\Relations\Relation;
7
use Illuminate\Pagination\AbstractPaginator;
8
use Illuminate\Support\Collection;
9
use Illuminate\Support\Facades\Input;
10
11
class Model
12
{
13
    /**
14
     * Eloquent model instance of the grid model.
15
     *
16
     * @var EloquentModel
17
     */
18
    protected $model;
19
20
    /**
21
     * Array of queries of the eloquent model.
22
     *
23
     * @var \Illuminate\Support\Collection
24
     */
25
    protected $queries;
26
27
    /**
28
     * Sort parameters of the model.
29
     *
30
     * @var array
31
     */
32
    protected $sort;
33
34
    /**
35
     * @var array
36
     */
37
    protected $data = [];
38
39
    /*
40
     * 20 items per page as default.
41
     *
42
     * @var int
43
     */
44
    protected $perPage = 20;
45
46
    /**
47
     * If the model use pagination.
48
     *
49
     * @var bool
50
     */
51
    protected $usePaginate = true;
52
53
    /**
54
     * The query string variable used to store the per-page.
55
     *
56
     * @var string
57
     */
58
    protected $perPageName = 'per_page';
59
60
    /**
61
     * The query string variable used to store the sort.
62
     *
63
     * @var string
64
     */
65
    protected $sortName = '_sort';
66
67
    /**
68
     * Create a new grid model instance.
69
     *
70
     * @param EloquentModel $model
71
     */
72
    public function __construct(EloquentModel $model)
73
    {
74
        $this->model = $model;
75
76
        $this->queries = collect();
77
    }
78
79
    /**
80
     * Get the eloquent model of the grid model.
81
     *
82
     * @return EloquentModel
83
     */
84
    public function eloquent()
85
    {
86
        return $this->model;
87
    }
88
89
    /**
90
     * Enable or disable pagination.
91
     *
92
     * @param bool $use
93
     */
94
    public function usePaginate($use = true)
95
    {
96
        $this->usePaginate = $use;
97
    }
98
99
    /**
100
     * Get the query string variable used to store the per-page.
101
     *
102
     * @return string
103
     */
104
    public function getPerPageName()
105
    {
106
        return $this->perPageName;
107
    }
108
109
    /**
110
     * Set the query string variable used to store the per-page.
111
     *
112
     * @param string $name
113
     *
114
     * @return $this
115
     */
116
    public function setPerPageName($name)
117
    {
118
        $this->perPageName = $name;
119
120
        return $this;
121
    }
122
123
    /**
124
     * Get the query string variable used to store the sort.
125
     *
126
     * @return string
127
     */
128
    public function getSortName()
129
    {
130
        return $this->sortName;
131
    }
132
133
    /**
134
     * Set the query string variable used to store the sort.
135
     *
136
     * @param string $name
137
     *
138
     * @return $this
139
     */
140
    public function setSortName($name)
141
    {
142
        $this->sortName = $name;
143
144
        return $this;
145
    }
146
147
    /**
148
     * Build.
149
     *
150
     * @return array
151
     */
152
    public function buildData()
153
    {
154
        if (empty($this->data)) {
155
            $this->data = $this->get()->toArray();
156
        }
157
158
        return $this->data;
159
    }
160
161
    /**
162
     * Add conditions to grid model.
163
     *
164
     * @param array $conditions
165
     *
166
     * @return void
167
     */
168
    public function addConditions(array $conditions)
169
    {
170
        foreach ($conditions as $condition) {
171
            call_user_func_array([$this, key($condition)], current($condition));
172
        }
173
    }
174
175
    /**
176
     * Get table of the model.
177
     *
178
     * @return string
179
     */
180
    public function getTable()
181
    {
182
        return $this->model->getTable();
183
    }
184
185
    /**
186
     * @throws \Exception
187
     *
188
     * @return Collection
189
     */
190
    protected function get()
191
    {
192
        if ($this->model instanceof AbstractPaginator) {
193
            return $this->model;
194
        }
195
196
        $this->setSort();
197
        $this->setPaginate();
198
199
        $this->queries->unique()->each(function ($query) {
200
            $this->model = call_user_func_array([$this->model, $query['method']], $query['arguments']);
201
        });
202
203
        if ($this->model instanceof Collection) {
204
            return $this->model;
205
        }
206
207
        if ($this->model instanceof AbstractPaginator) {
208
            return $this->model->getCollection();
209
        }
210
211
        throw new \Exception('Grid query error');
212
    }
213
214
    /**
215
     * Set the grid paginate.
216
     *
217
     * @return void
218
     */
219
    protected function setPaginate()
220
    {
221
        $paginate = $this->findQueryByMethod('paginate');
222
223
        $this->queries = $this->queries->reject(function ($query) {
224
            return $query['method'] == 'paginate';
225
        });
226
227
        if (!$this->usePaginate) {
228
            $query = [
229
                'method'    => 'get',
230
                'arguments' => [],
231
            ];
232
        } else {
233
            $query = [
234
                'method'    => 'paginate',
235
                'arguments' => $this->resolvePerPage($paginate),
0 ignored issues
show
Documentation introduced by
$paginate is of type this<Encore\Admin\Grid\Model>, but the function expects a array|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
236
            ];
237
        }
238
239
        $this->queries->push($query);
240
    }
241
242
    /**
243
     * Resolve perPage for pagination.
244
     *
245
     * @param array|null $paginate
246
     *
247
     * @return array
248
     */
249
    protected function resolvePerPage($paginate)
250
    {
251
        if ($perPage = app('request')->input($this->perPageName)) {
252
            if (is_array($paginate)) {
253
                $paginate['arguments'][0] = $perPage;
254
255
                return $paginate['arguments'];
256
            }
257
258
            $this->perPage = $perPage;
259
        }
260
        
261
        if (isset($paginate['arguments'][0])) {
262
            return $paginate['arguments'];
263
        }
264
265
        return [$this->perPage];
266
    }
267
268
    /**
269
     * Find query by method name.
270
     *
271
     * @param $method
272
     *
273
     * @return static
274
     */
275
    protected function findQueryByMethod($method)
276
    {
277
        return $this->queries->first(function ($query) use ($method) {
278
            return $query['method'] == $method;
279
        });
280
    }
281
282
    /**
283
     * Set the grid sort.
284
     *
285
     * @return void
286
     */
287
    protected function setSort()
288
    {
289
        $this->sort = Input::get($this->sortName, []);
0 ignored issues
show
Documentation Bug introduced by
It seems like \Illuminate\Support\Faca...his->sortName, array()) of type * is incompatible with the declared type array of property $sort.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
290
        if (!is_array($this->sort)) {
291
            return;
292
        }
293
294
        if (empty($this->sort['column']) || empty($this->sort['type'])) {
295
            return;
296
        }
297
298
        if (str_contains($this->sort['column'], '.')) {
299
            $this->setRelationSort($this->sort['column']);
300
        } else {
301
            $this->resetOrderBy();
302
303
            $this->queries->push([
304
                'method'    => 'orderBy',
305
                'arguments' => [$this->sort['column'], $this->sort['type']],
306
            ]);
307
        }
308
    }
309
310
    /**
311
     * Set relation sort.
312
     *
313
     * @param string $column
314
     *
315
     * @return void
316
     */
317
    protected function setRelationSort($column)
318
    {
319
        list($relationName, $relationColumn) = explode('.', $column);
320
321
        if ($this->queries->contains(function ($query) use ($relationName) {
322
            return $query['method'] == 'with' && in_array($relationName, $query['arguments']);
323
        })) {
324
            $relation = $this->model->$relationName();
325
326
            $this->queries->push([
327
                'method'    => 'join',
328
                'arguments' => $this->joinParameters($relation),
329
            ]);
330
331
            $this->resetOrderBy();
332
333
            $this->queries->push([
334
                'method'    => 'orderBy',
335
                'arguments' => [
336
                    $relation->getRelated()->getTable().'.'.$relationColumn,
337
                    $this->sort['type'],
338
                ],
339
            ]);
340
        }
341
    }
342
343
    /**
344
     * Reset orderBy query.
345
     *
346
     * @return void
347
     */
348
    public function resetOrderBy()
349
    {
350
        $this->queries = $this->queries->reject(function ($query) {
351
            return $query['method'] == 'orderBy';
352
        });
353
    }
354
355
    /**
356
     * Build join parameters.
357
     *
358
     * @param Relation $relation
359
     *
360
     * @return array
361
     */
362
    protected function joinParameters(Relation $relation)
363
    {
364
        return [
365
            $relation->getRelated()->getTable(),
366
            $relation->getQualifiedParentKeyName(),
367
            '=',
368
            $relation->getForeignKey(),
369
        ];
370
    }
371
372
    /**
373
     * @param string $method
374
     * @param array  $arguments
375
     *
376
     * @return $this
377
     */
378
    public function __call($method, $arguments)
379
    {
380
        $this->queries->push([
381
            'method'    => $method,
382
            'arguments' => $arguments,
383
        ]);
384
385
        return $this;
386
    }
387
388
    /**
389
     * @param $key
390
     *
391
     * @return mixed
392
     */
393
    public function __get($key)
394
    {
395
        $data = $this->buildData();
396
397
        if (array_key_exists($key, $data)) {
398
            return $data[$key];
399
        }
400
    }
401
}
402