CacheableDecorator::methodIsCacheable()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Suitmedia\Cacheable;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Support\Collection;
7
use Suitmedia\Cacheable\Contracts\CacheableRepository;
8
use Suitmedia\Cacheable\Exceptions\MethodNotFoundException;
9
10
class CacheableDecorator
11
{
12
    /**
13
     * Cacheable Repository.
14
     *
15
     * @var \Suitmedia\Cacheable\Contracts\CacheableRepository
16
     */
17
    private $repository;
18
19
    /**
20
     * Cacheable service object.
21
     *
22
     * @var \Suitmedia\Cacheable\CacheableService
23
     */
24
    private $service;
25
26
    /**
27
     * Class constructor.
28
     *
29
     * @param \Suitmedia\Cacheable\CacheableService              $service
30
     * @param \Suitmedia\Cacheable\Contracts\CacheableRepository $repository
31
     */
32
    public function __construct(CacheableService $service, CacheableRepository $repository)
33
    {
34
        $this->service = $service;
35
        $this->repository = $repository;
36
    }
37
38
    /**
39
     * Generate custom cache tags.
40
     *
41
     * @param \Illuminate\Support\Collection      $tags
42
     * @param \Illuminate\Database\Eloquent\Model $object
43
     *
44
     * @return void
45
     */
46
    private function generateCustomTags(Collection $tags, Model $object): void
47
    {
48
        $class = class_basename(get_class($object));
49
        $baseTags = (array) $this->repository->cacheTags();
50
51
        $tags->push($class.':'.$object->getKey());
52
53
        foreach ($baseTags as $tag) {
54
            $tags->push($tag.':'.$class.':'.$object->getKey());
55
        }
56
    }
57
58
    /**
59
     * Generate cache tags.
60
     *
61
     * @param mixed $args
62
     *
63
     * @return array
64
     */
65
    private function generateTags($args): array
66
    {
67
        $args = collect($args);
68
        $tags = collect($this->repository->cacheTags());
69
70
        $args->each(function ($object) use ($tags) {
71
            if ($this->isCustomTagInstance($object)) {
72
                $this->generateCustomTags($tags, $object);
73
            }
74
        });
75
76
        return $tags->sort()->unique()->all();
77
    }
78
79
    /**
80
     * Get the correct return value if the repository returns itself.
81
     *
82
     * @param mixed $value
83
     *
84
     * @return mixed
85
     */
86
    private function getReturnValue($value)
87
    {
88
        return ($value === $this->repository) ? $this : $value;
89
    }
90
91
    /**
92
     * Determine if the given object is a custom tag instance.
93
     *
94
     * @param mixed $object
95
     *
96
     * @return bool
97
     */
98
    private function isCustomTagInstance($object): bool
99
    {
100
        $customTagInstances = (array) config('cacheable.customTags');
101
102
        return is_object($object) && ($object instanceof Model) && in_array(get_class($object), $customTagInstances, true);
103
    }
104
105
    /**
106
     * Finds whether the method is cacheable.
107
     *
108
     * @param string $method
109
     *
110
     * @return bool
111
     */
112
    private function methodIsCacheable($method): bool
113
    {
114
        return !in_array($method, $this->repository->cacheExcept(), true);
115
    }
116
117
    /**
118
     * Dynamically call methods from repository.
119
     *
120
     * @param string $method
121
     * @param mixed  $args
122
     *
123
     * @return mixed
124
     */
125
    public function __call($method, $args)
126
    {
127
        $repository = $this->repository;
128
129
        if (!method_exists($repository, $method)) {
130
            throw (new MethodNotFoundException())->setRepositoryMethod(
131
                get_class($repository),
132
                $method
133
            );
134
        }
135
136
        if (!$this->methodIsCacheable($method)) {
137
            return $this->getReturnValue(call_user_func_array([$repository, $method], $args));
138
        }
139
140
        return $this->getReturnValue($this->service->retrieve(
141
            $this->generateTags($args),
142
            $repository->cacheKey($method, $args),
143
            $repository->cacheDuration(),
144
            static function () use ($repository, $method, $args) {
145
                $result = call_user_func_array([$repository, $method], $args);
146
147
                return $result ?? false;
148
            }
149
        ));
150
    }
151
}
152