Passed
Push — master ( 4c3e72...46eb59 )
by Arthur
10:39
created

ModelCache::eagerLoadRelations()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: arthur
5
 * Date: 11.10.18
6
 * Time: 14:11.
7
 */
8
9
namespace Foundation\Cache;
10
11
use Cache;
12
use Foundation\Exceptions\Exception;
13
use Illuminate\Support\Facades\Redis;
14
15
class ModelCache
16
{
17
    protected $model;
18
19
    protected $cacheTime;
20
21
    /* Unique secondary indexes */
22
    protected $secondaryIndexes;
23
24
    /**
25
     * ModelCache constructor.
26
     */
27 1
    public function __construct(string $model, array $indexes = [], $cacheTime = null)
28
    {
29 1
        $this->model = $model;
30 1
        $this->secondaryIndexes = $indexes;
31 1
        $this->cacheTime = $cacheTime;
32 1
    }
33
34
    /**
35
     * @param $id
36
     * @param string $modelClass
37
     *
38
     * @return \Eloquent
39
     */
40 21
    public function find($id, $eagerLoad = true)
41
    {
42 21
        $model = Cache::get(self::getCacheName($id));
0 ignored issues
show
Bug Best Practice introduced by
The method Foundation\Cache\ModelCache::getCacheName() is not static, but was called statically. ( Ignorable by Annotation )

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

42
        $model = Cache::get(self::/** @scrutinizer ignore-call */ getCacheName($id));
Loading history...
43
44 21
        if ($eagerLoad) {
45 20
            return $this->eagerLoadRelations($model);
46
        }
47
48 1
        return $model;
49
    }
50
51 19
    public function findBy(string $index, $key, $eagerLoad = true)
52
    {
53 19
        if (!in_array($index, $this->secondaryIndexes)) {
54
            throw new Exception('provided index does not exist as secondary index on the cache model');
55
        }
56 19
        $modelId = $this->findSecondaryIndex($index, $key);
57
58 19
        if ($modelId === null) {
59 18
            $model = ($this->model)::where($index, $key)->first();
60 18
            if ($model !== null)
61
                $this->store($model);
62 18
            return $model;
63
        }
64
65 18
        return $this->find($modelId, $eagerLoad);
66
    }
67
68 20
    protected function eagerLoadRelations($model)
69
    {
70 20
        if ($model !== null) {
71 19
            return $model::eagerLoadRelations([$model])[0];
72
        }
73 3
    }
74
75 19
    protected function findSecondaryIndex(string $index, $key)
76
    {
77 19
        return Cache::get($this->getCacheName($key, $index));
78
    }
79
80
    /**
81
     * @param string
82
     */
83 26
    public function getCacheName($id, string $index = 'id')
84
    {
85 26
        return config('model.cache_prefix') . ':' . strtolower(get_short_class_name($this->model)) . ':' . $index . ':' . $id;
86
    }
87
88
    /**
89
     * @return \Illuminate\Config\Repository|mixed
90
     */
91 26
    public function getCacheTime()
92
    {
93 26
        return $this->cacheTime ?? config('model.cache_time');
94
    }
95
96
    /**
97
     * @param \Eloquent $model
98
     */
99 26
    public function store($model)
100
    {
101 26
        Cache::put($this->getCacheName($model->getKey()), $model->newFromBuilder($model->getAttributes()), $this->getCacheTime());
102 26
        $this->storeSecondaryIndexReferences($model);
103 26
    }
104
105
    /**
106
     * @param string $index
107
     * @param \Eloquent $model
108
     */
109 26
    protected function storeSecondaryIndexReferences($model)
110
    {
111 26
        foreach ($this->secondaryIndexes as $index) {
112 26
            $indexValue = $model->$index;
113 26
            if ($indexValue !== null) {
114 26
                Cache::put($this->getCacheName($indexValue, $index), $model->getKey(), $this->getCacheTime());
115
            }
116
        }
117 26
    }
118
119
    /**
120
     * @param $id
121
     * @param string $modelClass
122
     *
123
     * @return bool
124
     */
125 1
    public function remove($id)
126
    {
127 1
        return Cache::forget($this->getCacheName($id));
128
    }
129
130 46
    public static function clearAll()
131
    {
132 46
        $pattern = config('model.cache_prefix');
133 46
        self::deleteWithPrefix($pattern);
134 46
    }
135
136
    /**
137
     * @param $prefix
138
     *
139
     * @throws Exception
140
     */
141 46
    private static function deleteWithPrefix($prefix)
142
    {
143 46
        $redis = self::getCacheConnection();
144 46
        $keyPattern = Cache::getPrefix() . $prefix . '*';
0 ignored issues
show
Bug introduced by
The call to Illuminate\Cache\CacheManager::getPrefix() has too few arguments starting with config. ( Ignorable by Annotation )

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

144
        $keyPattern = Cache::/** @scrutinizer ignore-call */ getPrefix() . $prefix . '*';

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
145 46
        $keys = $redis->keys($keyPattern);
146 46
        $redis->delete($keys);
147 46
    }
148
149
    /**
150
     * @throws Exception
151
     *
152
     * @return \Illuminate\Redis\Connections\Connection
153
     */
154 46
    private static function getCacheConnection()
155
    {
156 46
        if (config('cache.default') === 'redis') {
157 46
            return Redis::connection('cache');
158
        }
159
160
        throw new Exception('This action is only possible with redis as cache driver');
161
    }
162
163
    /**
164
     * @param $modelClass
165
     *
166
     * @throws Exception
167
     */
168 1
    public function clearModelCache()
169
    {
170 1
        $pattern = config('model.cache_prefix') . ':' . strtolower(get_short_class_name($this->model));
171 1
        self::deleteWithPrefix($pattern);
172 1
    }
173
174 6
    public function enabled(): bool
175
    {
176 6
        return (bool)config('model.caching');
177
    }
178
}
179