Test Failed
Push — master ( d418fd...9098a2 )
by Mike
08:47
created

CachedBuilder::preventHashCollision()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.0856
c 0
b 0
f 0
cc 2
eloc 11
nc 2
nop 6
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(['*'], null, "-find_{$id}");
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 paginate(
129
        $perPage = null,
130
        $columns = ['*'],
131
        $pageName = 'page',
132
        $page = null
133
    ) {
134
        if (! $this->isCachable) {
135
            return parent::paginate($perPage, $columns, $pageName, $page);
136
        }
137
138
        $arguments = func_get_args();
139
        $page = $page ?: 1;
140
        $cacheKey = $this->makeCacheKey($columns, null, "-paginate_by_{$perPage}_{$pageName}_{$page}");
141
        $method = 'paginate';
142
143
        return $this->cachedValue($arguments, $cacheKey, $method);
144
    }
145
146
    public function pluck($column, $key = null)
147
    {
148
        if (! $this->isCachable) {
149
            return parent::pluck($column, $key);
150
        }
151
152
        $keyDifferentiator = "-pluck_{$column}" . ($key ? "_{$key}" : "");
153
        $arguments = func_get_args();
154
        $cacheKey = $this->makeCacheKey([$column], null, $keyDifferentiator);
155
        $method = 'pluck';
156
157
        return $this->cachedValue($arguments, $cacheKey, $method);
158
    }
159
160
    public function sum($column)
161
    {
162
        if (! $this->isCachable) {
163
            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

163
            return parent::/** @scrutinizer ignore-call */ sum($column);
Loading history...
164
        }
165
166
        $arguments = func_get_args();
167
        $cacheKey = $this->makeCacheKey(['*'], null, "-sum_{$column}");
168
        $method = 'sum';
169
170
        return $this->cachedValue($arguments, $cacheKey, $method);
171
    }
172
173
    public function value($column)
174
    {
175
        if (! $this->isCachable) {
176
            return parent::value($column);
177
        }
178
179
        $arguments = func_get_args();
180
        $cacheKey = $this->makeCacheKey(['*'], null, "-value_{$column}");
181
        $method = 'value';
182
183
        return $this->cachedValue($arguments, $cacheKey, $method);
184
    }
185
186
    public function cachedValue(array $arguments, string $cacheKey, string $method)
187
    {
188
        $cacheTags = $this->makeCacheTags();
189
        $hashedCacheKey = sha1($cacheKey);
190
191
        $result = $this->retrieveCachedValue(
192
            $arguments,
193
            $cacheKey,
194
            $cacheTags,
195
            $hashedCacheKey,
196
            $method
197
        );
198
199
        return $this->preventHashCollision(
200
            $result,
201
            $arguments,
202
            $cacheKey,
203
            $cacheTags,
204
            $hashedCacheKey,
205
            $method
206
        );
207
    }
208
209
    protected function preventHashCollision(
210
        array $result,
211
        array $arguments,
212
        string $cacheKey,
213
        array $cacheTags,
214
        string $hashedCacheKey,
215
        string $method
216
    ) {
217
        if ($result['key'] !== $cacheKey) {
218
            $this->cache()
219
                ->tags($cacheTags)
220
                ->forget($hashedCacheKey);
221
222
            $result = $this->retrieveCachedValue(
223
                $arguments,
224
                $cacheKey,
225
                $cacheTags,
226
                $hashedCacheKey,
227
                $method
228
            );
229
        }
230
231
        return $result['value'];
232
    }
233
234
    protected function retrieveCachedValue(
235
        array $arguments,
236
        string $cacheKey,
237
        array $cacheTags,
238
        string $hashedCacheKey,
239
        string $method
240
    ) {
241
        return $this->cache($cacheTags)
242
            ->rememberForever(
243
                $hashedCacheKey,
244
                function () use ($arguments, $cacheKey, $method) {
245
                    return [
246
                        'key' => $cacheKey,
247
                        'value' => parent::{$method}(...$arguments),
248
                    ];
249
                }
250
            );
251
    }
252
}
253