Passed
Push — master ( 286e06...ca2f56 )
by Mike
04:55
created

Caching::getCachePrefix()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php namespace GeneaLabs\LaravelModelCaching\Traits;
2
3
use Carbon\Carbon;
4
use GeneaLabs\LaravelModelCaching\CacheKey;
5
use GeneaLabs\LaravelModelCaching\CacheTags;
6
use Illuminate\Cache\TaggableStore;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Database\Query\Builder;
9
10
trait Caching
11
{
12
    protected $isCachable = true;
13
14
    public function cache(array $tags = [])
15
    {
16
        $cache = app('cache');
17
18
        if (config('laravel-model-caching.store')) {
19
            $cache = $cache->store(config('laravel-model-caching.store'));
20
        }
21
22
        if (is_subclass_of($cache->getStore(), TaggableStore::class)) {
23
            $cache = $cache->tags($tags);
24
        }
25
26
        return $cache;
27
    }
28
29
    public function disableModelCaching()
30
    {
31
        $this->isCachable = false;
32
33
        return $this;
34
    }
35
36
    public function flushCache(array $tags = [])
37
    {
38
        if (count($tags) === 0) {
39
            $tags = $this->makeCacheTags();
40
        }
41
42
        $this->cache($tags)->flush();
43
44
        [$cacheCooldown] = $this->getModelCacheCooldown($this);
1 ignored issue
show
Bug introduced by
$this of type GeneaLabs\LaravelModelCaching\Traits\Caching is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $instance of GeneaLabs\LaravelModelCa...getModelCacheCooldown(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

44
        [$cacheCooldown] = $this->getModelCacheCooldown(/** @scrutinizer ignore-type */ $this);
Loading history...
45
46
        if ($cacheCooldown) {
0 ignored issues
show
introduced by
$cacheCooldown is of type Illuminate\Database\Eloquent\Collection, thus it always evaluated to true.
Loading history...
47
            $cachePrefix = $this->getCachePrefix();
48
            $modelClassName = get_class($this);
49
            $cacheKey = "{$cachePrefix}:{$modelClassName}-cooldown:saved-at";
50
51
            $this->cache()
52
                ->rememberForever($cacheKey, function () {
53
                    return (new Carbon)->now();
54
                });
55
        }
56
    }
57
58
    protected function getCachePrefix() : string
59
    {
60
        return "genealabs:laravel-model-caching:"
61
            . (config('laravel-model-caching.cache-prefix')
62
                ? config('laravel-model-caching.cache-prefix', '') . ":"
63
                : "");
64
    }
65
66
    protected function makeCacheKey(
67
        array $columns = ['*'],
68
        $idColumn = null,
69
        string $keyDifferentiator = ''
70
    ) : string {
71
        $eagerLoad = $this->eagerLoad ?? [];
72
        $model = $this->model ?? $this;
73
        $query = $this->query ?? app('db')->query();
74
75
        return (new CacheKey($eagerLoad, $model, $query))
1 ignored issue
show
Bug introduced by
It seems like $model can also be of type GeneaLabs\LaravelModelCaching\Traits\Caching; however, parameter $model of GeneaLabs\LaravelModelCa...CacheKey::__construct() does only seem to accept Illuminate\Database\Eloquent\Model, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

75
        return (new CacheKey($eagerLoad, /** @scrutinizer ignore-type */ $model, $query))
Loading history...
76
            ->make($columns, $idColumn, $keyDifferentiator);
77
    }
78
79
    protected function makeCacheTags() : array
80
    {
81
        $eagerLoad = $this->eagerLoad ?? [];
82
        $model = $this->model instanceof Model
83
            ? $this->model
84
            : $this;
85
        $query = $this->query instanceof Builder
86
            ? $this->query
87
            : app('db')->query();
88
        $tags = (new CacheTags($eagerLoad, $model, $query))
1 ignored issue
show
Bug introduced by
It seems like $model can also be of type GeneaLabs\LaravelModelCaching\Traits\Caching; however, parameter $model of GeneaLabs\LaravelModelCa...acheTags::__construct() does only seem to accept Illuminate\Database\Eloquent\Model, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

88
        $tags = (new CacheTags($eagerLoad, /** @scrutinizer ignore-type */ $model, $query))
Loading history...
89
            ->make();
90
91
        return $tags;
92
    }
93
94
    public function getModelCacheCooldown(Model $instance) : array
95
    {
96
        $cachePrefix = $this->getCachePrefix();
97
        $modelClassName = get_class($instance);
98
        [$cacheCooldown, $invalidatedAt, $savedAt] = $this
99
            ->getCacheCooldownDetails($instance, $cachePrefix, $modelClassName);
100
101
        if (! $cacheCooldown || $cacheCooldown === 0) {
2 ignored issues
show
introduced by
The condition $cacheCooldown === 0 is always false.
Loading history...
introduced by
$cacheCooldown is of type Illuminate\Database\Eloquent\Collection, thus it always evaluated to true.
Loading history...
102
            return [null, null, null];
103
        }
104
105
        return [$cacheCooldown, $invalidatedAt, $savedAt];
106
    }
107
108
    protected function getCacheCooldownDetails(
109
        Model $instance,
110
        string $cachePrefix,
111
        string $modelClassName
112
    ) : array {
113
        return [
114
            $instance
115
                ->cache()
116
                ->get("{$cachePrefix}:{$modelClassName}-cooldown:seconds"),
1 ignored issue
show
Bug introduced by
$cachePrefix.':'.$modelC...ame.'-cooldown:seconds' of type string is incompatible with the type array expected by parameter $columns of Illuminate\Database\Eloquent\Builder::get(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

116
                ->get(/** @scrutinizer ignore-type */ "{$cachePrefix}:{$modelClassName}-cooldown:seconds"),
Loading history...
117
            $instance
118
                ->cache()
119
                ->get("{$cachePrefix}:{$modelClassName}-cooldown:invalidated-at"),
120
            $instance
121
                ->cache()
122
                ->get("{$cachePrefix}:{$modelClassName}-cooldown:saved-at"),
123
        ];
124
    }
125
126
    protected function checkCooldownAndRemoveIfExpired(Model $instance)
127
    {
128
        [$cacheCooldown, $invalidatedAt] = $this->getModelCacheCooldown($instance);
129
130
        if (! $cacheCooldown
0 ignored issues
show
introduced by
$cacheCooldown is of type Illuminate\Database\Eloquent\Collection, thus it always evaluated to true.
Loading history...
131
            || (new Carbon)->now()->diffInSeconds($invalidatedAt) < $cacheCooldown
132
        ) {
133
            return;
134
        }
135
136
        $cachePrefix = $this->getCachePrefix();
137
        $modelClassName = get_class($instance);
138
139
        $instance
140
            ->cache()
141
            ->forget("{$cachePrefix}:{$modelClassName}-cooldown:invalidated-at");
142
        $instance
143
            ->cache()
144
            ->forget("{$cachePrefix}:{$modelClassName}-cooldown:invalidated-at");
145
        $instance
146
            ->cache()
147
            ->forget("{$cachePrefix}:{$modelClassName}-cooldown:saved-at");
148
        $instance->flushCache();
149
    }
150
151
    protected function checkCooldownAndFlushAfterPersisting(Model $instance)
152
    {
153
        [$cacheCooldown, $invalidatedAt] = $instance->getModelCacheCooldown($instance);
154
155
        if (! $cacheCooldown) {
156
            $instance->flushCache();
157
158
            return;
159
        }
160
161
        $this->setCacheCooldownSavedAtTimestamp($instance);
162
163
        if ((new Carbon)->now()->diffInSeconds($invalidatedAt) >= $cacheCooldown) {
164
            $instance->flushCache();
165
        }
166
    }
167
168
    public function isCachable() : bool
169
    {
170
        return $this->isCachable
171
            && ! config('laravel-model-caching.disabled');
172
    }
173
174
    protected function setCacheCooldownSavedAtTimestamp(Model $instance)
175
    {
176
        $cachePrefix = $this->getCachePrefix();
177
        $modelClassName = get_class($instance);
178
        $cacheKey = "{$cachePrefix}:{$modelClassName}-cooldown:saved-at";
179
180
        $instance->cache()
181
            ->rememberForever($cacheKey, function () {
182
                return (new Carbon)->now();
183
            });
184
    }
185
}
186