Passed
Push — master ( 4a84e5...3893f1 )
by Mike
03:42
created

Buildable::getRelation()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 2
nop 1
dl 0
loc 11
rs 10
c 0
b 0
f 0
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
        if (! is_array($columns)) {
72
            $columns = [$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);
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 = app('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
        if (property_exists($this, "model")) {
279
            $this->checkCooldownAndRemoveIfExpired($this->model);
280
        }
281
282
        if (method_exists($this, "getModel")) {
283
            $this->checkCooldownAndRemoveIfExpired($this->getModel());
284
        }
285
286
        return $this->cache($cacheTags)
287
            ->rememberForever(
288
                $hashedCacheKey,
289
                function () use ($arguments, $cacheKey, $method) {
290
                    return [
291
                        "key" => $cacheKey,
292
                        "value" => parent::{$method}(...$arguments),
293
                    ];
294
                }
295
            );
296
    }
297
}
298