Repository   B
last analyzed

Complexity

Total Complexity 42

Size/Duplication

Total Lines 381
Duplicated Lines 4.2 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 42
dl 16
loc 381
rs 8.295
c 1
b 0
f 0

22 Methods

Rating   Name   Duplication   Size   Complexity  
A count() 0 6 1
A invalidOperator() 0 3 1
A prepareValueAndOperator() 0 9 3
A value() 0 4 2
A prepareDeleteQuery() 0 12 3
A paginate() 0 3 1
A select() 0 5 2
A invalidOperatorAndValue() 0 4 3
A first() 7 7 2
A get() 7 7 2
A where() 0 15 2
A orWhere() 0 3 1
A active() 0 5 1
A __construct() 0 3 1
A find() 0 3 1
A whereIn() 0 6 2
A with() 0 6 2
C prepareQuery() 0 23 7
A delete() 0 7 2
A create() 0 3 1
A update() 0 6 1
A destroy() 0 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Repository 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.

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 Repository, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace OzanAkman\RepositoryGenerator;
4
5
use InvalidArgumentException;
6
7
abstract class Repository implements RepositoryInterface
8
{
9
    /**
10
     * The model being used by repository.
11
     *
12
     * @var
13
     */
14
    public $model;
15
16
    /**
17
     * The relationships that should be eager loaded.
18
     *
19
     * @var array
20
     */
21
    public $relations = [];
22
23
    /**
24
     * Basic where clauses to affect query.
25
     *
26
     * @var array
27
     */
28
    protected $wheres = [];
29
30
    /**
31
     * The columns being selected.
32
     *
33
     * @var
34
     */
35
    protected $columns;
36
37
    /**
38
     * Indicates whether active column is being used.
39
     *
40
     * @var bool
41
     */
42
    public $active = false;
43
44
    /**
45
     * All of the available clause operators.
46
     *
47
     * @var array
48
     */
49
    public $operators = [
50
        '=', '<', '>', '<=', '>=', '<>', '!=',
51
        'like', 'like binary', 'not like', 'between', 'ilike',
52
        '&', '|', '^', '<<', '>>',
53
        'rlike', 'regexp', 'not regexp',
54
        '~', '~*', '!~', '!~*', 'similar to',
55
        'not similar to', 'not ilike', '~~*', '!~~*',
56
    ];
57
58
    /**
59
     * Create a new repository instance.
60
     *
61
     * @param $model
62
     */
63
    public function __construct($model)
64
    {
65
        $this->model = $model;
66
    }
67
68
    /**
69
     * Set the columns to be selected.
70
     *
71
     * @param  array|mixed $columns
72
     * @return $this
73
     */
74
    public function select($columns = ['*'])
75
    {
76
        $this->columns = is_array($columns) ? $columns : func_get_args();
77
78
        return $this;
79
    }
80
81
    /**
82
     * Set the query to get only active records from database.
83
     *
84
     * @return $this
85
     */
86
    public function active()
87
    {
88
        $this->where(config('repository-generator.active_column'), 1);
89
90
        return $this;
91
    }
92
93
    /**
94
     * Add a basic where clause to the query.
95
     *
96
     * @param $column
97
     * @param string $operator
98
     * @param mixed $value
99
     * @param string $boolean
100
     * @return $this
101
     */
102
    public function where($column, $operator = null, $value = null, $boolean = 'and')
103
    {
104
        list($value, $operator) = $this->prepareValueAndOperator(
105
            $value, $operator, func_num_args() == 2
106
        );
107
108
        if ($this->invalidOperator($operator)) {
109
            list($value, $operator) = [$operator, '='];
0 ignored issues
show
Comprehensibility Best Practice introduced by
This list assign is not used and could be removed.
Loading history...
110
        }
111
112
        $this->wheres[] = compact(
113
            'type', 'column', 'operator', 'value', 'boolean'
114
        );
115
116
        return $this;
117
    }
118
119
    /**
120
     * Add a "where in" clause to the query.
121
     *
122
     * @param  string $column
123
     * @param  mixed $values
124
     * @param  string $boolean
125
     * @param  bool $not
126
     * @return $this
127
     */
128
    public function whereIn($column, $values, $boolean = 'and', $not = false)
129
    {
130
        $type = $not ? 'NotIn' : 'In';
131
        $this->wheres[] = compact('type', 'column', 'values', 'boolean');
132
133
        return $this;
134
    }
135
136
    /**
137
     * Add an "or where" clause to the query.
138
     *
139
     * @param  \Closure|string $column
140
     * @param  string $operator
141
     * @param  mixed $value
142
     * @return \Illuminate\Database\Query\Builder|static
0 ignored issues
show
Bug introduced by
The type Illuminate\Database\Query\Builder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
143
     */
144
    public function orWhere($column, $operator = null, $value = null)
145
    {
146
        return $this->where($column, $operator, $value, 'or');
147
    }
148
149
    /**
150
     * Set the relationships that should be eager loaded.
151
     *
152
     * @param  mixed $relations
153
     * @return $this
154
     */
155
    public function with($relations)
156
    {
157
        $relations = is_string($relations) ? func_get_args() : $relations;
158
        $this->relations[] = $relations;
159
160
        return $this;
161
    }
162
163
    /**
164
     * Retrieve the "count" result of the query.
165
     *
166
     * @return int
167
     */
168
    public function count()
169
    {
170
        $this->columns = ['id'];
171
        $query = $this->prepareQuery();
172
173
        return $query->count();
174
    }
175
176
    /**
177
     * Execute a query for a single record by ID.
178
     *
179
     * @param  int $id
180
     * @param  array $columns
181
     * @return mixed|static
182
     */
183
    public function find($id, $columns = ['*'])
184
    {
185
        return $this->where('id', '=', $id)->first($columns);
186
    }
187
188
    /**
189
     * Execute a query for a single record by bindings.
190
     *
191
     * @param array $columns
192
     * @return mixed
193
     */
194 View Code Duplication
    public function first($columns = ['*'])
195
    {
196
        if (is_null($this->columns)) {
197
            $this->columns = $columns;
198
        }
199
200
        return $this->prepareQuery()->first();
201
    }
202
203
    /**
204
     * Get a single column's value from the first result of a query.
205
     *
206
     * @param  string  $column
207
     * @return mixed
208
     */
209
    public function value($column)
210
    {
211
        if ($result = $this->first([$column])) {
212
            return $result->{$column};
213
        }
214
    }
215
216
    /**
217
     * Execute the query.
218
     *
219
     * @param  array $columns
220
     * @return \Illuminate\Support\Collection
221
     */
222 View Code Duplication
    public function get($columns = ['*'])
223
    {
224
        if (is_null($this->columns)) {
225
            $this->columns = $columns;
226
        }
227
228
        return $this->prepareQuery()->get();
229
    }
230
231
    /**
232
     * Paginate the given query into a simple paginator.
233
     *
234
     * @param int $rows
235
     * @return mixed
236
     */
237
    public function paginate($rows = 20)
238
    {
239
        return $this->prepareQuery()->paginate($rows);
240
    }
241
242
    /**
243
     * Create a new database record.
244
     *
245
     * @param array $attributes
246
     * @return mixed
247
     */
248
    public function create($attributes)
249
    {
250
        return $this->model->create($attributes);
251
    }
252
253
    /**
254
     * Update database record with given attributes by ID.
255
     *
256
     * @param $attributes
257
     * @param $id
258
     * @return mixed
259
     */
260
    public function update($attributes, $id)
261
    {
262
        $this->columns = null;
263
        $object = $this->where('id', $id)->first();
264
265
        return $object->update($attributes);
266
    }
267
268
    /**
269
     * Delete mass or single record from the database.
270
     *
271
     * @param  mixed  $id
272
     * @return int
273
     */
274
    public function delete($id = null)
275
    {
276
        if (! is_null($id)) {
277
            $this->where('id', $id);
278
        }
279
280
        return $this->prepareDeleteQuery()->delete();
281
    }
282
283
    /**
284
     * Delete a single record from the database by ID.
285
     *
286
     * @param $id
287
     * @return mixed
288
     */
289
    public function destroy($id)
290
    {
291
        return $this->model->destroy($id);
292
    }
293
294
    /**
295
     * Prepare a executable query.
296
     *
297
     * @return mixed
298
     */
299
    protected function prepareQuery()
300
    {
301
        $query = $this->model->select($this->columns);
302
303
        $wheres = $this->wheres;
304
        if (! is_null($wheres)) {
305
            foreach ($wheres as $where) {
306
                if (isset($where['values']) && isset($where['type'])) {
307
                    $query->whereIn($where['column'], $where['values']);
308
                } else {
309
                    $query->where($where['column'], $where['operator'], $where['value']);
310
                }
311
            }
312
        }
313
314
        $relations = $this->relations;
315
        if (! is_null($this->relations)) {
316
            foreach ($relations as $relation) {
317
                $query->with($relation);
318
            }
319
        }
320
321
        return $query;
322
    }
323
324
    /**
325
     * Prepare a executable delete query.
326
     *
327
     * @return mixed
328
     */
329
    protected function prepareDeleteQuery()
330
    {
331
        $query = $this->model;
332
333
        $wheres = $this->wheres;
334
        if (! is_null($wheres)) {
335
            foreach ($wheres as $where) {
336
                $query->where($where['column'], $where['operator'], $where['value']);
337
            }
338
        }
339
340
        return $query;
341
    }
342
343
    /**
344
     * Prepare the value and operator for a where clause.
345
     *
346
     * @param  string $value
347
     * @param  string $operator
348
     * @param  bool $useDefault
349
     * @return array
350
     *
351
     * @throws \InvalidArgumentException
352
     */
353
    protected function prepareValueAndOperator($value, $operator, $useDefault = false)
354
    {
355
        if ($useDefault) {
356
            return [$operator, '='];
357
        } elseif ($this->invalidOperatorAndValue($operator, $value)) {
358
            throw new InvalidArgumentException('Illegal operator and value combination.');
359
        }
360
361
        return [$value, $operator];
362
    }
363
364
    /**
365
     * Determine if the given operator and value combination is legal.
366
     *
367
     * Prevents using Null values with invalid operators.
368
     *
369
     * @param  string $operator
370
     * @param  mixed $value
371
     * @return bool
372
     */
373
    protected function invalidOperatorAndValue($operator, $value)
374
    {
375
        return is_null($value) && in_array($operator, $this->operators) &&
376
            ! in_array($operator, ['=', '<>', '!=']);
377
    }
378
379
    /**
380
     * Determine if the given operator is supported.
381
     *
382
     * @param  string $operator
383
     * @return bool
384
     */
385
    protected function invalidOperator($operator)
386
    {
387
        return ! in_array(strtolower($operator), $this->operators, true);
388
    }
389
}
390