Passed
Push — master ( c47628...915eb6 )
by Mike
04:09
created

CachedBuilder::cachedValue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 15
nc 1
nop 3
1
<?php namespace GeneaLabs\LaravelModelCaching;
2
3
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
4
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
5
6
/**
7
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
8
 */
9
class CachedBuilder extends EloquentBuilder
10
{
11
    use Cachable;
12
13
    public function avg($column)
14
    {
15
        if (! $this->isCachable) {
16
            return parent::avg($column);
0 ignored issues
show
introduced by
The method avg() 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

16
            return parent::/** @scrutinizer ignore-call */ avg($column);
Loading history...
17
        }
18
19
        $arguments = func_get_args();
20
        $cacheKey = $this->makeCacheKey(['*'], null, "-avg_{$column}");
21
        $method = 'avg';
22
23
        return $this->cachedValue($arguments, $cacheKey, $method);
24
    }
25
26
    public function count($columns = ['*'])
27
    {
28
        if (! $this->isCachable) {
29
            return parent::count($columns);
1 ignored issue
show
introduced by
The method count() 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

29
            return parent::/** @scrutinizer ignore-call */ count($columns);
Loading history...
30
        }
31
32
        $arguments = func_get_args();
33
        $cacheKey = $this->makeCacheKey(['*'], null, "-count");
34
        $method = 'count';
35
36
        return $this->cachedValue($arguments, $cacheKey, $method);
37
    }
38
39
    public function cursor()
40
    {
41
        if (! $this->isCachable) {
42
            return collect(parent::cursor());
43
        }
44
45
        $arguments = func_get_args();
46
        $cacheKey = $this->makeCacheKey(['*'], null, "-cursor");
47
        $method = 'cursor';
48
49
        return $this->cachedValue($arguments, $cacheKey, $method);
50
    }
51
52
    public function delete()
53
    {
54
        $this->cache($this->makeCacheTags())
55
            ->flush();
56
57
        return parent::delete();
58
    }
59
60
    /**
61
     * @SuppressWarnings(PHPMD.ShortVariable)
62
     */
63
    public function find($id, $columns = ['*'])
64
    {
65
        if (! $this->isCachable) {
66
            return parent::find($id, $columns);
67
        }
68
69
        $arguments = func_get_args();
70
        $cacheKey = $this->makeCacheKey($columns);
71
        $method = 'find';
72
73
        return $this->cachedValue($arguments, $cacheKey, $method);
74
    }
75
76
    public function first($columns = ['*'])
77
    {
78
        if (! $this->isCachable) {
79
            return parent::first($columns);
80
        }
81
82
        $arguments = func_get_args();
83
        $cacheKey = $this->makeCacheKey($columns);
84
        $method = 'first';
85
86
        return $this->cachedValue($arguments, $cacheKey, $method);
87
    }
88
89
    public function get($columns = ['*'])
90
    {
91
        if (! $this->isCachable) {
92
            return parent::get($columns);
93
        }
94
95
        $arguments = func_get_args();
96
        $cacheKey = $this->makeCacheKey($columns);
97
        $method = 'get';
98
99
        return $this->cachedValue($arguments, $cacheKey, $method);
100
    }
101
102
    public function max($column)
103
    {
104
        if (! $this->isCachable) {
105
            return parent::max($column);
0 ignored issues
show
introduced by
The method max() 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

105
            return parent::/** @scrutinizer ignore-call */ max($column);
Loading history...
106
        }
107
108
        $arguments = func_get_args();
109
        $cacheKey = $this->makeCacheKey(['*'], null, "-max_{$column}");
110
        $method = 'max';
111
112
        return $this->cachedValue($arguments, $cacheKey, $method);
113
    }
114
115
    public function min($column)
116
    {
117
        if (! $this->isCachable) {
118
            return parent::min($column);
0 ignored issues
show
introduced by
The method min() 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

118
            return parent::/** @scrutinizer ignore-call */ min($column);
Loading history...
119
        }
120
121
        $arguments = func_get_args();
122
        $cacheKey = $this->makeCacheKey(['*'], null, "-min_{$column}");
123
        $method = 'min';
124
125
        return $this->cachedValue($arguments, $cacheKey, $method);
126
    }
127
128
    public function pluck($column, $key = null)
129
    {
130
        if (! $this->isCachable) {
131
            return parent::pluck($column, $key);
132
        }
133
134
        $keyDifferentiator = "-pluck_{$column}" . ($key ? "_{$key}" : "");
135
        $arguments = func_get_args();
136
        $cacheKey = $this->makeCacheKey([$column], null, $keyDifferentiator);
137
        $method = 'pluck';
138
139
        return $this->cachedValue($arguments, $cacheKey, $method);
140
    }
141
142
    public function sum($column)
143
    {
144
        if (! $this->isCachable) {
145
            return parent::sum($column);
0 ignored issues
show
introduced by
The method sum() 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

145
            return parent::/** @scrutinizer ignore-call */ sum($column);
Loading history...
146
        }
147
148
        $arguments = func_get_args();
149
        $cacheKey = $this->makeCacheKey(['*'], null, "-sum_{$column}");
150
        $method = 'sum';
151
152
        return $this->cachedValue($arguments, $cacheKey, $method);
153
    }
154
155
    public function value($column)
156
    {
157
        if (! $this->isCachable) {
158
            return parent::value($column);
159
        }
160
161
        $arguments = func_get_args();
162
        $cacheKey = $this->makeCacheKey(['*'], null, "-value_{$column}");
163
        $method = 'value';
164
165
        return $this->cachedValue($arguments, $cacheKey, $method);
166
    }
167
168
    public function cachedValue(array $arguments, string $cacheKey, string $method)
169
    {
170
        $cacheTags = $this->makeCacheTags();
171
        $hashedCacheKey = sha1($cacheKey);
172
173
        $result = $this->retrieveCachedValue(
174
            $arguments,
175
            $cacheKey,
176
            $cacheTags,
177
            $hashedCacheKey,
178
            $method
179
        );
180
181
        return $this->preventHashCollision(
182
            $result,
183
            $arguments,
184
            $cacheKey,
185
            $cacheTags,
186
            $hashedCacheKey,
187
            $method
188
        );
189
    }
190
191
    protected function preventHashCollision(
192
        array $result,
193
        array $arguments,
194
        string $cacheKey,
195
        array $cacheTags,
196
        string $hashedCacheKey,
197
        string $method
198
    ) {
199
        if ($result['key'] !== $cacheKey) {
200
            cache()->tags($cacheTags)->forget($hashedCacheKey);
201
202
            $result = $this->retrieveCachedValue(
203
                $arguments,
204
                $cacheKey,
205
                $cacheTags,
206
                $hashedCacheKey,
207
                $method
208
            );
209
        }
210
211
        return $result['value'];
212
    }
213
214
    protected function retrieveCachedValue(
215
        array $arguments,
216
        string $cacheKey,
217
        array $cacheTags,
218
        string $hashedCacheKey,
219
        string $method
220
    ) {
221
        return $this->cache($cacheTags)
222
            ->rememberForever(
223
                $hashedCacheKey,
224
                function () use ($arguments, $cacheKey, $method) {
225
                    return [
226
                        'key' => $cacheKey,
227
                        'value' => parent::{$method}(...$arguments),
228
                    ];
229
                }
230
            );
231
    }
232
}
233