Passed
Push — master ( 6e54e7...2eaef0 )
by Mike
02:21
created

Buildable   A

Complexity

Total Complexity 42

Size/Duplication

Total Lines 277
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 115
dl 0
loc 277
rs 9.0399
c 0
b 0
f 0
wmc 42

22 Methods

Rating   Name   Duplication   Size   Complexity  
A count() 0 9 2
A avg() 0 9 2
A decrement() 0 6 1
A find() 0 14 3
A delete() 0 6 1
A inRandomOrder() 0 5 1
A pluck() 0 10 3
A forceDelete() 0 6 1
A preventHashCollision() 0 22 2
A recursiveImplodeWithKey() 0 9 2
A cachedValue() 0 20 1
A increment() 0 6 1
A value() 0 9 2
A first() 0 9 2
A insert() 0 5 1
A get() 0 9 2
A sum() 0 9 2
A retrieveCachedValue() 0 22 3
A min() 0 9 2
A update() 0 5 1
A max() 0 9 2
A paginate() 0 20 5

How to fix   Complexity   

Complex Class

Complex classes like Buildable 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 Buildable, and based on these observations, apply Extract Interface, too.

1
<?php namespace GeneaLabs\LaravelModelCaching\Traits;
2
3
/**
4
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
5
 */
6
trait Buildable
7
{
8
    public function avg($column)
9
    {
10
        if (! $this->isCachable()) {
11
            return parent::avg($column);
12
        }
13
14
        $cacheKey = $this->makeCacheKey(["*"], null, "-avg_{$column}");
15
16
        return $this->cachedValue(func_get_args(), $cacheKey);
17
    }
18
19
    public function count($columns = "*")
20
    {
21
        if (! $this->isCachable()) {
22
            return parent::count($columns);
23
        }
24
25
        $cacheKey = $this->makeCacheKey([$columns], null, "-count");
26
27
        return $this->cachedValue(func_get_args(), $cacheKey);
28
    }
29
30
    public function decrement($column, $amount = 1, array $extra = [])
31
    {
32
        $this->cache($this->makeCacheTags())
33
            ->flush();
34
35
        return parent::decrement($column, $amount, $extra);
36
    }
37
38
    public function delete()
39
    {
40
        $this->cache($this->makeCacheTags())
41
            ->flush();
42
43
        return parent::delete();
44
    }
45
46
    /**
47
     * @SuppressWarnings(PHPMD.ShortVariable)
48
     */
49
    public function find($id, $columns = ["*"])
50
    {
51
        if (! $this->isCachable()) {
52
            return parent::find($id, $columns);
53
        }
54
55
        $idKey = collect($id)
56
            ->implode('_');
57
        $preStr = is_array($id)
58
            ? 'find_list'
59
            : 'find';
60
        $cacheKey = $this->makeCacheKey($columns, null, "-{$preStr}_{$idKey}");
61
62
        return $this->cachedValue(func_get_args(), $cacheKey);
63
    }
64
65
    public function first($columns = ["*"])
66
    {
67
        if (! $this->isCachable()) {
68
            return parent::first($columns);
69
        }
70
71
        $cacheKey = $this->makeCacheKey($columns, null, "-first");
72
73
        return $this->cachedValue(func_get_args(), $cacheKey);
74
    }
75
76
    public function forceDelete()
77
    {
78
        $this->cache($this->makeCacheTags())
79
            ->flush();
80
81
        return parent::forceDelete();
82
    }
83
84
    public function get($columns = ["*"])
85
    {
86
        if (! $this->isCachable()) {
87
            return parent::get($columns);
88
        }
89
90
        $cacheKey = $this->makeCacheKey($columns);
91
92
        return $this->cachedValue(func_get_args(), $cacheKey);
93
    }
94
95
    public function increment($column, $amount = 1, array $extra = [])
96
    {
97
        $this->cache($this->makeCacheTags())
98
            ->flush();
99
100
        return parent::increment($column, $amount, $extra);
101
    }
102
103
    public function inRandomOrder($seed = '')
104
    {
105
        $this->isCachable = false;
106
107
        return parent::inRandomOrder($seed);
108
    }
109
110
    public function insert(array $values)
111
    {
112
        $this->checkCooldownAndFlushAfterPersisting($this->model);
113
114
        return parent::insert($values);
115
    }
116
117
    public function max($column)
118
    {
119
        if (! $this->isCachable()) {
120
            return parent::max($column);
121
        }
122
123
        $cacheKey = $this->makeCacheKey(["*"], null, "-max_{$column}");
124
125
        return $this->cachedValue(func_get_args(), $cacheKey);
126
    }
127
128
    public function min($column)
129
    {
130
        if (! $this->isCachable()) {
131
            return parent::min($column);
132
        }
133
134
        $cacheKey = $this->makeCacheKey(["*"], null, "-min_{$column}");
135
136
        return $this->cachedValue(func_get_args(), $cacheKey);
137
    }
138
139
    public function paginate(
140
        $perPage = null,
141
        $columns = ["*"],
142
        $pageName = "page",
143
        $page = null
144
    ) {
145
        if (! $this->isCachable()) {
146
            return parent::paginate($perPage, $columns, $pageName, $page);
147
        }
148
149
        $page = app('request')->input($pageName)
150
            ?: $page
151
            ?: 1;
152
153
        if (is_array($page)) {
154
            $page = $this->recursiveImplodeWithKey($page);
155
        }
156
        $cacheKey = $this->makeCacheKey($columns, null, "-paginate_by_{$perPage}_{$pageName}_{$page}");
157
158
        return $this->cachedValue(func_get_args(), $cacheKey);
159
    }
160
161
    protected function recursiveImplodeWithKey(array $items, string $glue = "_") : string
162
    {
163
        $result = "";
164
165
        foreach ($items as $key => $value) {
166
            $result .= $glue . $key . $glue . $value;
167
        }
168
169
        return $result;
170
    }
171
172
    public function pluck($column, $key = null)
173
    {
174
        if (! $this->isCachable()) {
175
            return parent::pluck($column, $key);
176
        }
177
178
        $keyDifferentiator = "-pluck_{$column}" . ($key ? "_{$key}" : "");
179
        $cacheKey = $this->makeCacheKey([$column], null, $keyDifferentiator);
180
181
        return $this->cachedValue(func_get_args(), $cacheKey);
182
    }
183
184
    public function sum($column)
185
    {
186
        if (! $this->isCachable()) {
187
            return parent::sum($column);
188
        }
189
190
        $cacheKey = $this->makeCacheKey(["*"], null, "-sum_{$column}");
191
192
        return $this->cachedValue(func_get_args(), $cacheKey);
193
    }
194
195
    public function update(array $values)
196
    {
197
        $this->checkCooldownAndFlushAfterPersisting($this->model);
198
199
        return parent::update($values);
200
    }
201
202
    public function value($column)
203
    {
204
        if (! $this->isCachable()) {
205
            return parent::value($column);
206
        }
207
208
        $cacheKey = $this->makeCacheKey(["*"], null, "-value_{$column}");
209
210
        return $this->cachedValue(func_get_args(), $cacheKey);
211
    }
212
213
    public function cachedValue(array $arguments, string $cacheKey)
214
    {
215
        $method = debug_backtrace()[1]['function'];
216
        $cacheTags = $this->makeCacheTags();
217
        $hashedCacheKey = sha1($cacheKey);
218
        $result = $this->retrieveCachedValue(
219
            $arguments,
220
            $cacheKey,
221
            $cacheTags,
222
            $hashedCacheKey,
223
            $method
224
        );
225
226
        return $this->preventHashCollision(
227
            $result,
228
            $arguments,
229
            $cacheKey,
230
            $cacheTags,
231
            $hashedCacheKey,
232
            $method
233
        );
234
    }
235
236
    protected function preventHashCollision(
237
        array $result,
238
        array $arguments,
239
        string $cacheKey,
240
        array $cacheTags,
241
        string $hashedCacheKey,
242
        string $method
243
    ) {
244
        if ($result["key"] === $cacheKey) {
245
            return $result["value"];
246
        }
247
248
        $this->cache()
249
            ->tags($cacheTags)
250
            ->forget($hashedCacheKey);
251
252
        return $this->retrieveCachedValue(
253
            $arguments,
254
            $cacheKey,
255
            $cacheTags,
256
            $hashedCacheKey,
257
            $method
258
        );
259
    }
260
261
    protected function retrieveCachedValue(
262
        array $arguments,
263
        string $cacheKey,
264
        array $cacheTags,
265
        string $hashedCacheKey,
266
        string $method
267
    ) {
268
        if (property_exists($this, "model")) {
269
            $this->checkCooldownAndRemoveIfExpired($this->model);
270
        }
271
272
        if (method_exists($this, "getModel")) {
273
            $this->checkCooldownAndRemoveIfExpired($this->getModel());
274
        }
275
276
        return $this->cache($cacheTags)
277
            ->rememberForever(
278
                $hashedCacheKey,
279
                function () use ($arguments, $cacheKey, $method) {
280
                    return [
281
                        "key" => $cacheKey,
282
                        "value" => parent::{$method}(...$arguments),
283
                    ];
284
                }
285
            );
286
    }
287
}
288