This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | namespace Telefonica\Cacheable; |
||
6 | |||
7 | use Closure; |
||
8 | use Illuminate\Database\Eloquent\Model; |
||
9 | use Illuminate\Database\Eloquent\Builder; |
||
10 | |||
11 | trait CacheableEloquent |
||
12 | { |
||
13 | /** |
||
14 | * Register an updated model event with the dispatcher. |
||
15 | * |
||
16 | * @param \Closure|string $callback |
||
17 | * |
||
18 | * @return void |
||
19 | */ |
||
20 | abstract public static function updated($callback); |
||
21 | |||
22 | /** |
||
23 | * Register a created model event with the dispatcher. |
||
24 | * |
||
25 | * @param \Closure|string $callback |
||
26 | * |
||
27 | * @return void |
||
28 | */ |
||
29 | abstract public static function created($callback); |
||
30 | |||
31 | /** |
||
32 | * Register a deleted model event with the dispatcher. |
||
33 | * |
||
34 | * @param \Closure|string $callback |
||
35 | * |
||
36 | * @return void |
||
37 | */ |
||
38 | abstract public static function deleted($callback); |
||
39 | |||
40 | /** |
||
41 | * Boot the cacheable eloquent trait for a model. |
||
42 | * |
||
43 | * @return void |
||
44 | */ |
||
45 | public static function bootCacheableEloquent(): void |
||
46 | { |
||
47 | static::updated( |
||
48 | function (Model $cachedModel) { |
||
49 | ! $cachedModel->isCacheClearEnabled() || $cachedModel::forgetCache(); |
||
50 | } |
||
51 | ); |
||
52 | |||
53 | static::created( |
||
54 | function (Model $cachedModel) { |
||
55 | ! $cachedModel->isCacheClearEnabled() || $cachedModel::forgetCache(); |
||
56 | } |
||
57 | ); |
||
58 | |||
59 | static::deleted( |
||
60 | function (Model $cachedModel) { |
||
61 | ! $cachedModel->isCacheClearEnabled() || $cachedModel::forgetCache(); |
||
62 | } |
||
63 | ); |
||
64 | } |
||
65 | |||
66 | /** |
||
67 | * Store the given cache key for the given model by mimicking cache tags. |
||
68 | * |
||
69 | * @param string $modelName |
||
70 | * @param string $cacheKey |
||
71 | * |
||
72 | * @return void |
||
73 | */ |
||
74 | protected static function storeCacheKey(string $modelName, string $cacheKey): void |
||
75 | { |
||
76 | $keysFile = storage_path('framework/cache/data/sierratecnologia.cacheable.json'); |
||
77 | $cacheKeys = static::getCacheKeys($keysFile); |
||
78 | |||
79 | if (! isset($cacheKeys[$modelName]) || ! in_array($cacheKey, $cacheKeys[$modelName])) { |
||
80 | $cacheKeys[$modelName][] = $cacheKey; |
||
81 | file_put_contents($keysFile, json_encode($cacheKeys)); |
||
82 | } |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * Get cache keys from the given file. |
||
87 | * |
||
88 | * @param string $file |
||
89 | * |
||
90 | * @return array |
||
91 | */ |
||
92 | protected static function getCacheKeys($file): array |
||
93 | { |
||
94 | if (! file_exists($file)) { |
||
95 | $dir = dirname($file); |
||
96 | is_dir($dir) || mkdir($dir); |
||
97 | file_put_contents($file, null); |
||
98 | } |
||
99 | |||
100 | return json_decode(file_get_contents($file), true) ?: []; |
||
101 | } |
||
102 | |||
103 | /** |
||
104 | * Flush cache keys of the given model by mimicking cache tags. |
||
105 | * |
||
106 | * @param string $modelName |
||
107 | * |
||
108 | * @return array |
||
109 | */ |
||
110 | protected static function flushCacheKeys(string $modelName): array |
||
111 | { |
||
112 | $flushedKeys = []; |
||
113 | $keysFile = storage_path('framework/cache/data/sierratecnologia.cacheable.json'); |
||
114 | $cacheKeys = static::getCacheKeys($keysFile); |
||
115 | |||
116 | if (isset($cacheKeys[$modelName])) { |
||
117 | $flushedKeys = $cacheKeys[$modelName]; |
||
118 | |||
119 | unset($cacheKeys[$modelName]); |
||
120 | |||
121 | file_put_contents($keysFile, json_encode($cacheKeys)); |
||
122 | } |
||
123 | |||
124 | return $flushedKeys; |
||
125 | } |
||
126 | |||
127 | /** |
||
128 | * Set the model cache lifetime. |
||
129 | * |
||
130 | * @param int $cacheLifetime |
||
131 | * |
||
132 | * @return $this |
||
133 | */ |
||
134 | public function setCacheLifetime(int $cacheLifetime) |
||
135 | { |
||
136 | $this->cacheLifetime = $cacheLifetime; |
||
0 ignored issues
–
show
|
|||
137 | |||
138 | return $this; |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * Get the model cache lifetime. |
||
143 | * |
||
144 | * @return int |
||
145 | */ |
||
146 | public function getCacheLifetime(): int |
||
147 | { |
||
148 | return $this->cacheLifetime ?? -1; |
||
149 | } |
||
150 | |||
151 | /** |
||
152 | * Set the model cache driver. |
||
153 | * |
||
154 | * @param string $cacheDriver |
||
155 | * |
||
156 | * @return $this |
||
157 | */ |
||
158 | public function setCacheDriver($cacheDriver) |
||
159 | { |
||
160 | $this->cacheDriver = $cacheDriver; |
||
0 ignored issues
–
show
The property
cacheDriver does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
161 | |||
162 | return $this; |
||
163 | } |
||
164 | |||
165 | /** |
||
166 | * Get the model cache driver. |
||
167 | * |
||
168 | * @return string|null |
||
169 | */ |
||
170 | public function getCacheDriver(): ?string |
||
171 | { |
||
172 | return $this->cacheDriver ?? null; |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * Determine if model cache clear is enabled. |
||
177 | * |
||
178 | * @return bool |
||
179 | */ |
||
180 | public function isCacheClearEnabled(): bool |
||
181 | { |
||
182 | return $this->cacheClearEnabled ?? true; |
||
0 ignored issues
–
show
The property
cacheClearEnabled does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
183 | } |
||
184 | |||
185 | /** |
||
186 | * Forget the model cache. |
||
187 | * |
||
188 | * @return void |
||
189 | */ |
||
190 | public static function forgetCache() |
||
191 | { |
||
192 | static::fireCacheFlushEvent('cache.flushing'); |
||
193 | |||
194 | // Flush cache tags |
||
195 | if (method_exists(app('cache')->getStore(), 'tags')) { |
||
196 | app('cache')->tags(static::class)->flush(); |
||
197 | } else { |
||
198 | // Flush cache keys, then forget actual cache |
||
199 | foreach (static::flushCacheKeys(static::class) as $cacheKey) { |
||
200 | app('cache')->forget($cacheKey); |
||
201 | } |
||
202 | } |
||
203 | |||
204 | static::fireCacheFlushEvent('cache.flushed', false); |
||
205 | } |
||
206 | |||
207 | /** |
||
208 | * Fire the given event for the model. |
||
209 | * |
||
210 | * @param string $event |
||
211 | * @param bool $halt |
||
212 | * |
||
213 | * @return mixed |
||
214 | */ |
||
215 | protected static function fireCacheFlushEvent($event, $halt = true) |
||
216 | { |
||
217 | if (! isset(static::$dispatcher)) { |
||
218 | return true; |
||
219 | } |
||
220 | |||
221 | // We will append the names of the class to the event to distinguish it from |
||
222 | // other model events that are fired, allowing us to listen on each model |
||
223 | // event set individually instead of catching event for all the models. |
||
224 | $event = "eloquent.{$event}: ".static::class; |
||
225 | |||
226 | $method = $halt ? 'until' : 'dispatch'; |
||
227 | |||
228 | return static::$dispatcher->{$method}($event, static::class); |
||
229 | } |
||
230 | |||
231 | /** |
||
232 | * Reset cached model to its defaults. |
||
233 | * |
||
234 | * @return $this |
||
235 | */ |
||
236 | public function resetCacheConfig() |
||
237 | { |
||
238 | ! $this->cacheDriver || $this->cacheDriver = null; |
||
239 | ! $this->cacheLifetime || $this->cacheLifetime = -1; |
||
240 | |||
241 | return $this; |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * Generate unique cache key. |
||
246 | * |
||
247 | * @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $builder |
||
248 | * @param array $columns |
||
249 | * |
||
250 | * @return string |
||
251 | */ |
||
252 | protected function generateCacheKey($builder, array $columns): string |
||
253 | { |
||
254 | $query = $builder instanceof Builder ? $builder->getQuery() : $builder; |
||
0 ignored issues
–
show
The class
Illuminate\Database\Eloquent\Builder does not exist. Did you forget a USE statement, or did you not list all dependencies?
This error could be the result of: 1. Missing dependenciesPHP Analyzer uses your Are you sure this class is defined by one of your dependencies, or did you maybe
not list a dependency in either the 2. Missing use statementPHP does not complain about undefined classes in if ($x instanceof DoesNotExist) {
// Do something.
}
If you have not tested against this specific condition, such errors might go unnoticed. ![]() |
|||
255 | $vars = [ |
||
256 | 'aggregate' => $query->aggregate, |
||
257 | 'columns' => $query->columns, |
||
258 | 'distinct' => $query->distinct, |
||
259 | 'from' => $query->from, |
||
260 | 'joins' => $query->joins, |
||
261 | 'wheres' => $query->wheres, |
||
262 | 'groups' => $query->groups, |
||
263 | 'havings' => $query->havings, |
||
264 | 'orders' => $query->orders, |
||
265 | 'limit' => $query->limit, |
||
266 | 'offset' => $query->offset, |
||
267 | 'unions' => $query->unions, |
||
268 | 'unionLimit' => $query->unionLimit, |
||
269 | 'unionOffset' => $query->unionOffset, |
||
270 | 'unionOrders' => $query->unionOrders, |
||
271 | 'lock' => $query->lock, |
||
272 | ]; |
||
273 | |||
274 | return md5( |
||
275 | json_encode( |
||
276 | [ |
||
277 | $vars, |
||
278 | $columns, |
||
279 | static::class, |
||
280 | $this->getCacheDriver(), |
||
281 | $this->getCacheLifetime(), |
||
282 | $builder instanceof Builder ? $builder->getEagerLoads() : null, |
||
0 ignored issues
–
show
The class
Illuminate\Database\Eloquent\Builder does not exist. Did you forget a USE statement, or did you not list all dependencies?
This error could be the result of: 1. Missing dependenciesPHP Analyzer uses your Are you sure this class is defined by one of your dependencies, or did you maybe
not list a dependency in either the 2. Missing use statementPHP does not complain about undefined classes in if ($x instanceof DoesNotExist) {
// Do something.
}
If you have not tested against this specific condition, such errors might go unnoticed. ![]() |
|||
283 | $builder->getBindings(), |
||
284 | $builder->toSql(), |
||
285 | ] |
||
286 | ) |
||
287 | ); |
||
288 | } |
||
289 | |||
290 | /** |
||
291 | * Cache given callback. |
||
292 | * |
||
293 | * @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $builder |
||
294 | * @param array $columns |
||
295 | * @param \Closure $closure |
||
296 | * |
||
297 | * @return mixed |
||
298 | */ |
||
299 | public function cacheQuery($builder, array $columns, Closure $closure) |
||
300 | { |
||
301 | $modelName = $this->getMorphClass(); |
||
0 ignored issues
–
show
It seems like
getMorphClass() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
302 | $lifetime = $this->getCacheLifetime(); |
||
303 | $cacheKey = $this->generateCacheKey($builder, $columns); |
||
304 | |||
305 | // Switch cache driver on runtime |
||
306 | if ($driver = $this->getCacheDriver()) { |
||
307 | app('cache')->setDefaultDriver($driver); |
||
308 | } |
||
309 | |||
310 | // We need cache tags, check if default driver supports it |
||
311 | if (method_exists(app('cache')->getStore(), 'tags')) { |
||
312 | $result = $lifetime === -1 ? app('cache')->tags($modelName)->rememberForever($cacheKey, $closure) : app('cache')->tags($modelName)->remember($cacheKey, $lifetime, $closure); |
||
313 | |||
314 | return $result; |
||
315 | } |
||
316 | |||
317 | $result = $lifetime === -1 ? app('cache')->rememberForever($cacheKey, $closure) : app('cache')->remember($cacheKey, $lifetime, $closure); |
||
318 | |||
319 | // Default cache driver doesn't support tags, let's do it manually |
||
320 | static::storeCacheKey($modelName, $cacheKey); |
||
321 | |||
322 | // We're done, let's clean up! |
||
323 | $this->resetCacheConfig(); |
||
324 | |||
325 | return $result; |
||
326 | } |
||
327 | |||
328 | /** |
||
329 | * Create a new Eloquent query builder for the model. |
||
330 | * |
||
331 | * @param \Illuminate\Database\Query\Builder $query |
||
332 | * |
||
333 | * @return \Illuminate\Database\Eloquent\Builder|static |
||
334 | */ |
||
335 | public function newEloquentBuilder($query) |
||
336 | { |
||
337 | return new EloquentBuilder($query); |
||
338 | } |
||
339 | } |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: