BaseRepository::prepareQuery()   F
last analyzed

Complexity

Conditions 14
Paths 5120

Size

Total Lines 78

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 78
rs 2.16
cc 14
nc 5120
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Rinvex\Repository\Repositories;
6
7
use Closure;
8
use Rinvex\Repository\Traits\Cacheable;
9
use Illuminate\Contracts\Container\Container;
10
use Rinvex\Repository\Contracts\CacheableContract;
11
use Rinvex\Repository\Contracts\RepositoryContract;
12
13
abstract class BaseRepository implements RepositoryContract, CacheableContract
14
{
15
    use Cacheable;
16
17
    /**
18
     * The IoC container instance.
19
     *
20
     * @var \Illuminate\Contracts\Container\Container
21
     */
22
    protected $container;
23
24
    /**
25
     * The connection name for the repository.
26
     *
27
     * @var string
28
     */
29
    protected $connection;
30
31
    /**
32
     * The repository identifier.
33
     *
34
     * @var string
35
     */
36
    protected $repositoryId;
37
38
    /**
39
     * The repository model.
40
     *
41
     * @var string
42
     */
43
    protected $model;
44
45
    /**
46
     * The relations to eager load on query execution.
47
     *
48
     * @var array
49
     */
50
    protected $relations = [];
51
52
    /**
53
     * The query where clauses.
54
     *
55
     * @var array
56
     */
57
    protected $where = [];
58
59
    /**
60
     * The query whereIn clauses.
61
     *
62
     * @var array
63
     */
64
    protected $whereIn = [];
65
66
    /**
67
     * The query whereNotIn clauses.
68
     *
69
     * @var array
70
     */
71
    protected $whereNotIn = [];
72
73
    /**
74
     * The query whereHas clauses.
75
     *
76
     * @var array
77
     */
78
    protected $whereHas = [];
79
80
    /**
81
     * The query scopes.
82
     *
83
     * @var array
84
     */
85
    protected $scopes = [];
86
87
    /**
88
     * The "offset" value of the query.
89
     *
90
     * @var int
91
     */
92
    protected $offset;
93
94
    /**
95
     * The "limit" value of the query.
96
     *
97
     * @var int
98
     */
99
    protected $limit;
100
101
    /**
102
     * The column to order results by.
103
     *
104
     * @var array
105
     */
106
    protected $orderBy = [];
107
108
    /**
109
     * The column to order results by.
110
     *
111
     * @var array
112
     */
113
    protected $groupBy = [];
114
115
    /**
116
     * The query having clauses.
117
     *
118
     * @var array
119
     */
120
    protected $having = [];
121
122
    /**
123
     * Execute given callback and return the result.
124
     *
125
     * @param string   $class
126
     * @param string   $method
127
     * @param array    $args
128
     * @param \Closure $closure
129
     *
130
     * @return mixed
131
     */
132
    protected function executeCallback($class, $method, $args, Closure $closure)
133
    {
134
        $skipUri = $this->getContainer('config')->get('rinvex.repository.cache.skip_uri');
135
136
        // Check if cache is enabled
137
        if ($this->getCacheLifetime() && ! $this->getContainer('request')->has($skipUri)) {
138
            return $this->cacheCallback($class, $method, $args, $closure);
139
        }
140
141
        // Cache disabled, just execute query & return result
142
        $result = call_user_func($closure);
143
144
        // We're done, let's clean up!
145
        $this->resetRepository();
146
147
        return $result;
148
    }
149
150
    /**
151
     * Reset repository to its defaults.
152
     *
153
     * @return $this
154
     */
155
    protected function resetRepository()
156
    {
157
        $this->relations = [];
158
        $this->where = [];
159
        $this->whereIn = [];
160
        $this->whereNotIn = [];
161
        $this->whereHas = [];
162
        $this->scopes = [];
163
        $this->offset = null;
164
        $this->limit = null;
165
        $this->orderBy = [];
166
        $this->groupBy = [];
167
        $this->having = [];
168
169
        if (method_exists($this, 'flushCriteria')) {
170
            $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...
171
        }
172
173
        return $this;
174
    }
175
176
    /**
177
     * Prepare query.
178
     *
179
     * @param object $model
180
     *
181
     * @return mixed
182
     */
183
    protected function prepareQuery($model)
184
    {
185
        // Set the relationships that should be eager loaded
186
        if (! empty($this->relations)) {
187
            $model = $model->with($this->relations);
188
        }
189
190
        // Add a basic where clause to the query
191
        foreach ($this->where as $where) {
192
            [$attribute, $operator, $value, $boolean] = array_pad($where, 4, null);
0 ignored issues
show
Bug introduced by
The variable $attribute does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $operator does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $value does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $boolean does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
193
194
            $model = $model->where($attribute, $operator, $value, $boolean);
195
        }
196
197
        // Add a "where in" clause to the query
198
        foreach ($this->whereIn as $whereIn) {
199
            [$attribute, $values, $boolean, $not] = array_pad($whereIn, 4, null);
0 ignored issues
show
Bug introduced by
The variable $values does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $not does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
200
201
            $model = $model->whereIn($attribute, $values, $boolean, $not);
202
        }
203
204
        // Add a "where not in" clause to the query
205
        foreach ($this->whereNotIn as $whereNotIn) {
206
            [$attribute, $values, $boolean] = array_pad($whereNotIn, 3, null);
207
208
            $model = $model->whereNotIn($attribute, $values, $boolean);
209
        }
210
211
        // Add a "where has" clause to the query
212
        foreach ($this->whereHas as $whereHas) {
213
            [$relation, $callback, $operator, $count] = array_pad($whereHas, 4, null);
0 ignored issues
show
Bug introduced by
The variable $relation does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $callback does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $count does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
214
215
            $model = $model->whereHas($relation, $callback, $operator, $count);
216
        }
217
218
        // Add a "scope" to the query
219
        foreach ($this->scopes as $scope => $parameters) {
220
            $model = $model->{$scope}(...$parameters);
221
        }
222
223
        // Set the "offset" value of the query
224
        if ($this->offset > 0) {
225
            $model = $model->offset($this->offset);
226
        }
227
228
        // Set the "limit" value of the query
229
        if ($this->limit > 0) {
230
            $model = $model->limit($this->limit);
231
        }
232
233
        // Add an "order by" clause to the query.
234
        foreach ($this->orderBy as $orderBy) {
235
            [$attribute, $direction] = $orderBy;
0 ignored issues
show
Bug introduced by
The variable $direction does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
236
237
            $model = $model->orderBy($attribute, $direction);
238
        }
239
240
        // Add an "group by" clause to the query.
241
        if (! empty($this->groupBy)) {
242
            foreach ($this->groupBy as $group) {
243
                $model = $model->groupBy($group);
244
            }
245
        }
246
247
        // Add a "having" clause to the query
248
        foreach ($this->having as $having) {
249
            [$column, $operator, $value, $boolean] = array_pad($having, 4, null);
0 ignored issues
show
Bug introduced by
The variable $column does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
250
251
            $model = $model->having($column, $operator, $value, $boolean);
252
        }
253
254
        // Apply all criteria to the query
255
        if (method_exists($this, 'applyCriteria')) {
256
            $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...
257
        }
258
259
        return $model;
260
    }
261
262
    /**
263
     * {@inheritdoc}
264
     */
265
    public function setContainer(Container $container)
266
    {
267
        $this->container = $container;
268
269
        return $this;
270
    }
271
272
    /**
273
     * {@inheritdoc}
274
     */
275
    public function getContainer($service = null)
276
    {
277
        return is_null($service) ? ($this->container ?: app()) : ($this->container[$service] ?: app($service));
278
    }
279
280
    /**
281
     * {@inheritdoc}
282
     */
283
    public function setConnection($name)
284
    {
285
        $this->connection = $name;
286
287
        return $this;
288
    }
289
290
    /**
291
     * {@inheritdoc}
292
     */
293
    public function getConnection(): string
294
    {
295
        return $this->connection;
296
    }
297
298
    /**
299
     * {@inheritdoc}
300
     */
301
    public function setRepositoryId($repositoryId)
302
    {
303
        $this->repositoryId = $repositoryId;
304
305
        return $this;
306
    }
307
308
    /**
309
     * {@inheritdoc}
310
     */
311
    public function getRepositoryId(): string
312
    {
313
        return $this->repositoryId ?: static::class;
314
    }
315
316
    /**
317
     * {@inheritdoc}
318
     */
319
    public function setModel($model)
320
    {
321
        $this->model = $model;
322
323
        return $this;
324
    }
325
326
    /**
327
     * {@inheritdoc}
328
     */
329
    public function getModel(): string
330
    {
331
        $model = $this->getContainer('config')->get('rinvex.repository.models');
332
333
        return $this->model ?: str_replace(['Repositories', 'Repository'], [$model, ''], static::class);
334
    }
335
336
    /**
337
     * {@inheritdoc}
338
     */
339
    public function with($relations)
340
    {
341
        if (is_string($relations)) {
342
            $relations = func_get_args();
343
        }
344
345
        $this->relations = $relations;
346
347
        return $this;
348
    }
349
350
    /**
351
     * {@inheritdoc}
352
     */
353
    public function where($attribute, $operator = null, $value = null, $boolean = 'and')
354
    {
355
        // The last `$boolean` expression is intentional to fix list() & array_pad() results
356
        $this->where[] = [$attribute, $operator, $value, $boolean ?: 'and'];
357
358
        return $this;
359
    }
360
361
    /**
362
     * {@inheritdoc}
363
     */
364
    public function whereIn($attribute, $values, $boolean = 'and', $not = false)
365
    {
366
        // The last `$boolean` & `$not` expressions are intentional to fix list() & array_pad() results
367
        $this->whereIn[] = [$attribute, $values, $boolean ?: 'and', (bool) $not];
368
369
        return $this;
370
    }
371
372
    /**
373
     * {@inheritdoc}
374
     */
375
    public function whereNotIn($attribute, $values, $boolean = 'and')
376
    {
377
        // The last `$boolean` expression is intentional to fix list() & array_pad() results
378
        $this->whereNotIn[] = [$attribute, $values, $boolean ?: 'and'];
379
380
        return $this;
381
    }
382
383
    /**
384
     * {@inheritdoc}
385
     */
386
    public function whereHas($relation, Closure $callback = null, $operator = '>=', $count = 1)
387
    {
388
        // The last `$operator` & `$count` expressions are intentional to fix list() & array_pad() results
389
        $this->whereHas[] = [$relation, $callback, $operator ?: '>=', $count ?: 1];
390
391
        return $this;
392
    }
393
394
    /**
395
     * {@inheritdoc}
396
     */
397
    public function scope($name, array $parameters = [])
398
    {
399
        $this->scopes[$name] = $parameters;
400
401
        return $this;
402
    }
403
404
    /**
405
     * {@inheritdoc}
406
     */
407
    public function offset($offset)
408
    {
409
        $this->offset = $offset;
410
411
        return $this;
412
    }
413
414
    /**
415
     * {@inheritdoc}
416
     */
417
    public function limit($limit)
418
    {
419
        $this->limit = $limit;
420
421
        return $this;
422
    }
423
424
    /**
425
     * {@inheritdoc}
426
     */
427
    public function orderBy($attribute, $direction = 'asc')
428
    {
429
        $this->orderBy[] = [$attribute, $direction ?: 'asc'];
430
431
        return $this;
432
    }
433
434
    /**
435
     * {@inheritdoc}
436
     */
437
    public function groupBy($column)
438
    {
439
        $this->groupBy = array_merge((array) $this->groupBy, is_array($column) ? $column : [$column]);
440
441
        return $this;
442
    }
443
444
    /**
445
     * {@inheritdoc}
446
     */
447
    public function having($column, $operator = null, $value = null, $boolean = 'and')
448
    {
449
        $this->having[] = [$column, $operator, $value, $boolean ?: 'and'];
450
451
        return $this;
452
    }
453
454
    /**
455
     * {@inheritdoc}
456
     */
457
    public function orHaving($column, $operator = null, $value = null, $boolean = 'and')
458
    {
459
        return $this->having($column, $operator, $value, 'or');
460
    }
461
462
    /**
463
     * {@inheritdoc}
464
     */
465
    public function store($id, array $attributes = [], bool $syncRelations = false)
466
    {
467
        return ! $id ? $this->create($attributes, $syncRelations) : $this->update($id, $attributes, $syncRelations);
468
    }
469
470
    /**
471
     * {@inheritdoc}
472
     */
473
    public static function __callStatic($method, $parameters)
474
    {
475
        return call_user_func_array([new static(), $method], $parameters);
476
    }
477
478
    /**
479
     * {@inheritdoc}
480
     */
481
    public function __call($method, $parameters)
482
    {
483
        if (method_exists($model = $this->createModel(), $scope = 'scope'.ucfirst($method))) {
484
            $this->scope($method, $parameters);
485
486
            return $this;
487
        }
488
489
        return call_user_func_array([$this->createModel(), $method], $parameters);
490
    }
491
}
492