Passed
Push — master ( 8b9923...b95d07 )
by Mostafa
03:05 queued 36s
created

InteractsWithCache::entityIsCallable()   B

Complexity

Conditions 9
Paths 31

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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