Completed
Pull Request — develop (#78)
by Ionut
01:50
created

BaseRepository   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 403
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 403
c 1
b 0
f 0
wmc 44
lcom 2
cbo 1
rs 8.3396

24 Methods

Rating   Name   Duplication   Size   Complexity  
A executeCallback() 0 17 3
A resetRepository() 0 13 1
C prepareQuery() 0 54 9
A setContainer() 0 6 1
A getContainer() 0 4 4
A setConnection() 0 6 1
A getConnection() 0 4 1
A setRepositoryId() 0 6 1
A getRepositoryId() 0 4 2
A setModel() 0 6 1
A getModel() 0 6 2
A with() 0 6 1
A where() 0 7 2
A whereIn() 0 7 2
A whereNotIn() 0 7 2
A whereHas() 0 7 3
A offset() 0 6 1
A limit() 0 6 1
A orderBy() 0 6 1
A beginTransaction() 0 4 1
A commit() 0 4 1
A rollBack() 0 4 1
A __callStatic() 0 4 1
A __call() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like BaseRepository often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use BaseRepository, and based on these observations, apply Extract Interface, too.

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