Passed
Pull Request — master (#274)
by
unknown
03:01
created

Buildable::get()   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
        $cacheKey = $this->makeCacheKey($columns, null, "-{$preStr}_{$idKey}");
63
64
        return $this->cachedValue(func_get_args(), $cacheKey);
65
    }
66
67
    public function first($columns = ["*"])
68
    {
69
        if (! $this->isCachable()) {
70
            return parent::first($columns);
71
        }
72
73
        $cacheKey = $this->makeCacheKey($columns, null, "-first");
74
75
        return $this->cachedValue(func_get_args(), $cacheKey);
76
    }
77
78
    public function forceDelete()
79
    {
80
        $this->cache($this->makeCacheTags())
81
            ->flush();
82
83
        return parent::forceDelete();
84
    }
85
86
    public function get($columns = ["*"])
87
    {
88
        if (! $this->isCachable()) {
89
            return parent::get($columns);
90
        }
91
92
        $cacheKey = $this->makeCacheKey($columns);
93
94
        return $this->cachedValue(func_get_args(), $cacheKey);
95
    }
96
97
    public function increment($column, $amount = 1, array $extra = [])
98
    {
99
        $this->cache($this->makeCacheTags())
100
            ->flush();
101
102
        return parent::increment($column, $amount, $extra);
103
    }
104
105
    public function inRandomOrder($seed = '')
106
    {
107
        $this->isCachable = false;
108
109
        return parent::inRandomOrder($seed);
110
    }
111
112
    public function insert(array $values)
113
    {
114
        $this->checkCooldownAndFlushAfterPersisting($this->model);
115
116
        return parent::insert($values);
117
    }
118
119
    public function max($column)
120
    {
121
        if (! $this->isCachable()) {
122
            return parent::max($column);
123
        }
124
125
        $cacheKey = $this->makeCacheKey(["*"], null, "-max_{$column}");
126
127
        return $this->cachedValue(func_get_args(), $cacheKey);
128
    }
129
130
    public function min($column)
131
    {
132
        if (! $this->isCachable()) {
133
            return parent::min($column);
134
        }
135
136
        $cacheKey = $this->makeCacheKey(["*"], null, "-min_{$column}");
137
138
        return $this->cachedValue(func_get_args(), $cacheKey);
139
    }
140
141
    public function paginate(
142
        $perPage = null,
143
        $columns = ["*"],
144
        $pageName = "page",
145
        $page = null
146
    ) {
147
        if (! $this->isCachable()) {
148
            return parent::paginate($perPage, $columns, $pageName, $page);
149
        }
150
151
        $page = Container::getInstance()
152
            ->make("request")
153
            ->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
            $result .= $glue . $key . $glue . $value;
171
        }
172
173
        return $result;
174
    }
175
176
    public function pluck($column, $key = null)
177
    {
178
        if (! $this->isCachable()) {
179
            return parent::pluck($column, $key);
180
        }
181
182
        $keyDifferentiator = "-pluck_{$column}" . ($key ? "_{$key}" : "");
183
        $cacheKey = $this->makeCacheKey([$column], null, $keyDifferentiator);
184
185
        return $this->cachedValue(func_get_args(), $cacheKey);
186
    }
187
188
    public function sum($column)
189
    {
190
        if (! $this->isCachable()) {
191
            return parent::sum($column);
192
        }
193
194
        $cacheKey = $this->makeCacheKey(["*"], null, "-sum_{$column}");
195
196
        return $this->cachedValue(func_get_args(), $cacheKey);
197
    }
198
199
    public function update(array $values)
200
    {
201
        $this->checkCooldownAndFlushAfterPersisting($this->model);
202
203
        return parent::update($values);
204
    }
205
206
    public function value($column)
207
    {
208
        if (! $this->isCachable()) {
209
            return parent::value($column);
210
        }
211
212
        $cacheKey = $this->makeCacheKey(["*"], null, "-value_{$column}");
213
214
        return $this->cachedValue(func_get_args(), $cacheKey);
215
    }
216
217
    public function cachedValue(array $arguments, string $cacheKey)
218
    {
219
        $method = debug_backtrace()[1]['function'];
220
        $cacheTags = $this->makeCacheTags();
221
        $hashedCacheKey = sha1($cacheKey);
222
        $result = $this->retrieveCachedValue(
223
            $arguments,
224
            $cacheKey,
225
            $cacheTags,
226
            $hashedCacheKey,
227
            $method
228
        );
229
230
        return $this->preventHashCollision(
231
            $result,
232
            $arguments,
233
            $cacheKey,
234
            $cacheTags,
235
            $hashedCacheKey,
236
            $method
237
        );
238
    }
239
240
    protected function preventHashCollision(
241
        array $result,
242
        array $arguments,
243
        string $cacheKey,
244
        array $cacheTags,
245
        string $hashedCacheKey,
246
        string $method
247
    ) {
248
        if ($result["key"] === $cacheKey) {
249
            return $result["value"];
250
        }
251
252
        $this->cache()
253
            ->tags($cacheTags)
254
            ->forget($hashedCacheKey);
255
256
        return $this->retrieveCachedValue(
257
            $arguments,
258
            $cacheKey,
259
            $cacheTags,
260
            $hashedCacheKey,
261
            $method
262
        );
263
    }
264
265
    protected function retrieveCachedValue(
266
        array $arguments,
267
        string $cacheKey,
268
        array $cacheTags,
269
        string $hashedCacheKey,
270
        string $method
271
    ) {
272
        if (property_exists($this, "model")) {
273
            $this->checkCooldownAndRemoveIfExpired($this->model);
274
        }
275
276
        $cache_callback = function () use ($arguments, $cacheKey, $method) {
277
            return [
278
              "key" => $cacheKey,
279
              "value" => parent::{$method}(...$arguments),
280
            ];
281
        };
282
283
        if (method_exists($this, "getModel")) {
284
            $this->checkCooldownAndRemoveIfExpired($this->getModel());
285
            if ($this->getModel()::maxCacheTimeout() > 0) {
286
                return $this->cache($cacheTags)
287
                  ->remember(
288
                    $hashedCacheKey,
289
                    $this->getModel()::maxCacheTimeout(),
290
                    $cache_callback
291
                  );
292
            }
293
        }
294
295
        return $this->cache($cacheTags)
296
            ->rememberForever(
297
                $hashedCacheKey,
298
                $cache_callback
299
            );
300
    }
301
}
302