Completed
Push — master ( 1bc299...b12741 )
by Kirill
03:33
created

Bootstrap::getClassInheritance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
/**
3
 * This file is part of Properties package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Serafim\Properties;
11
12
use Psr\SimpleCache\CacheInterface;
13
use Serafim\Properties\Attribute\AttributeInterface;
14
15
/**
16
 * Class Bootstrap
17
 */
18
final class Bootstrap
19
{
20
    /**
21
     * @var Bootstrap
22
     */
23
    private static $instance;
24
25
    /**
26
     * @var CacheInterface
27
     */
28
    private $cache;
29
30
    /**
31
     * @var Builder
32
     */
33
    private $builder;
34
35
    /**
36
     * @var array|string[]
37
     */
38
    private $inheritance = [];
39
40
    /**
41
     * @return Bootstrap
42
     */
43
    public static function getInstance(): self
44
    {
45
        return self::$instance ?? self::setInstance(new self());
46
    }
47
48
    /**
49
     * @param self|Bootstrap $instance
50
     * @return Bootstrap
51
     */
52
    public static function setInstance(?self $instance): self
53
    {
54
        return self::$instance = $instance;
55
    }
56
57
    /**
58
     * Bootstrap constructor.
59
     */
60
    private function __construct()
61
    {
62
        $this->cache = new ArrayCache();
63
        $this->builder = new Builder();
64
    }
65
66
    /**
67
     * @return array
68
     */
69
    public function getInvocationPosition(): array
70
    {
71
        $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS)[2] ?? [];
72
73
        return [$trace['file'] ?? __FILE__, $trace['line'] ?? __LINE__];
74
    }
75
76
    /**
77
     * @param null|CacheInterface $cache
78
     */
79
    public function setCacheDriver(?CacheInterface $cache): void
80
    {
81
        $this->cache = $cache ?? new ArrayCache();
82
    }
83
84
    /**
85
     * @param string $class
86
     * @param string $name
87
     * @return AttributeInterface|null
88
     * @throws \Psr\SimpleCache\InvalidArgumentException
89
     */
90
    public function getAttribute(string $class, string $name): ?AttributeInterface
91
    {
92
        foreach ($this->getClassInheritance($class) as $child) {
93
            $result = $this->getAttributeOrBuild($child, $name, function () use ($child) {
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $result is correct as $this->getAttributeOrBui...> $attribute); } }) (which targets Serafim\Properties\Boots...::getAttributeOrBuild()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
94
                foreach ($this->builder->buildClass($child) as $attribute) {
95
                    yield $this->getCacheKey($child, $attribute->getName()) => $attribute;
96
                }
97
            });
98
99
            if ($result) {
100
                return $result;
101
            }
102
        }
103
104
        return null;
105
    }
106
107
    /**
108
     * @param string $class
109
     * @return iterable|string[]
110
     */
111
    private function getClassInheritance(string $class): iterable
112
    {
113
        $inheritance = function() use ($class) {
114
            yield $class;
115
            yield from \array_keys(\class_parents($class));
116
            yield from \array_keys(\class_implements($class));
117
            yield from \array_keys(\class_uses($class));
118
        };
119
120
        if (! isset($this->inheritance[$class])) {
121
            $this->inheritance[$class] = \iterator_to_array($inheritance(), false);
122
        }
123
124
        return $this->inheritance[$class];
125
    }
126
127
    /**
128
     * @param string $class
129
     * @param string $name
130
     * @param \Closure $build
131
     * @return null|AttributeInterface
132
     * @throws \Psr\SimpleCache\InvalidArgumentException
133
     */
134
    private function getAttributeOrBuild(string $class, string $name, \Closure $build): ?AttributeInterface
135
    {
136
        $key = $this->getCacheKey($class, $name);
137
138
        if (! $this->cache->has($key)) {
139
            foreach ($build() as $inner => $attribute) {
140
                $this->cache->set($inner, $attribute);
141
            }
142
        }
143
144
        return $this->cache->get($key);
145
    }
146
147
    /**
148
     * @param string $class
149
     * @param string $name
150
     * @return string
151
     */
152
    private function getCacheKey(string $class, string $name): string
153
    {
154
        return \implode(':', [$class, $name]);
155
    }
156
}
157