Passed
Push — master ( 023a58...c85858 )
by Mike
06:09 queued 03:34
created

CachedBuilder::insert()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
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;
1 ignored issue
show
Bug introduced by
The trait GeneaLabs\LaravelModelCaching\Traits\Caching requires the property $cacheCooldownSeconds which is not provided by GeneaLabs\LaravelModelCaching\CachedBuilder.
Loading history...
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)
64
            ->implode('_');
65
        $preStr = is_array($id)
66
            ? 'find_list'
67
            : 'find';
68
        $cacheKey = $this->makeCacheKey($columns, null, "-{$preStr}_{$idKey}");
69
70
        return $this->cachedValue(func_get_args(), $cacheKey);
71
    }
72
73
    public function first($columns = ["*"])
74
    {
75
        if (! $this->isCachable()) {
76
            return parent::first($columns);
77
        }
78
79
        $cacheKey = $this->makeCacheKey($columns, null, "-first");
80
81
        return $this->cachedValue(func_get_args(), $cacheKey);
82
    }
83
84
    public function forceDelete()
85
    {
86
        $this->cache($this->makeCacheTags())
87
            ->flush();
88
89
        return parent::forceDelete();
90
    }
91
92
    public function get($columns = ["*"])
93
    {
94
        if (! $this->isCachable()) {
95
            return parent::get($columns);
96
        }
97
98
        $cacheKey = $this->makeCacheKey($columns);
99
100
        return $this->cachedValue(func_get_args(), $cacheKey);
101
    }
102
103
    public function increment($column, $amount = 1, array $extra = [])
104
    {
105
        $this->cache($this->makeCacheTags())
106
            ->flush();
107
108
        return parent::increment($column, $amount, $extra);
109
    }
110
111
    public function inRandomOrder($seed = '')
112
    {
113
        $this->isCachable = false;
114
115
        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

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