Completed
Push — develop ( 6c1fc8...1958ec )
by Abdelrahman
02:06
created

BaseRepository::orderBy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
3
/*
4
 * NOTICE OF LICENSE
5
 *
6
 * Part of the Rinvex Repository Package.
7
 *
8
 * This source file is subject to The MIT License (MIT)
9
 * that is bundled with this package in the LICENSE file.
10
 *
11
 * Package: Rinvex Repository Package
12
 * License: The MIT License (MIT)
13
 * Link:    https://rinvex.com
14
 */
15
16
namespace Rinvex\Repository\Repositories;
17
18
use Closure;
19
use Rinvex\Repository\Traits\Cacheable;
20
use Illuminate\Contracts\Container\Container;
21
use Rinvex\Repository\Contracts\CacheableContract;
22
use Rinvex\Repository\Contracts\RepositoryContract;
23
24
abstract class BaseRepository implements RepositoryContract, CacheableContract
25
{
26
    use Cacheable;
27
28
    /**
29
     * The IoC container instance.
30
     *
31
     * @var \Illuminate\Contracts\Container\Container
32
     */
33
    protected $container;
34
35
    /**
36
     * The connection name for the repository.
37
     *
38
     * @var string
39
     */
40
    protected $connection;
41
42
    /**
43
     * The repository identifier.
44
     *
45
     * @var string
46
     */
47
    protected $repositoryId;
48
49
    /**
50
     * The repository model.
51
     *
52
     * @var string
53
     */
54
    protected $model;
55
56
    /**
57
     * The relations to eager load on query execution.
58
     *
59
     * @var array
60
     */
61
    protected $relations = [];
62
63
    /**
64
     * The query where clauses.
65
     *
66
     * @var array
67
     */
68
    protected $where = [];
69
70
    /**
71
     * The query whereIn clauses.
72
     *
73
     * @var array
74
     */
75
    protected $whereIn = [];
76
77
    /**
78
     * The query whereNotIn clauses.
79
     *
80
     * @var array
81
     */
82
    protected $whereNotIn = [];
83
84
    /**
85
     * The query whereHas clauses.
86
     *
87
     * @var array
88
     */
89
    protected $whereHas = [];
90
91
    /**
92
     * The "offset" value of the query.
93
     *
94
     * @var int
95
     */
96
    protected $offset;
97
98
    /**
99
     * The "limit" value of the query.
100
     *
101
     * @var int
102
     */
103
    protected $limit;
104
105
    /**
106
     * The column to order results by.
107
     *
108
     * @var array
109
     */
110
    protected $orderBy = [];
111
112
    /**
113
     * The column to order results by.
114
     *
115
     * @var array
116
     */
117
    protected $groupBy = [];
118
119
    /**
120
     * The query having clauses.
121
     *
122
     * @var array
123
     */
124
    protected $having = [];
125
126
    /**
127
     * Execute given callback and return the result.
128
     *
129
     * @param string   $class
130
     * @param string   $method
131
     * @param array    $args
132
     * @param \Closure $closure
133
     *
134
     * @return mixed
135
     */
136
    protected function executeCallback($class, $method, $args, Closure $closure)
137
    {
138
        $skipUri = $this->getContainer('config')->get('rinvex.repository.cache.skip_uri');
139
140
        // Check if cache is enabled
141
        if ($this->getCacheLifetime() && ! $this->getContainer('request')->has($skipUri)) {
142
            return $this->cacheCallback($class, $method, $args, $closure);
143
        }
144
145
        // Cache disabled, just execute query & return result
146
        $result = call_user_func($closure);
147
148
        // We're done, let's clean up!
149
        $this->resetRepository();
150
151
        return $result;
152
    }
153
154
    /**
155
     * Reset repository to its defaults.
156
     *
157
     * @return $this
158
     */
159
    protected function resetRepository()
160
    {
161
        $this->relations  = [];
162
        $this->where      = [];
163
        $this->whereIn    = [];
164
        $this->whereNotIn = [];
165
        $this->whereHas   = [];
166
        $this->offset     = null;
167
        $this->limit      = null;
168
        $this->orderBy    = [];
169
        $this->groupBy    = [];
170
        $this->having     = [];
171
172
        if (method_exists($this, 'flushCriteria')) {
173
            $this->flushCriteria();
0 ignored issues
show
Documentation Bug introduced by
The method flushCriteria does not exist on object<Rinvex\Repository...itories\BaseRepository>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
174
        }
175
176
        return $this;
177
    }
178
179
    /**
180
     * Prepare query.
181
     *
182
     * @param object $model
183
     *
184
     * @return mixed
185
     */
186
    protected function prepareQuery($model)
187
    {
188
        // Set the relationships that should be eager loaded
189
        if (! empty($this->relations)) {
190
            $model = $model->with($this->relations);
191
        }
192
193
        // Add a basic where clause to the query
194
        foreach ($this->where as $where) {
195
            list($attribute, $operator, $value, $boolean) = array_pad($where, 4, null);
196
197
            $model = $model->where($attribute, $operator, $value, $boolean);
198
        }
199
200
        // Add a "where in" clause to the query
201
        foreach ($this->whereIn as $whereIn) {
202
            list($attribute, $values, $boolean, $not) = array_pad($whereIn, 4, null);
203
204
            $model = $model->whereIn($attribute, $values, $boolean, $not);
205
        }
206
207
        // Add a "where not in" clause to the query
208
        foreach ($this->whereNotIn as $whereNotIn) {
209
            list($attribute, $values, $boolean) = array_pad($whereNotIn, 3, null);
210
211
            $model = $model->whereNotIn($attribute, $values, $boolean);
212
        }
213
214
        // Add a "where has" clause to the query
215
        foreach ($this->whereHas as $whereHas) {
216
            list($relation, $callback, $operator, $count) = array_pad($whereHas, 4, null);
217
218
            $model = $model->whereHas($relation, $callback, $operator, $count);
219
        }
220
221
        // Set the "offset" value of the query
222
        if ($this->offset > 0) {
223
            $model = $model->offset($this->offset);
224
        }
225
226
        // Set the "limit" value of the query
227
        if ($this->limit > 0) {
228
            $model = $model->limit($this->limit);
229
        }
230
231
        // Add an "order by" clause to the query.
232
        if (! empty($this->orderBy)) {
233
            list($attribute, $direction) = $this->orderBy;
234
235
            $model = $model->orderBy($attribute, $direction);
236
        }
237
238
        // Add an "group by" clause to the query.
239
        if (! empty($this->groupBy)) {
240
            foreach ($this->groupBy as $group) {
241
                $model = $model->groupBy($group);
242
            }
243
        }
244
245
        // Add a "having" clause to the query
246
        foreach ($this->having as $having) {
247
            list($column, $operator, $value, $boolean) = array_pad($having, 4, null);
248
249
            $model = $model->having($column, $operator, $value, $boolean);
250
        }
251
252
        // Apply all criteria to the query
253
        if (method_exists($this, 'applyCriteria')) {
254
            $model = $this->applyCriteria($model, $this);
0 ignored issues
show
Documentation Bug introduced by
The method applyCriteria does not exist on object<Rinvex\Repository...itories\BaseRepository>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
255
        }
256
257
        return $model;
258
    }
259
260
    /**
261
     * {@inheritdoc}
262
     */
263
    public function setContainer(Container $container)
264
    {
265
        $this->container = $container;
266
267
        return $this;
268
    }
269
270
    /**
271
     * {@inheritdoc}
272
     */
273
    public function getContainer($service = null)
274
    {
275
        return is_null($service) ? ($this->container ?: app()) : ($this->container[$service] ?: app($service));
276
    }
277
278
    /**
279
     * {@inheritdoc}
280
     */
281
    public function setConnection($name)
282
    {
283
        $this->connection = $name;
284
285
        return $this;
286
    }
287
288
    /**
289
     * {@inheritdoc}
290
     */
291
    public function getConnection()
292
    {
293
        return $this->connection;
294
    }
295
296
    /**
297
     * {@inheritdoc}
298
     */
299
    public function setRepositoryId($repositoryId)
300
    {
301
        $this->repositoryId = $repositoryId;
302
303
        return $this;
304
    }
305
306
    /**
307
     * {@inheritdoc}
308
     */
309
    public function getRepositoryId()
310
    {
311
        return $this->repositoryId ?: get_called_class();
312
    }
313
314
    /**
315
     * {@inheritdoc}
316
     */
317
    public function setModel($model)
318
    {
319
        $this->model = $model;
320
321
        return $this;
322
    }
323
324
    /**
325
     * {@inheritdoc}
326
     */
327
    public function getModel()
328
    {
329
        $model = $this->getContainer('config')->get('rinvex.repository.models');
330
331
        return $this->model ?: str_replace(['Repositories', 'Repository'], [$model, ''], get_called_class());
332
    }
333
334
    /**
335
     * {@inheritdoc}
336
     */
337
    public function with($relations)
338
    {
339
        if (is_string($relations)) {
340
            $relations = func_get_args();
341
        }
342
343
        $this->relations = $relations;
344
345
        return $this;
346
    }
347
348
    /**
349
     * {@inheritdoc}
350
     */
351
    public function where($attribute, $operator = null, $value = null, $boolean = 'and')
352
    {
353
        // The last `$boolean` expression is intentional to fix list() & array_pad() results
354
        $this->where[] = [$attribute, $operator, $value, $boolean ?: 'and'];
355
356
        return $this;
357
    }
358
359
    /**
360
     * {@inheritdoc}
361
     */
362
    public function whereIn($attribute, $values, $boolean = 'and', $not = false)
363
    {
364
        // The last `$boolean` & `$not` expressions are intentional to fix list() & array_pad() results
365
        $this->whereIn[] = [$attribute, $values, $boolean ?: 'and', (bool) $not];
366
367
        return $this;
368
    }
369
370
    /**
371
     * {@inheritdoc}
372
     */
373
    public function whereNotIn($attribute, $values, $boolean = 'and')
374
    {
375
        // The last `$boolean` expression is intentional to fix list() & array_pad() results
376
        $this->whereNotIn[] = [$attribute, $values, $boolean ?: 'and'];
377
378
        return $this;
379
    }
380
381
    /**
382
     * {@inheritdoc}
383
     */
384
    public function whereHas($relation, Closure $callback, $operator = '>=', $count = 1)
385
    {
386
        // The last `$operator` & `$count` expressions are intentional to fix list() & array_pad() results
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
387
        $this->whereHas[] = [$relation, $callback, $operator ?: '>=', $count ?: 1];
388
389
        return $this;
390
    }
391
392
    /**
393
     * {@inheritdoc}
394
     */
395
    public function offset($offset)
396
    {
397
        $this->offset = $offset;
398
399
        return $this;
400
    }
401
402
    /**
403
     * {@inheritdoc}
404
     */
405
    public function limit($limit)
406
    {
407
        $this->limit = $limit;
408
409
        return $this;
410
    }
411
412
    /**
413
     * {@inheritdoc}
414
     */
415
    public function orderBy($attribute, $direction = 'asc')
416
    {
417
        $this->orderBy = [$attribute, $direction];
418
419
        return $this;
420
    }
421
422
    /**
423
     * {@inheritdoc}
424
     */
425
    public function groupBy($column)
426
    {
427
        $this->groupBy = array_merge((array) $this->groupBy, is_array($column) ? $column : [$column]);
428
429
        return $this;
430
    }
431
432
    /**
433
     * {@inheritdoc}
434
     */
435
    public function having($column, $operator = null, $value = null, $boolean = 'and')
436
    {
437
        $this->having[] = [$column, $operator, $value, $boolean ?: 'and'];
438
439
        return $this;
440
    }
441
442
    /**
443
     * {@inheritdoc}
444
     */
445
    public function orHaving($column, $operator = null, $value = null, $boolean = 'and')
446
    {
447
        return $this->having($column, $operator, $value, 'or');
448
    }
449
450
    /**
451
     * {@inheritdoc}
452
     */
453
    public function store($id, array $attributes = [])
454
    {
455
        return ! $id ? $this->create($attributes) : $this->update($id, $attributes);
456
    }
457
458
    /**
459
     * {@inheritdoc}
460
     */
461
    public static function __callStatic($method, $parameters)
462
    {
463
        return call_user_func_array([new static(), $method], $parameters);
464
    }
465
466
    /**
467
     * {@inheritdoc}
468
     */
469
    public function __call($method, $parameters)
470
    {
471
        return call_user_func_array([$this->createModel(), $method], $parameters);
472
    }
473
}
474