Passed
Pull Request — master (#12)
by Mostafa
11:54
created

InteractsWithCache::getEntityFullName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Mostafaznv\LaraCache\Traits;
4
5
use Illuminate\Support\Facades\Cache;
6
use Illuminate\Support\Str;
7
use Mostafaznv\LaraCache\CacheEntity;
8
use Mostafaznv\LaraCache\DTOs\CacheData;
9
use Mostafaznv\LaraCache\DTOs\CacheEvent;
10
use Mostafaznv\LaraCache\DTOs\CacheStatus;
11
use Mostafaznv\LaraCache\Exceptions\CacheEntityDoesNotExist;
12
use Mostafaznv\LaraCache\Jobs\UpdateLaraCacheModelsList;
13
14
trait InteractsWithCache
15
{
16
    private string $prefix;
17
    private mixed $model;
18
    private string $laracacheListKey;
19
20
    public function __construct(string $model)
21
    {
22
        $this->prefix = Str::kebab(class_basename($model));
23
        $this->model = $model;
24
        $this->laracacheListKey = config('laracache.laracache-list');
25
    }
26
27
28
    private function getEntityFullName(CacheEntity $entity): string
29
    {
30
        return $this->prefix . '.' . $entity->name;
31
    }
32
33
    private function findCacheEntity(string $name, ?CacheEntity $entity = null): CacheEntity
34
    {
35
        if ($entity) {
36
            return $entity;
37
        }
38
39
        foreach ($this->model::cacheEntities() as $cacheEntity) {
40
            if ($cacheEntity->name === $name) {
41
                return $cacheEntity;
42
            }
43
        }
44
45
        throw CacheEntityDoesNotExist::make($name, $this->model);
46
    }
47
48
    private function entityIsCallable(CacheEntity $entity, ?CacheEvent $event = null): bool
49
    {
50
        return is_null($event)
51
            or ($event->equals(CacheEvent::CREATED()) and $entity->refreshAfterCreate)
52
            or ($event->equals(CacheEvent::UPDATED()) and $entity->refreshAfterUpdate)
53
            or ($event->equals(CacheEvent::DELETED()) and $entity->refreshAfterDelete)
54
            or ($event->equals(CacheEvent::RESTORED()) and $entity->refreshAfterRestore);
55
    }
56
57
    private function callCacheClosure(CacheEntity $entity, int $ttl, bool $delete = false): CacheData
58
    {
59
        if ($delete) {
60
            return CacheData::make(CacheStatus::DELETED(), $ttl, $entity->default);
61
        }
62
63
        $value = $entity->cacheClosure ? call_user_func($entity->cacheClosure) : null;
64
65
        return CacheData::make(
66
            status: CacheStatus::CREATED(),
67
            ttl: $ttl,
68
            value: $value ?: $entity->default
69
        );
70
    }
71
72
    private function updateCacheEntitiesList(CacheEntity $entity): void
73
    {
74
        $name = $this->getEntityFullName($entity);
75
        $list = Cache::store($entity->driver)->get($this->laracacheListKey);
76
77
        if (is_array($list)) {
78
            if (isset($list[$this->model]) and is_array($list[$this->model])) {
79
                if (!in_array($name, $list[$this->model])) {
80
                    $list[$this->model][] = $name;
81
                }
82
            }
83
            else {
84
                $list[$this->model] = [$name];
85
            }
86
        }
87
        else {
88
            $list = [
89
                $this->model => [$name]
90
            ];
91
        }
92
93
        Cache::store($entity->driver)->forever($this->laracacheListKey, $list);
94
    }
95
96
    private function putCacheIntoCacheStorage(CacheData $cache, string $driver, string $name, int $ttl): bool
97
    {
98
        if (is_null($cache->expiration)) {
99
            return Cache::store($driver)->forever($name, $cache);
100
        }
101
102
        return Cache::store($driver)->put($name, $cache, $ttl);
103
    }
104
105
    private function initCache(CacheEntity $entity, int $ttl): void
106
    {
107
        $name = $this->getEntityFullName($entity);
108
        $cache = CacheData::fromCache($entity, $this->prefix, $ttl);
109
110
        if ($cache->status->equals(CacheStatus::NOT_CREATED())) {
111
            $cache->value = $entity->default;
112
        }
113
114
        $cache->status = CacheStatus::CREATING();
115
116
        $this->putCacheIntoCacheStorage($cache, $entity->driver, $name, $ttl);
117
    }
118
119
    private function storeCache(CacheData $cache, CacheEntity $entity, int $ttl): void
120
    {
121
        $name = $this->getEntityFullName($entity);
122
123
        $this->putCacheIntoCacheStorage($cache, $entity->driver, $name, $ttl);
124
        $this->updateCacheEntitiesList($entity);
125
    }
126
127
    private function updateLaraCacheModelsList(): void
128
    {
129
        UpdateLaraCacheModelsList::dispatch($this->model);
130
    }
131
132
    private function updateCacheEntity(string $name, ?CacheEvent $event = null, CacheEntity $entity = null): CacheData
133
    {
134
        $entity = $this->findCacheEntity($name, $entity);
135
136
        if ($this->entityIsCallable($entity, $event)) {
137
            $ttl = $entity->getTtl();
138
139
            $this->initCache($entity, $ttl);
140
            $cache = $this->callCacheClosure($entity, $ttl);
141
            $this->storeCache($cache, $entity, $ttl);
142
143
            return $cache;
144
        }
145
146
        return CacheData::fromCache($entity, $this->prefix);
147
    }
148
149
    private function deleteCacheEntity(string $name, bool $deleteForever = false, CacheEntity $entity = null): CacheData
150
    {
151
        $entity = $this->findCacheEntity($name, $entity);
152
        $ttl = !$deleteForever ? $entity->getTtl() : 0;
153
        $cache = $this->callCacheClosure($entity, $ttl, true);
154
        $this->storeCache($cache, $entity, $ttl);
155
156
        return $cache;
157
    }
158
159
    private function retrieve(string $name): CacheData
160
    {
161
        $entity = $this->findCacheEntity($name);
162
        $cache = CacheData::fromCache($entity, $this->prefix);
163
164
        if ($cache->status->equals(CacheStatus::NOT_CREATED())) {
165
            return $this->updateCacheEntity($name, null, $entity);
166
        }
167
168
        return $cache;
169
    }
170
}
171