Passed
Push — master ( 17add5...305685 )
by Mike
06:16 queued 03:24
created

Buildable::decrement()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 3
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php namespace GeneaLabs\LaravelModelCaching\Traits;
2
3
use Illuminate\Support\Collection;
4
use GeneaLabs\LaravelModelCaching\Tests\Fixtures\BaseModel;
5
6
/**
7
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
8
 */
9
trait Buildable
10
{
11
    public function avg($column)
12
    {
13
        if (! $this->isCachable()) {
14
            return parent::avg($column);
15
        }
16
17
        $cacheKey = $this->makeCacheKey(["*"], null, "-avg_{$column}");
18
19
        return $this->cachedValue(func_get_args(), $cacheKey);
20
    }
21
22
    public function count($columns = "*")
23
    {
24
        if (! $this->isCachable()) {
25
            return parent::count($columns);
26
        }
27
28
        $cacheKey = $this->makeCacheKey([$columns], null, "-count");
29
30
        return $this->cachedValue(func_get_args(), $cacheKey);
31
    }
32
33
    public function decrement($column, $amount = 1, array $extra = [])
34
    {
35
        $this->cache($this->makeCacheTags())
36
            ->flush();
37
38
        return parent::decrement($column, $amount, $extra);
39
    }
40
41
    public function delete()
42
    {
43
        $this->cache($this->makeCacheTags())
44
            ->flush();
45
46
        return parent::delete();
47
    }
48
49
    /**
50
     * @SuppressWarnings(PHPMD.ShortVariable)
51
     */
52
    public function find($id, $columns = ["*"])
53
    {
54
        if (! $this->isCachable()) {
55
            return parent::find($id, $columns);
56
        }
57
58
        $idKey = collect($id)
59
            ->implode('_');
60
        $preStr = is_array($id)
61
            ? 'find_list'
62
            : 'find';
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
        if (! is_array($columns)) {
75
            $columns = [$columns];
76
        }
77
78
        $cacheKey = $this->makeCacheKey($columns, null, "-first");
79
80
        return $this->cachedValue(func_get_args(), $cacheKey);
81
    }
82
83
    public function forceDelete()
84
    {
85
        $this->cache($this->makeCacheTags())
86
            ->flush();
87
88
        return parent::forceDelete();
89
    }
90
91
    public function get($columns = ["*"])
92
    {
93
        if (! $this->isCachable()) {
94
            return parent::get($columns);
95
        }
96
97
        $cacheKey = $this->makeCacheKey($columns);
98
99
        return $this->cachedValue(func_get_args(), $cacheKey);
100
    }
101
102
    public function increment($column, $amount = 1, array $extra = [])
103
    {
104
        $this->cache($this->makeCacheTags())
105
            ->flush();
106
107
        return parent::increment($column, $amount, $extra);
108
    }
109
110
    public function inRandomOrder($seed = '')
111
    {
112
        $this->isCachable = false;
113
114
        return parent::inRandomOrder($seed);
115
    }
116
117
    public function insert(array $values)
118
    {
119
        $this->checkCooldownAndFlushAfterPersisting($this->model);
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 = app('request')->input($pageName)
157
            ?: $page
158
            ?: 1;
159
160
        if (is_array($page)) {
161
            $page = $this->recursiveImplodeWithKey($page);
162
        }
163
        $cacheKey = $this->makeCacheKey($columns, null, "-paginate_by_{$perPage}_{$pageName}_{$page}");
164
165
        return $this->cachedValue(func_get_args(), $cacheKey);
166
    }
167
168
    public function getRelation($name)
169
    {
170
        $relation = parent::getRelation($name);
171
172
        if (! $this->isCachable()
173
            && is_a($relation->getQuery(), self::class)
174
        ) {
175
            $relation->getQuery()->disableModelCaching();
176
        }
177
178
        return $relation;
179
    }
180
181
    protected function recursiveImplodeWithKey(array $items, string $glue = "_") : string
182
    {
183
        $result = "";
184
185
        foreach ($items as $key => $value) {
186
            if (is_array($value)) {
187
                $result .= $key . $glue . $this->recursiveImplodeWithKey($value, $glue);
188
189
                continue;
190
            }
191
192
            $result .= $glue . $key . $glue . $value;
193
        }
194
195
        return $result;
196
    }
197
198
    public function pluck($column, $key = null)
199
    {
200
        if (! $this->isCachable()) {
201
            return parent::pluck($column, $key);
202
        }
203
204
        $keyDifferentiator = "-pluck_{$column}" . ($key ? "_{$key}" : "");
205
        $cacheKey = $this->makeCacheKey([$column], null, $keyDifferentiator);
206
207
        return $this->cachedValue(func_get_args(), $cacheKey);
208
    }
209
210
    public function sum($column)
211
    {
212
        if (! $this->isCachable()) {
213
            return parent::sum($column);
214
        }
215
216
        $cacheKey = $this->makeCacheKey(["*"], null, "-sum_{$column}");
217
218
        return $this->cachedValue(func_get_args(), $cacheKey);
219
    }
220
221
    public function update(array $values)
222
    {
223
        $this->checkCooldownAndFlushAfterPersisting($this->model);
224
225
        return parent::update($values);
226
    }
227
228
    public function value($column)
229
    {
230
        if (! $this->isCachable()) {
231
            return parent::value($column);
232
        }
233
234
        $cacheKey = $this->makeCacheKey(["*"], null, "-value_{$column}");
235
236
        return $this->cachedValue(func_get_args(), $cacheKey);
237
    }
238
239
    public function cachedValue(array $arguments, string $cacheKey)
240
    {
241
        $method = debug_backtrace()[1]['function'];
242
        $cacheTags = $this->makeCacheTags();
243
        $hashedCacheKey = sha1($cacheKey);
244
        $result = $this->retrieveCachedValue(
245
            $arguments,
246
            $cacheKey,
247
            $cacheTags,
248
            $hashedCacheKey,
249
            $method
250
        );
251
252
        return $this->preventHashCollision(
253
            $result,
254
            $arguments,
255
            $cacheKey,
256
            $cacheTags,
257
            $hashedCacheKey,
258
            $method
259
        );
260
    }
261
262
    protected function preventHashCollision(
263
        array $result,
264
        array $arguments,
265
        string $cacheKey,
266
        array $cacheTags,
267
        string $hashedCacheKey,
268
        string $method
269
    ) {
270
        if ($result["key"] === $cacheKey) {
271
            return $result["value"];
272
        }
273
274
        $this->cache()
275
            ->tags($cacheTags)
276
            ->forget($hashedCacheKey);
277
278
        return $this->retrieveCachedValue(
279
            $arguments,
280
            $cacheKey,
281
            $cacheTags,
282
            $hashedCacheKey,
283
            $method
284
        );
285
    }
286
287
    protected function retrieveCachedValue(
288
        array $arguments,
289
        string $cacheKey,
290
        array $cacheTags,
291
        string $hashedCacheKey,
292
        string $method
293
    ) {
294
        $model = new BaseModel;
295
296
        if (property_exists($this, "model")) {
297
            $model = $this->model;
298
        }
299
300
        if (\method_exists($this, "getModel")) {
301
            $model = $this->getModel();
302
        }
303
304
        $this->checkCooldownAndRemoveIfExpired($model);
305
306
        return $this->cache($cacheTags)
307
            ->rememberForever(
308
                $hashedCacheKey,
309
                function () use ($arguments, $cacheKey, $method) {
310
                    return [
311
                        "key" => $cacheKey,
312
                        "value" => parent::{$method}(...$arguments),
313
                    ];
314
                }
315
            );
316
    }
317
}
318