Completed
Pull Request — develop (#76)
by
unknown
03:03
created

BaseRepository::prepareQuery()   D

Complexity

Conditions 10
Paths 512

Size

Total Lines 59
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 7
Bugs 2 Features 1
Metric Value
c 7
b 2
f 1
dl 0
loc 59
rs 4.7356
cc 10
eloc 25
nc 512
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
/*
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
     * Execute given callback and return the result.
114
     *
115
     * @param string   $class
116
     * @param string   $method
117
     * @param array    $args
118
     * @param \Closure $closure
119
     *
120
     * @return mixed
121
     */
122
    protected function executeCallback($class, $method, $args, Closure $closure)
123
    {
124
        $skipUri = $this->getContainer('config')->get('rinvex.repository.cache.skip_uri');
125
126
        // Check if cache is enabled
127
        if ($this->getCacheLifetime() && ! $this->getContainer('request')->has($skipUri)) {
128
            return $this->cacheCallback($class, $method, $args, $closure);
129
        }
130
131
        // Cache disabled, just execute query & return result
132
        $result = call_user_func($closure);
133
134
        // We're done, let's clean up!
135
        $this->resetRepository();
136
137
        return $result;
138
    }
139
140
    /**
141
     * Reset repository to it's defaults.
142
     *
143
     * @return $this
144
     */
145
    protected function resetRepository()
146
    {
147
        $this->relations  = [];
148
        $this->where      = [];
149
        $this->whereIn    = [];
150
        $this->whereNotIn = [];
151
        $this->whereHas   = [];
152
        $this->offset     = null;
153
        $this->limit      = null;
154
        $this->orderBy    = [];
155
156
        if (property_exists($this, 'criteria')) {
157
            $this->criteria   = [];
0 ignored issues
show
Bug introduced by
The property criteria does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
158
        }
159
160
        return $this;
161
    }
162
163
    /**
164
     * Prepare query.
165
     *
166
     * @param object $model
167
     *
168
     * @return object
169
     */
170
    protected function prepareQuery($model)
171
    {
172
        // Set the relationships that should be eager loaded
173
        if (! empty($this->relations)) {
174
            $model = $model->with($this->relations);
175
        }
176
177
        // Add a basic where clause to the query
178
        foreach ($this->where as $where) {
179
            list($attribute, $operator, $value, $boolean) = array_pad($where, 4, null);
180
181
            $model = $model->where($attribute, $operator, $value, $boolean);
182
        }
183
184
        // Add a "where in" clause to the query
185
        foreach ($this->whereIn as $whereIn) {
186
            list($attribute, $values, $boolean, $not) = array_pad($whereIn, 4, null);
187
188
            $model = $model->whereIn($attribute, $values, $boolean, $not);
189
        }
190
191
        // Add a "where not in" clause to the query
192
        foreach ($this->whereNotIn as $whereNotIn) {
193
            list($attribute, $values, $boolean) = array_pad($whereNotIn, 3, null);
194
195
            $model = $model->whereNotIn($attribute, $values, $boolean);
196
        }
197
198
        // Add a "where has" clause to the query
199
        foreach ($this->whereHas as $whereHas) {
200
            list($relation, $callback, $operator, $count) = array_pad($whereHas, 4, null);
201
202
            $model = $model->whereHas($relation, $callback, $operator, $count);
203
        }
204
205
        // Set the "offset" value of the query
206
        if ($this->offset > 0) {
207
            $model = $model->offset($this->offset);
208
        }
209
210
        // Set the "limit" value of the query
211
        if ($this->limit > 0) {
212
            $model = $model->limit($this->limit);
213
        }
214
215
        // Add an "order by" clause to the query.
216
        if (! empty($this->orderBy)) {
217
            list($attribute, $direction) = $this->orderBy;
218
219
            $model = $model->orderBy($attribute, $direction);
220
        }
221
222
        // Apply all criteria to the query
223
        if (method_exists($this, 'applyCriteria')) {
224
            $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...
225
        }
226
227
        return $model;
228
    }
229
230
    /**
231
     * {@inheritdoc}
232
     */
233
    public function setContainer(Container $container)
234
    {
235
        $this->container = $container;
236
237
        return $this;
238
    }
239
240
    /**
241
     * {@inheritdoc}
242
     */
243
    public function getContainer($service = null)
244
    {
245
        return is_null($service) ? ($this->container ?: app()) : ($this->container[$service] ?: app($service));
246
    }
247
248
    /**
249
     * {@inheritdoc}
250
     */
251
    public function setConnection($name)
252
    {
253
        $this->connection = $name;
254
255
        return $this;
256
    }
257
258
    /**
259
     * {@inheritdoc}
260
     */
261
    public function getConnection()
262
    {
263
        return $this->connection;
264
    }
265
266
    /**
267
     * {@inheritdoc}
268
     */
269
    public function setRepositoryId($repositoryId)
270
    {
271
        $this->repositoryId = $repositoryId;
272
273
        return $this;
274
    }
275
276
    /**
277
     * {@inheritdoc}
278
     */
279
    public function getRepositoryId()
280
    {
281
        return $this->repositoryId ?: get_called_class();
282
    }
283
284
    /**
285
     * {@inheritdoc}
286
     */
287
    public function setModel($model)
288
    {
289
        $this->model = $model;
290
291
        return $this;
292
    }
293
294
    /**
295
     * {@inheritdoc}
296
     */
297
    public function getModel()
298
    {
299
        $model = $this->getContainer('config')->get('rinvex.repository.models');
300
301
        return $this->model ?: str_replace(['Repositories', 'Repository'], [$model, ''], get_called_class());
302
    }
303
304
    /**
305
     * {@inheritdoc}
306
     */
307
    public function with(array $relations)
308
    {
309
        $this->relations = $relations;
310
311
        return $this;
312
    }
313
314
    /**
315
     * {@inheritdoc}
316
     */
317
    public function where($attribute, $operator = null, $value = null, $boolean = 'and')
318
    {
319
        // The last `$boolean` expression is intentional to fix list() & array_pad() results
320
        $this->where[] = [$attribute, $operator, $value, $boolean ?: 'and'];
321
322
        return $this;
323
    }
324
325
    /**
326
     * {@inheritdoc}
327
     */
328
    public function whereIn($attribute, $values, $boolean = 'and', $not = false)
329
    {
330
        // The last `$boolean` & `$not` expressions are intentional to fix list() & array_pad() results
331
        $this->whereIn[] = [$attribute, $values, $boolean ?: 'and', (bool) $not];
332
333
        return $this;
334
    }
335
336
    /**
337
     * {@inheritdoc}
338
     */
339
    public function whereNotIn($attribute, $values, $boolean = 'and')
340
    {
341
        // The last `$boolean` expression is intentional to fix list() & array_pad() results
342
        $this->whereNotIn[] = [$attribute, $values, $boolean ?: 'and'];
343
344
        return $this;
345
    }
346
347
    /**
348
     * {@inheritdoc}
349
     */
350
    public function whereHas($relation, Closure $callback, $operator = '>=', $count = 1)
351
    {
352
        // 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...
353
        $this->whereHas[] = [$relation, $callback, $operator ?: '>=', $count ?: 1];
354
355
        return $this;
356
    }
357
358
    /**
359
     * {@inheritdoc}
360
     */
361
    public function offset($offset)
362
    {
363
        $this->offset = $offset;
364
365
        return $this;
366
    }
367
368
    /**
369
     * {@inheritdoc}
370
     */
371
    public function limit($limit)
372
    {
373
        $this->limit = $limit;
374
375
        return $this;
376
    }
377
378
    /**
379
     * {@inheritdoc}
380
     */
381
    public function orderBy($attribute, $direction = 'asc')
382
    {
383
        $this->orderBy = [$attribute, $direction];
384
385
        return $this;
386
    }
387
388
    /**
389
     * {@inheritdoc}
390
     */
391
    public static function __callStatic($method, $parameters)
392
    {
393
        return call_user_func_array([new static(), $method], $parameters);
394
    }
395
396
    /**
397
     * {@inheritdoc}
398
     */
399
    public function __call($method, $parameters)
400
    {
401
        return call_user_func_array([$this->createModel(), $method], $parameters);
402
    }
403
}