BuilderOverride::applyOrderByClauses()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 6
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 8
ccs 7
cts 7
cp 1
crap 4
rs 10
1
<?php
2
3
namespace Okipa\LaravelModelJsonStorage;
4
5
use Illuminate\Database\Eloquent\ModelNotFoundException;
6
use Illuminate\Pagination\LengthAwarePaginator;
7
use Illuminate\Pagination\Paginator;
8
use Illuminate\Support\Collection;
9
10
trait BuilderOverride
11
{
12
    /**
13
     * The "select" clauses of the query.
14
     *
15
     * @var array
16
     */
17
    protected $selects = [];
18
    /**
19
     * The "where" clauses of the query.
20
     *
21
     * @var array
22
     */
23
    protected $wheres = [];
24
    /**
25
     * The "whereIn" clauses of the query.
26
     *
27
     * @var array
28
     */
29
    protected $whereIns = [];
30
    /**
31
     * The "whereNotIn" clauses of the query.
32
     *
33
     * @var array
34
     */
35
    protected $whereNotIns = [];
36
    /**
37
     * The "orderBy" clauses of the query.
38
     *
39
     * @var array
40
     */
41
    protected $orderBys = [];
42
43
    /**
44
     * Get the number of models to return per page.
45
     *
46
     * @return int
47
     */
48
    abstract public function getPerPage();
49
50
    /**
51
     * Set the column to be selected.
52
     *
53
     * @param  string $column
54
     *
55
     * @return $this
56
     */
57 2
    public function select(string $column)
58
    {
59 2
        $this->selects[] = $column;
60
61 2
        return $this;
62
    }
63
64
    /**
65
     * Add a new select column to the query.
66
     *
67
     * @param  string $column
68
     *
69
     * @return $this
70
     */
71 1
    public function addSelect(string $column)
72
    {
73 1
        $this->selects[] = $column;
74
75 1
        return $this;
76
    }
77
78
    /**
79
     * Add a "where in" clause to the query.
80
     *
81
     * @param string $column
82
     * @param array  $values
83
     *
84
     * @return $this
85
     */
86 1
    public function whereIn(string $column, array $values)
87
    {
88 1
        $this->whereIns[] = compact('column', 'values');
89
90 1
        return $this;
91
    }
92
93
    /**
94
     * Add a "where not in" clause to the query.
95
     *
96
     * @param string $column
97
     * @param array  $values
98
     *
99
     * @return $this
100
     */
101 4
    public function whereNotIn(string $column, array $values)
102
    {
103 4
        $this->whereNotIns[] = compact('column', 'values');
104
105 4
        return $this;
106
    }
107
108
    /**
109
     * Add an "order by" clause to the query.
110
     *
111
     * @param  string $column
112
     * @param  string $direction
113
     *
114
     * @return $this
115
     */
116 1
    public function orderBy(string $column, string $direction = 'asc')
117
    {
118 1
        $this->orderBys[] = compact('column', 'direction');
119
120 1
        return $this;
121
    }
122
123
    /**
124
     * Find a model by its primary key or throw an exception.
125
     *
126
     * @param  mixed $id
127
     * @param  array $columns
128
     *
129
     * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection
130
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
131
     */
132 1
    public function findOrFail(int $id, array $columns = ['*'])
133
    {
134 1
        $result = $this->find($id, $columns);
135 1
        if (! is_null($result)) {
136 1
            return $result;
137
        }
138
        throw (new ModelNotFoundException)->setModel(
139
            get_class($this), $id
140
        );
141
    }
142
143
    /**
144
     * Execute a query for a single record by ID.
145
     *
146
     * @param  int   $id
147
     * @param  array $columns
148
     *
149
     * @return mixed|static
150
     */
151 2
    public function find(int $id, array $columns = ['*'])
152
    {
153 2
        return $this->where('id', '=', $id)->first($columns);
154
    }
155
156
    /**
157
     * Execute the query and get the first result.
158
     *
159
     * @param  array $columns
160
     *
161
     * @return Model|null
162
     */
163
    abstract public function first(array $columns = ['*']);
164
165
    /**
166
     * Add a basic where clause to the query.
167
     *
168
     * @param  string $column
169
     * @param  mixed  $operator
170
     * @param  mixed  $value
171
     *
172
     * @return $this
173
     */
174 4
    public function where(string $column, $operator = null, $value = null)
175
    {
176 4
        if (! isset($value)) {
177 2
            $value = $operator;
178 2
            $operator = '=';
179
        }
180 4
        $this->wheres[] = compact('column', 'operator', 'value');
181
182 4
        return $this;
183
    }
184
185
    /**
186
     * Get a single column's value from the first result of a query.
187
     *
188
     * @param string $column
189
     * The "pluck" collection method is used under the hood.
190
     *
191
     * @return Collection
192
     */
193 1
    public function value(string $column)
194
    {
195 1
        return $this->get()->pluck($column)->first();
196
    }
197
198
    /**
199
     * Execute the query as a "select" statement.
200
     *
201
     * @param  array $columns
202
     *
203
     * @return Collection
204
     */
205 22
    public function get(array $columns = ['*'])
206
    {
207 22
        if ($columns !== ['*']) {
208 2
            $this->selects = $columns;
209
        }
210 22
        $modelsCollection = $this->loadModelsFromJson();
211 22
        $this->applyWhereClauses($modelsCollection);
212 22
        $this->applyWhereInClauses($modelsCollection);
213 22
        $this->applyWhereNotInClauses($modelsCollection);
214 22
        $this->applyOrderByClauses($modelsCollection);
215 22
        $this->applySelectClauses($modelsCollection);
216
217 22
        return $modelsCollection->values();
218
    }
219
220
    /**
221
     * Apply the "where" clauses on the collection.
222
     *
223
     * @param $modelsCollection
224
     *
225
     * @return void
226
     */
227 22
    protected function applyWhereClauses(Collection &$modelsCollection)
228
    {
229 22
        if (! empty($this->wheres) && ! $modelsCollection->isEmpty()) {
230 4
            foreach ($this->wheres as $where) {
231 4
                $modelsCollection = $modelsCollection->where($where['column'], $where['operator'], $where['value']);
232
            }
233
        }
234 22
    }
235
236
    /**
237
     * Apply the "whereIn" clauses on the collection.
238
     *
239
     * @param $modelsCollection
240
     *
241
     * @return void
242
     */
243 22
    protected function applyWhereInClauses(Collection &$modelsCollection)
244
    {
245 22
        if (! empty($this->whereIns) && ! $modelsCollection->isEmpty()) {
246 1
            foreach ($this->whereIns as $whereIn) {
247 1
                $modelsCollection = $modelsCollection->whereIn($whereIn['column'], $whereIn['values']);
248
            }
249
        }
250 22
    }
251
252
    /**
253
     * Apply the "whereNotIn" clauses on the collection.
254
     *
255
     * @param $modelsCollection
256
     *
257
     * @return void
258
     */
259 22
    protected function applyWhereNotInClauses(Collection &$modelsCollection)
260
    {
261 22
        if (! empty($this->whereNotIns) && ! $modelsCollection->isEmpty()) {
262 4
            foreach ($this->whereNotIns as $whereNotIn) {
263 4
                $modelsCollection = $modelsCollection->whereNotIn($whereNotIn['column'], $whereNotIn['values']);
264
            }
265
        }
266 22
    }
267
268
    /**
269
     * Apply the "orderBy" clauses on the collection.
270
     *
271
     * @param $modelsCollection
272
     *
273
     * @return void
274
     */
275 22
    protected function applyOrderByClauses(Collection &$modelsCollection)
276
    {
277 22
        if (! empty($this->orderBys) && ! $modelsCollection->isEmpty()) {
278 1
            foreach ($this->orderBys as $orders) {
279 1
                $modelsCollection = $modelsCollection->sortBy(
280 1
                    $orders['column'],
281 1
                    SORT_REGULAR,
282 1
                    $orders['direction'] === 'desc'
283
                );
284
            }
285
        }
286 22
    }
287
288
    /**
289
     * Apply the "select" clauses on the collection.
290
     *
291
     * @param $modelsCollection
292
     *
293
     * @return void
294
     */
295 22
    protected function applySelectClauses(Collection &$modelsCollection)
296
    {
297 22
        if (! empty($this->selects) && $this->selects !== ['*'] && ! $modelsCollection->isEmpty()) {
298 4
            $selectCollection = new Collection();
299
            $modelsCollection->each(function($model) use ($selectCollection) {
300 4
                $selectCollection->push(collect($model->toArray())->only(array_unique($this->selects)));
301 4
            });
302 4
            $modelsCollection = $selectCollection;
303
        }
304 22
    }
305
306
    /**
307
     * Get an array with the values of a given column.
308
     *
309
     * @param string $column
310
     * @param string null|$key
0 ignored issues
show
Documentation Bug introduced by
The doc comment null|$key at position 2 could not be parsed: Unknown type name '$key' at position 2 in null|$key.
Loading history...
311
     *
312
     * @return Collection
313
     */
314 1
    public function pluck(string $column, string $key = null)
315
    {
316 1
        return $this->get()->pluck($column, $key);
317
    }
318
319
    /**
320
     * Retrieve the "count" result of the query.
321
     *
322
     * @param  array $columns
323
     *
324
     * @return int
325
     */
326 1
    public function count(array $columns = ['*'])
327
    {
328 1
        return $this->get($columns)->count();
329
    }
330
331
    /**
332
     * Retrieve the minimum value of a given column.
333
     *
334
     * @param $column
335
     *
336
     * @return int
337
     */
338 1
    public function min(string $column)
339
    {
340 1
        return $this->get()->min($column);
341
    }
342
343
    /**
344
     * Retrieve the maximum value of a given column.
345
     *
346
     * @param  string $column
347
     *
348
     * @return int
349
     */
350 1
    public function max(string $column)
351
    {
352 1
        return $this->get()->max($column);
353
    }
354
355
    /**
356
     * Retrieve the average of the values of a given column.
357
     *
358
     * @param  string $column
359
     *
360
     * @return mixed
361
     */
362 1
    public function avg($column)
363
    {
364 1
        return $this->get()->avg($column);
365
    }
366
367
    /**
368
     * Paginate the given query.
369
     *
370
     * @param  int|null $perPage
371
     * @param  array    $columns
372
     * @param  string   $pageName
373
     * @param  int|null $page
374
     *
375
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
376
     * @throws \InvalidArgumentException
377
     */
378 1
    public function paginate(int $perPage = null, array $columns = ['*'], string $pageName = 'page', int $page = null)
379
    {
380 1
        $page = $page ?: Paginator::resolveCurrentPage($pageName);
381 1
        $perPage = $perPage ?: $this->getPerPage();
382 1
        $modelsCollection = $this->get($columns);
383 1
        $items = $modelsCollection->forPage($page, $perPage)->values();
384 1
        $total = $modelsCollection->count();
385
386 1
        return new LengthAwarePaginator(
387 1
            $items,
388 1
            $total,
389 1
            $perPage,
390 1
            $page,
391
            [
392 1
                'path'     => Paginator::resolveCurrentPath(),
393 1
                'pageName' => $pageName,
394
            ]
395
        );
396
    }
397
398
    /**
399
     * Load all of the models from the json file in the "modelsFromJson" variable.
400
     *
401
     * @return Collection
402
     */
403
    abstract protected function loadModelsFromJson();
404
}
405