Completed
Branch issue-01 (5952bd)
by Richan
11:33
created

CacheableDecorator::__call()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0
cc 3
eloc 14
nc 3
nop 2
1
<?php
2
3
namespace Suitmedia\Cacheable;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Suitmedia\Cacheable\Contracts\CacheableRepository;
7
use Suitmedia\Cacheable\Exceptions\MethodNotFoundException;
8
9
class CacheableDecorator
10
{
11
    /**
12
     * Cacheable Repository.
13
     *
14
     * @var \Suitmedia\Cacheable\Contracts\CacheableRepository
15
     */
16
    private $repository;
17
18
    /**
19
     * Cacheable service object.
20
     *
21
     * @var \Suitmedia\Cacheable\CacheableService
22
     */
23
    private $service;
24
25
    /**
26
     * Class constructor.
27
     *
28
     * @param \Suitmedia\Cacheable\CacheableService              $service
29
     * @param \Suitmedia\Cacheable\Contracts\CacheableRepository $repository
30
     */
31
    public function __construct(CacheableService $service, CacheableRepository $repository)
32
    {
33
        $this->service = $service;
34
        $this->repository = $repository;
35
    }
36
37
    /**
38
     * Generate custom cache tags.
39
     *
40
     * @param array $tags
41
     * @param Model $object
42
     *
43
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,boolean>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
44
     */
45
    private function generateCustomTags($tags, Model $object)
46
    {
47
        $class = last(explode('\\', get_class($object)));
48
        $customTags = [$class.':'.$object->getKey() => true];
49
50
        foreach ($tags as $tag) {
51
            $key = $tag.':'.$class.':'.$object->getKey();
52
            $customTags[$key] = true;
53
        }
54
55
        return $customTags;
56
    }
57
58
    /**
59
     * Generate cache tags.
60
     *
61
     * @param mixed $args
62
     *
63
     * @return array
64
     */
65
    private function generateTags($args)
66
    {
67
        $args = (array) $args;
68
        $tags = (array) $this->repository->cacheTags();
69
        $customTagInstances = (array) $this->service->getConfiguration('customTags');
70
        $customTags = [];
71
72
        foreach ($args as $arg) {
73
            if (is_object($arg) && in_array(get_class($arg), $customTagInstances)) {
74
                $customTags = array_merge($customTags, $this->generateCustomTags($tags, $arg));
75
            }
76
        }
77
78
        return array_merge($tags, array_keys($customTags));
79
    }
80
81
    /**
82
     * Finds whether the metod is cacheable.
83
     *
84
     * @param string $method
85
     *
86
     * @return bool
87
     */
88
    private function methodIsCacheable($method)
89
    {
90
        return !in_array($method, $this->repository->cacheExcept());
91
    }
92
93
    /**
94
     * Dynamically call methods from repository.
95
     *
96
     * @param string $method
97
     * @param mixed  $args
98
     *
99
     * @return mixed
100
     */
101
    public function __call($method, $args)
102
    {
103
        $repository = $this->repository;
104
105
        if (!method_exists($repository, $method)) {
106
            throw (new MethodNotFoundException())->setRepositoryMethod(
107
                get_class($repository),
108
                $method
109
            );
110
        }
111
112
        if (!$this->methodIsCacheable($method)) {
113
            return call_user_func_array([$repository, $method], $args);
114
        }
115
116
        return $this->service->retrieve(
117
            $this->generateTags($args),
118
            $repository->cacheKey($method, $args),
119
            $repository->cacheDuration(),
120
            function () use ($repository, $method, $args) {
121
                return call_user_func_array([$repository, $method], $args);
122
            }
123
        );
124
    }
125
}
126