Completed
Push — master ( 21ffa2...ce2f02 )
by Mike
04:55 queued 02:25
created

CachedBuilder   B

Complexity

Total Complexity 38

Size/Duplication

Total Lines 248
Duplicated Lines 35.48 %

Importance

Changes 0
Metric Value
dl 88
loc 248
rs 8.3999
c 0
b 0
f 0
wmc 38

20 Methods

Rating   Name   Duplication   Size   Complexity  
A cache() 0 9 2
A getCacheKey() 0 11 2
A getQueryColumns() 0 7 3
A getModelSlug() 0 3 1
A getLimitClause() 0 7 2
A getOffsetClause() 0 7 2
A getIdColumn() 0 4 2
A min() 8 8 1
A pluck() 0 12 2
A getCacheTags() 0 22 3
A find() 8 8 1
A getWithModels() 0 9 2
C getWhereClauses() 0 33 8
A max() 8 8 1
A avg() 8 8 1
A count() 8 8 1
A get() 8 8 1
A cursor() 8 8 1
A sum() 8 8 1
A first() 8 8 1

How to fix   Duplicated Code   

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:

1
<?php namespace GeneaLabs\LaravelModelCaching;
2
3
use Closure;
4
use Illuminate\Cache\TaggableStore;
5
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
6
use Illuminate\Database\Eloquent\Relations\Pivot;
7
use Illuminate\Support\Collection;
8
use Illuminate\Database\Eloquent\Relations\Relation;
9
10
class CachedBuilder extends EloquentBuilder
11
{
12
    protected function cache(array $tags = [])
13
    {
14
        $cache = cache();
15
16
        if (is_subclass_of($cache->getStore(), TaggableStore::class)) {
17
            $cache = $cache->tags($tags);
18
        }
19
20
        return $cache;
21
    }
22
23
    protected function getCacheKey(array $columns = ['*'], $idColumn = null) : string
24
    {
25
        $key = $this->getModelSlug();
26
        $key .= $this->getIdColumn($idColumn ?: '');
27
        $key .= $this->getQueryColumns($columns);
28
        $key .= $this->getWhereClauses();
29
        $key .= $this->getWithModels();
30
        $key .= $this->getOffsetClause();
31
        $key .= $this->getLimitClause();
32
33
        return $key;
34
    }
35
36
    protected function getIdColumn(string $idColumn) : string
37
    {
38
39
        return $idColumn ? "_{$idColumn}" : '';
40
    }
41
42
    protected function getLimitClause() : string
43
    {
44
        if (! $this->query->limit) {
45
            return '';
46
        }
47
48
        return "-limit_{$this->query->limit}";
49
    }
50
51
    protected function getModelSlug() : string
52
    {
53
        return str_slug(get_class($this->model));
54
    }
55
56
    protected function getOffsetClause() : string
57
    {
58
        if (! $this->query->offset) {
59
            return '';
60
        }
61
62
        return "-offset_{$this->query->offset}";
63
    }
64
65
    protected function getQueryColumns(array $columns) : string
66
    {
67
        if ($columns === ['*'] || $columns === []) {
68
            return '';
69
        }
70
71
        return '_' . implode('_', $columns);
72
    }
73
74
    protected function getWhereClauses(array $wheres = []) : string
75
    {
76
        $wheres = collect($wheres);
77
78
        if ($wheres->isEmpty()) {
79
            $wheres = collect($this->query->wheres);
80
        }
81
82
        return $wheres->reduce(function ($carry, $where) {
83
            if (in_array($where['type'], ['Exists', 'Nested'])) {
84
                return $this->getWhereClauses($where['query']->wheres);
85
            }
86
87
            if ($where['type'] === 'Column') {
88
                return "_{$where['boolean']}_{$where['first']}_{$where['operator']}_{$where['second']}";
89
            }
90
91
            if ($where['type'] === 'raw') {
92
                return "_{$where['boolean']}_" . str_slug($where['sql']);
93
            }
94
95
            $value = array_get($where, 'value');
96
97
            if (in_array($where['type'], ['In', 'Null', 'NotNull'])) {
98
                $value = strtolower($where['type']);
99
            }
100
101
            if (is_array(array_get($where, 'values'))) {
102
                $value .= '_' . implode('_', $where['values']);
103
            }
104
105
            return "{$carry}-{$where['column']}_{$value}";
106
        }) ?: '';
107
    }
108
109
    protected function getWithModels() : string
110
    {
111
        $eagerLoads = collect($this->eagerLoad);
112
113
        if ($eagerLoads->isEmpty()) {
114
            return '';
115
        }
116
117
        return '-' . implode('-', $eagerLoads->keys()->toArray());
118
    }
119
120
    protected function getCacheTags() : array
121
    {
122
        return collect($this->eagerLoad)->keys()
123
            ->map(function ($relationName) {
124
                $relation = collect(explode('.', $relationName))
125
                    ->reduce(function ($carry, $name) {
126
                        if (! $carry) {
127
                            $carry = $this->model;
128
                        }
129
130
                        if ($carry instanceof Relation) {
131
                            $carry = $carry->getQuery()->model;
132
                        }
133
134
                        return $carry->{$name}();
135
                    });
136
137
                return str_slug(get_class($relation->getQuery()->model));
138
            })
139
            ->prepend(str_slug(get_class($this->model)))
140
            ->values()
141
            ->toArray();
142
    }
143
144 View Code Duplication
    public function avg($column)
145
    {
146
        $tags = [str_slug(get_class($this->model))];
147
        $key = str_slug(get_class($this->model)) ."-avg_{$column}";
148
149
        return $this->cache($tags)
150
            ->rememberForever($key, function () use ($column) {
151
                return parent::avg($column);
152
            });
153
    }
154
155 View Code Duplication
    public function count($columns = ['*'])
156
    {
157
        $tags = [str_slug(get_class($this->model))];
158
        $key = str_slug(get_class($this->model)) ."-count";
159
160
        return $this->cache($tags)
161
            ->rememberForever($key, function () use ($columns) {
162
                return parent::count($columns);
163
            });
164
    }
165
166 View Code Duplication
    public function cursor()
167
    {
168
        $tags = [str_slug(get_class($this->model))];
169
        $key = str_slug(get_class($this->model)) ."-cursor";
170
171
        return $this->cache($tags)
172
            ->rememberForever($key, function () {
173
                return collect(parent::cursor());
174
            });
175
    }
176
177
    /**
178
     * @SuppressWarnings(PHPMD.ShortVariable)
179
     */
180 View Code Duplication
    public function find($id, $columns = ['*'])
181
    {
182
        $tags = $this->getCacheTags();
183
        $key = $this->getCacheKey($columns, $id);
184
185
        return $this->cache($tags)
186
            ->rememberForever($key, function () use ($id, $columns) {
187
                return parent::find($id, $columns);
188
            });
189
    }
190
191 View Code Duplication
    public function first($columns = ['*'])
192
    {
193
        $tags = $this->getCacheTags();
194
        $key = $this->getCacheKey($columns) . '-first';
195
196
        return $this->cache($tags)
197
            ->rememberForever($key, function () use ($columns) {
198
                return parent::first($columns);
199
            });
200
    }
201
202 View Code Duplication
    public function get($columns = ['*'])
203
    {
204
        $tags = $this->getCacheTags();
205
        $key = $this->getCacheKey($columns);
206
207
        return $this->cache($tags)
208
            ->rememberForever($key, function () use ($columns) {
209
                return parent::get($columns);
210
            });
211
    }
212
213 View Code Duplication
    public function max($column)
214
    {
215
        $tags = [str_slug(get_class($this->model))];
216
        $key = str_slug(get_class($this->model)) ."-max_{$column}";
217
218
        return $this->cache($tags)
219
            ->rememberForever($key, function () use ($column) {
220
                return parent::max($column);
221
            });
222
    }
223
224 View Code Duplication
    public function min($column)
225
    {
226
        $tags = [str_slug(get_class($this->model))];
227
        $key = str_slug(get_class($this->model)) ."-min_{$column}";
228
229
        return $this->cache($tags)
230
            ->rememberForever($key, function () use ($column) {
231
                return parent::min($column);
232
            });
233
    }
234
235
    public function pluck($column, $key = null)
236
    {
237
        $tags = $this->getCacheTags();
238
        $cacheKey = $this->getCacheKey([$column]) . "-pluck_{$column}";
239
240
        if ($key) {
241
            $cacheKey .= "_{$key}";
242
        }
243
244
        return $this->cache($tags)
245
            ->rememberForever($cacheKey, function () use ($column, $key) {
246
                return parent::pluck($column, $key);
247
            });
248
    }
249
250 View Code Duplication
    public function sum($column)
251
    {
252
        $tags = [str_slug(get_class($this->model))];
253
        $key = str_slug(get_class($this->model)) ."-sum_{$column}";
254
255
        return $this->cache($tags)
256
            ->rememberForever($key, function () use ($column) {
257
                return parent::sum($column);
258
            });
259
    }
260
}
261