Passed
Push — master ( 4157ba...7be804 )
by Mike
05:01
created

CachedBuilder::sum()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php namespace GeneaLabs\LaravelModelCaching;
2
3
use GeneaLabs\LaravelModelCaching\Traits\BuilderCaching;
4
use GeneaLabs\LaravelModelCaching\Traits\Caching;
5
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
6
use Illuminate\Support\Collection;
7
8
/**
9
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
10
 */
11
class CachedBuilder extends EloquentBuilder
12
{
13
    use BuilderCaching;
14
    use Caching;
15
16
    public function avg($column)
17
    {
18
        if (! $this->isCachable()) {
19
            return parent::avg($column);
20
        }
21
22
        $cacheKey = $this->makeCacheKey(["*"], null, "-avg_{$column}");
23
24
        return $this->cachedValue(func_get_args(), $cacheKey);
25
    }
26
27
    public function count($columns = "*")
28
    {
29
        if (! $this->isCachable()) {
30
            return parent::count($columns);
31
        }
32
33
        $cacheKey = $this->makeCacheKey([$columns], null, "-count");
34
35
        return $this->cachedValue(func_get_args(), $cacheKey);
36
    }
37
38
    public function decrement($column, $amount = 1, array $extra = [])
39
    {
40
        $this->cache($this->makeCacheTags())
41
            ->flush();
42
43
        return parent::decrement($column, $amount, $extra);
44
    }
45
46
    public function delete()
47
    {
48
        $this->cache($this->makeCacheTags())
49
            ->flush();
50
51
        return parent::delete();
52
    }
53
54
    /**
55
     * @SuppressWarnings(PHPMD.ShortVariable)
56
     */
57
    public function find($id, $columns = ["*"])
58
    {
59
        if (! $this->isCachable()) {
60
            return parent::find($id, $columns);
61
        }
62
63
        $idKey = collect($id)->implode('-');
64
        $cacheKey = $this->makeCacheKey($columns, null, "-find_{$idKey}");
65
66
        return $this->cachedValue(func_get_args(), $cacheKey);
67
    }
68
69
    public function first($columns = ["*"])
70
    {
71
        if (! $this->isCachable()) {
72
            return parent::first($columns);
73
        }
74
75
        $cacheKey = $this->makeCacheKey($columns, null, "-first");
76
77
        return $this->cachedValue(func_get_args(), $cacheKey);
78
    }
79
80
    public function forceDelete()
81
    {
82
        $this->cache($this->makeCacheTags())
83
            ->flush();
84
85
        return parent::forceDelete();
86
    }
87
88
    public function get($columns = ["*"])
89
    {
90
        if (! $this->isCachable()) {
91
            return parent::get($columns);
92
        }
93
94
        $cacheKey = $this->makeCacheKey($columns);
95
96
        return $this->cachedValue(func_get_args(), $cacheKey);
97
    }
98
99
    public function increment($column, $amount = 1, array $extra = [])
100
    {
101
        $this->cache($this->makeCacheTags())
102
            ->flush();
103
104
        return parent::increment($column, $amount, $extra);
105
    }
106
107
    public function inRandomOrder($seed = '')
108
    {
109
        $this->isCachable = false;
110
111
        return parent::inRandomOrder($seed);
1 ignored issue
show
introduced by
The method inRandomOrder() does not exist on Illuminate\Database\Eloquent\Builder. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

111
        return parent::/** @scrutinizer ignore-call */ inRandomOrder($seed);
Loading history...
112
    }
113
114
    public function insert(array $values)
115
    {
116
        $this->checkCooldownAndFlushAfterPersisting($this->model);
117
118
        return parent::insert($values);
119
    }
120
121
    public function max($column)
122
    {
123
        if (! $this->isCachable()) {
124
            return parent::max($column);
125
        }
126
127
        $cacheKey = $this->makeCacheKey(["*"], null, "-max_{$column}");
128
129
        return $this->cachedValue(func_get_args(), $cacheKey);
130
    }
131
132
    public function min($column)
133
    {
134
        if (! $this->isCachable()) {
135
            return parent::min($column);
136
        }
137
138
        $cacheKey = $this->makeCacheKey(["*"], null, "-min_{$column}");
139
140
        return $this->cachedValue(func_get_args(), $cacheKey);
141
    }
142
143
    public function paginate(
144
        $perPage = null,
145
        $columns = ["*"],
146
        $pageName = "page",
147
        $page = null
148
    ) {
149
        if (! $this->isCachable()) {
150
            return parent::paginate($perPage, $columns, $pageName, $page);
151
        }
152
153
        $page = request()->input($pageName)
154
            ?: $page
155
            ?: 1;
156
157
        if (is_array($page)) {
158
            $page = $this->recursiveImplodeWithKey($page);
159
        }
160
        $cacheKey = $this->makeCacheKey($columns, null, "-paginate_by_{$perPage}_{$pageName}_{$page}");
161
162
        return $this->cachedValue(func_get_args(), $cacheKey);
163
    }
164
165
    protected function recursiveImplodeWithKey(array $items, string $glue = "_") : string
166
    {
167
        $result = "";
168
169
        foreach ($items as $key => $value) {
170
            if (is_array($value)) {
171
                $result .= $key . $glue . $this->recursiveImplodeWithKey($value, $glue);
172
173
                continue;
174
            }
175
176
            $result .= $glue . $key . $glue . $value;
177
        }
178
179
        return $result;
180
    }
181
182
    public function pluck($column, $key = null)
183
    {
184
        if (! $this->isCachable()) {
185
            return parent::pluck($column, $key);
186
        }
187
188
        $keyDifferentiator = "-pluck_{$column}" . ($key ? "_{$key}" : "");
189
        $cacheKey = $this->makeCacheKey([$column], null, $keyDifferentiator);
190
191
        return $this->cachedValue(func_get_args(), $cacheKey);
192
    }
193
194
    public function sum($column)
195
    {
196
        if (! $this->isCachable()) {
197
            return parent::sum($column);
198
        }
199
200
        $cacheKey = $this->makeCacheKey(["*"], null, "-sum_{$column}");
201
202
        return $this->cachedValue(func_get_args(), $cacheKey);
203
    }
204
205
    public function update(array $values)
206
    {
207
        $this->checkCooldownAndFlushAfterPersisting($this->model);
208
209
        return parent::update($values);
210
    }
211
212
    public function value($column)
213
    {
214
        if (! $this->isCachable()) {
215
            return parent::value($column);
216
        }
217
218
        $cacheKey = $this->makeCacheKey(["*"], null, "-value_{$column}");
219
220
        return $this->cachedValue(func_get_args(), $cacheKey);
221
    }
222
223
    public function cachedValue(array $arguments, string $cacheKey)
224
    {
225
        $method = debug_backtrace()[1]['function'];
226
        $cacheTags = $this->makeCacheTags();
227
        $hashedCacheKey = sha1($cacheKey);
228
        $result = $this->retrieveCachedValue(
229
            $arguments,
230
            $cacheKey,
231
            $cacheTags,
232
            $hashedCacheKey,
233
            $method
234
        );
235
236
        return $this->preventHashCollision(
237
            $result,
238
            $arguments,
239
            $cacheKey,
240
            $cacheTags,
241
            $hashedCacheKey,
242
            $method
243
        );
244
    }
245
246
    protected function preventHashCollision(
247
        array $result,
248
        array $arguments,
249
        string $cacheKey,
250
        array $cacheTags,
251
        string $hashedCacheKey,
252
        string $method
253
    ) {
254
        if ($result["key"] === $cacheKey) {
255
            return $result["value"];
256
        }
257
258
        $this->cache()
259
            ->tags($cacheTags)
260
            ->forget($hashedCacheKey);
261
262
        return $this->retrieveCachedValue(
263
            $arguments,
264
            $cacheKey,
265
            $cacheTags,
266
            $hashedCacheKey,
267
            $method
268
        );
269
    }
270
271
    protected function retrieveCachedValue(
272
        array $arguments,
273
        string $cacheKey,
274
        array $cacheTags,
275
        string $hashedCacheKey,
276
        string $method
277
    ) {
278
        $this->checkCooldownAndRemoveIfExpired($this->model);
279
280
        return $this->cache($cacheTags)
281
            ->rememberForever(
282
                $hashedCacheKey,
283
                function () use ($arguments, $cacheKey, $method) {
284
                    return [
285
                        "key" => $cacheKey,
286
                        "value" => parent::{$method}(...$arguments),
287
                    ];
288
                }
289
            );
290
    }
291
}
292