Completed
Push — develop ( 99e2c8...c13420 )
by Abdelrahman
03:14
created

BaseRepository::isCacheable()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 3
eloc 3
nc 3
nop 0
1
<?php
2
3
/*
4
 * NOTICE OF LICENSE
5
 *
6
 * Part of the Rinvex Repository Package.
7
 *
8
 * This source file is subject to The MIT License (MIT)
9
 * that is bundled with this package in the LICENSE file.
10
 *
11
 * Package: Rinvex Repository Package
12
 * License: The MIT License (MIT)
13
 * Link:    https://rinvex.com
14
 */
15
16
namespace Rinvex\Repository\Repositories;
17
18
use Closure;
19
use Illuminate\Contracts\Container\Container;
20
use Rinvex\Repository\Contracts\RepositoryContract;
21
22
abstract class BaseRepository implements RepositoryContract
23
{
24
    /**
25
     * The IoC container instance.
26
     *
27
     * @var \Illuminate\Contracts\Container\Container
28
     */
29
    protected $container;
30
31
    /**
32
     * The repository model.
33
     *
34
     * @var object
35
     */
36
    protected $model;
37
38
    /**
39
     * The repository identifier.
40
     *
41
     * @var string
42
     */
43
    protected $repositoryId;
44
45
    /**
46
     * Indicate if the repository cache is enabled.
47
     *
48
     * @var bool
49
     */
50
    protected $cacheEnabled = true;
51
52
    /**
53
     * Indicate if the repository cache clear is enabled.
54
     *
55
     * @var bool
56
     */
57
    protected $cacheClearEnabled = true;
58
59
    /**
60
     * The repository cache lifetime.
61
     *
62
     * @var int
63
     */
64
    protected $cacheLifetime;
65
66
    /**
67
     * The repository cache driver.
68
     *
69
     * @var string
70
     */
71
    protected $cacheDriver;
72
73
    /**
74
     * Execute given callback and cache result set.
75
     *
76
     * @param string   $class
77
     * @param string   $method
78
     * @param string   $hash
0 ignored issues
show
Bug introduced by
There is no parameter named $hash. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
79
     * @param \Closure $closure
80
     *
81
     * @return mixed
82
     */
83
    protected function executeCallback($class, $method, $args, Closure $closure)
84
    {
85
        $driver   = $this->getCacheDriver();
86
        $lifetime = $this->getCacheLifetime();
87
        $hash     = md5(json_encode($args + [$driver, $lifetime, $this->model->toSql()]));
88
        $cacheKey = $class.'@'.$method.'.'.$hash;
89
90
        if ($driver) {
91
            // Switch cache driver on runtime
92
            $this->getContainer('cache')->setDefaultDriver($driver);
93
        }
94
95
        if ($this->isCacheable()) {
96
            if (method_exists($this->getContainer('cache')->getStore(), 'tags')) {
97
                return $lifetime === -1
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $lifetime (string) and -1 (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
98
                    ? $this->getContainer('cache')->tags($this->getRepositoryId())->rememberForever($cacheKey, $closure)
99
                    : $this->getContainer('cache')->tags($this->getRepositoryId())->remember($cacheKey, $lifetime, $closure);
100
            }
101
102
            // Store cache keys by mimicking cache tags
103
            $this->storeCacheKeys($class, $method, $hash);
104
105
            return $lifetime === -1
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $lifetime (string) and -1 (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
106
                ? $this->getContainer('cache')->rememberForever($cacheKey, $closure)
107
                : $this->getContainer('cache')->remember($cacheKey, $lifetime, $closure);
108
        }
109
110
        return call_user_func($closure);
111
    }
112
113
    /**
114
     * Set the IoC container instance.
115
     *
116
     * @param \Illuminate\Contracts\Container\Container $container
117
     *
118
     * @return $this
119
     */
120
    public function setContainer(Container $container)
121
    {
122
        $this->container = $container;
123
124
        return $this;
125
    }
126
127
    /**
128
     * Get the IoC container instance or any of it's services.
129
     *
130
     * @param string|null $service
131
     *
132
     * @return mixed
133
     */
134
    public function getContainer($service = null)
135
    {
136
        return is_null($service) ? ($this->container ?: app()) : ($this->container[$service] ?: app($service));
137
    }
138
139
    /**
140
     * Set the repository identifier.
141
     *
142
     * @param string $repositoryId
143
     *
144
     * @return $this
145
     */
146
    public function setRepositoryId($repositoryId)
147
    {
148
        $this->repositoryId = $repositoryId;
149
150
        return $this;
151
    }
152
153
    /**
154
     * Get the repository identifier.
155
     *
156
     * @return string
157
     */
158
    public function getRepositoryId()
159
    {
160
        return $this->repositoryId ?: get_called_class();
161
    }
162
163
    /**
164
     * Set the repository cache lifetime.
165
     *
166
     * @param string $cacheLifetime
167
     *
168
     * @return $this
169
     */
170
    public function setCacheLifetime($cacheLifetime)
171
    {
172
        $this->cacheLifetime = $cacheLifetime;
0 ignored issues
show
Documentation Bug introduced by
The property $cacheLifetime was declared of type integer, but $cacheLifetime is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
173
174
        return $this;
175
    }
176
177
    /**
178
     * Get the repository cache lifetime.
179
     *
180
     * @return string
181
     */
182
    public function getCacheLifetime()
183
    {
184
        return ! is_null($this->cacheLifetime) ? $this->cacheLifetime : $this->getContainer('config')->get('rinvex.repository.cache.lifetime');
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 143 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
185
    }
186
187
    /**
188
     * Set the repository cache driver.
189
     *
190
     * @param string $cacheDriver
191
     *
192
     * @return $this
193
     */
194
    public function setCacheDriver($cacheDriver)
195
    {
196
        $this->cacheDriver = $cacheDriver;
197
198
        return $this;
199
    }
200
201
    /**
202
     * Get the repository cache driver.
203
     *
204
     * @return string
205
     */
206
    public function getCacheDriver()
207
    {
208
        return $this->cacheDriver;
209
    }
210
211
    /**
212
     * Enable repository cache.
213
     *
214
     * @param bool $status
215
     *
216
     * @return $this
217
     */
218
    public function enableCache($status = true)
219
    {
220
        $this->cacheEnabled = $status;
221
222
        return $this;
223
    }
224
225
    /**
226
     * Determine if repository cache is enabled.
227
     *
228
     * @return bool
229
     */
230
    public function isCacheEnabled()
231
    {
232
        return $this->cacheEnabled;
233
    }
234
235
    /**
236
     * Enable repository cache clear.
237
     *
238
     * @param bool $status
239
     *
240
     * @return $this
241
     */
242
    public function enableCacheClear($status = true)
243
    {
244
        $this->cacheClearEnabled = $status;
245
246
        return $this;
247
    }
248
249
    /**
250
     * Determine if repository cache clear is enabled.
251
     *
252
     * @return bool
253
     */
254
    public function isCacheClearEnabled()
255
    {
256
        return $this->cacheClearEnabled;
257
    }
258
259
    /**
260
     * Forget the repository cache.
261
     *
262
     * @return $this
263
     */
264
    public function forgetCache()
265
    {
266
        if ($this->isCacheEnabled() && $this->getCacheLifetime()) {
267
            if (method_exists($this->getContainer('cache')->getStore(), 'tags')) {
268
                $this->getContainer('cache')->tags($this->getRepositoryId())->flush();
269
            } else {
270
                // Flush cache keys by mimicking cache tags
271
                foreach ($this->flushCacheKeys() as $cacheKey) {
272
                    $this->getContainer('cache')->forget($cacheKey);
273
                }
274
            }
275
276
            $this->getContainer('events')->fire($this->getRepositoryId().'.entity.cache.flushed', [$this]);
277
        }
278
279
        return $this;
280
    }
281
282
    /**
283
     * Set the relationships that should be eager loaded.
284
     *
285
     * @param mixed $relations
286
     *
287
     * @return $this
288
     */
289
    public function with($relations)
290
    {
291
        $this->model = $this->model->with($relations);
292
293
        return $this;
294
    }
295
296
    /**
297
     * Add an "order by" clause to the repository.
298
     *
299
     * @param string $column
300
     * @param string $direction
301
     *
302
     * @return $this
303
     */
304
    public function orderBy($column, $direction = 'asc')
305
    {
306
        $this->model = $this->model->orderBy($column, $direction);
307
308
        return $this;
309
    }
310
311
    /**
312
     * Register a new global scope.
313
     *
314
     * @param \Illuminate\Database\Eloquent\Scope|\Closure|string $scope
315
     * @param \Closure|null                                       $implementation
316
     *
317
     * @throws \InvalidArgumentException
318
     *
319
     * @return mixed
320
     */
321
    public function addGlobalScope($scope, Closure $implementation = null)
322
    {
323
        return $this->model->addGlobalScope($scope, $implementation);
324
    }
325
326
    /**
327
     * Remove all or passed registered global scopes.
328
     *
329
     * @param array|null $scopes
330
     *
331
     * @return $this
332
     */
333
    public function withoutGlobalScopes(array $scopes = null)
334
    {
335
        $this->model = $this->model->withoutGlobalScopes($scopes);
336
337
        return $this;
338
    }
339
340
    /**
341
     * Dynamically pass missing static methods to the model.
342
     *
343
     * @param $method
344
     * @param $parameters
345
     *
346
     * @return mixed
347
     */
348
    public static function __callStatic($method, $parameters)
349
    {
350
        return call_user_func_array([new static(), $method], $parameters);
351
    }
352
353
    /**
354
     * Dynamically pass missing methods to the model.
355
     *
356
     * @param string $method
357
     * @param array  $parameters
358
     *
359
     * @return mixed
360
     */
361
    public function __call($method, $parameters)
362
    {
363
        $model = $this->model;
364
365
        return call_user_func_array([$model, $method], $parameters);
366
    }
367
368
    /**
369
     * Store cache keys by mimicking cache tags.
370
     *
371
     * @param string $class
372
     * @param string $method
373
     * @param string $hash
374
     *
375
     * @return void
376
     */
377
    protected function storeCacheKeys($class, $method, $hash)
378
    {
379
        $keysFile  = $this->getContainer('config')->get('rinvex.repository.cache.keys_file');
380
        $cacheKeys = $this->getCacheKeys($keysFile);
381
382
        if (! isset($cacheKeys[$class]) || ! in_array($method.'.'.$hash, $cacheKeys[$class])) {
383
            $cacheKeys[$class][] = $method.'.'.$hash;
384
            file_put_contents($keysFile, json_encode($cacheKeys));
385
        }
386
    }
387
388
    /**
389
     * Flush cache keys by mimicking cache tags.
390
     *
391
     * @return array
392
     */
393
    protected function flushCacheKeys()
394
    {
395
        $flushedKeys  = [];
396
        $calledClasss = get_called_class();
397
        $config       = $this->getContainer('config')->get('rinvex.repository.cache');
398
        $cacheKeys    = $this->getCacheKeys($config['keys_file']);
399
400
        if (isset($cacheKeys[$calledClasss]) && is_array($cacheKeys[$calledClasss])) {
401
            foreach ($cacheKeys[$calledClasss] as $cacheKey) {
402
                $flushedKeys[] = $calledClasss.'@'.$cacheKey;
403
            }
404
405
            unset($cacheKeys[$calledClasss]);
406
            file_put_contents($config['keys_file'], json_encode($cacheKeys));
407
        }
408
409
        return $flushedKeys;
410
    }
411
412
    /**
413
     * Get cache keys.
414
     *
415
     * @param string $file
416
     *
417
     * @return array
418
     */
419
    protected function getCacheKeys($file)
420
    {
421
        return json_decode(file_get_contents(file_exists($file) ? $file : file_put_contents($file, null)), true) ?: [];
422
    }
423
424
    /**
425
     * Determine if repository is cacheable.
426
     *
427
     * @return bool
428
     */
429
    protected function isCacheable()
430
    {
431
        return $this->isCacheEnabled() && $this->getCacheLifetime()
432
               && ! $this->getContainer('request')->has($this->getContainer('config')->get('rinvex.repository.cache.skip_uri'));
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 128 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
433
    }
434
}
435