Passed
Push — master ( f0c247...f9be69 )
by Mike
04:04 queued 11s
created

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