Dependency::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
dl 0
loc 4
c 1
b 0
f 0
rs 10
cc 1
nc 1
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Di;
6
7
use Ray\Aop\Bind as AopBind;
8
use Ray\Aop\CompilerInterface;
9
use Ray\Aop\MethodInterceptor;
10
use Ray\Aop\WeavedInterface;
11
use Ray\Di\Bindings\AopInfo;
12
use ReflectionClass;
13
use ReflectionMethod;
14
15
use function assert;
16
use function method_exists;
17
use function sprintf;
18
19
/**
20
 * @psalm-import-type MethodArguments from Types
21
 * @psalm-import-type PointcutList from Types
22
 */
23
final class Dependency implements DependencyInterface, AcceptInterface
24
{
25
    /** @var NewInstance */
26
    private $newInstance;
27
28
    /** @var ?string */
29
    private $postConstruct;
30
31
    /** @var bool */
32
    private $isSingleton = false;
33
34
    /** @var ?mixed */
35
    private $instance;
36
37
    /** @var ?AopInfo */
38
    private $aopInfo;
39
40
    public function __construct(NewInstance $newInstance, ?ReflectionMethod $postConstruct = null)
41
    {
42
        $this->newInstance = $newInstance;
43
        $this->postConstruct = $postConstruct->name ?? null;
44
    }
45
46
    /**
47
     * @return array<string>
48
     */
49
    public function __sleep()
50
    {
51
        return ['newInstance', 'postConstruct', 'isSingleton'];
52
    }
53
54
    public function __toString(): string
55
    {
56
        return sprintf(
57
            '(dependency) %s',
58
            (string) $this->newInstance
59
        );
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65
    public function register(array &$container, Bind $bind): void
66
    {
67
        $container[(string) $bind] = $bind->getBound();
68
    }
69
70
    /**
71
     * {@inheritdoc}
72
     */
73
    public function inject(Container $container)
74
    {
75
        // singleton ?
76
        if ($this->isSingleton === true && $this->instance !== null) {
77
            return $this->instance;
78
        }
79
80
        // create dependency injected instance
81
        $this->instance = ($this->newInstance)($container);
82
83
        // @PostConstruct
84
        if ($this->postConstruct !== null) {
85
            assert(method_exists($this->instance, $this->postConstruct));
86
            $this->instance->{$this->postConstruct}();
87
        }
88
89
        return $this->instance;
90
    }
91
92
    /**
93
     * @param MethodArguments $params
0 ignored issues
show
Bug introduced by
The type Ray\Di\MethodArguments was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
94
     *
95
     * @return mixed
96
     */
97
    public function injectWithArgs(Container $container, array $params)
98
    {
99
        // singleton ?
100
        if ($this->isSingleton === true && $this->instance !== null) {
101
            return $this->instance;
102
        }
103
104
        // create dependency injected instance
105
        $this->instance = $this->newInstance->newInstanceArgs($container, $params);
106
107
        // @PostConstruct
108
        if ($this->postConstruct !== null) {
109
            assert(method_exists($this->instance, $this->postConstruct));
110
            $this->instance->{$this->postConstruct}();
111
        }
112
113
        return $this->instance;
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119
    public function setScope($scope): void
120
    {
121
        if ($scope === Scope::SINGLETON) {
122
            $this->isSingleton = true;
123
        }
124
    }
125
126
    /**
127
     * @param PointcutList $pointcuts
0 ignored issues
show
Bug introduced by
The type Ray\Di\PointcutList was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
128
     */
129
    public function weaveAspects(CompilerInterface $compiler, array $pointcuts): void
130
    {
131
        $class = (string) $this->newInstance;
132
        if ((new ReflectionClass($class))->isFinal()) {
133
            return;
134
        }
135
136
        $isInterceptor = (new ReflectionClass($class))->implementsInterface(MethodInterceptor::class);
137
        $isWeaved = (new ReflectionClass($class))->implementsInterface(WeavedInterface::class);
138
        if ($isInterceptor || $isWeaved) {
139
            return;
140
        }
141
142
        $bind = new AopBind();
143
        $className = (string) $this->newInstance;
144
        $bind->bind($className, $pointcuts);
145
        if (! $bind->getBindings()) {
146
            return;
147
        }
148
149
        // Store AOP info for later retrieval
150
        if ($compiler instanceof SpyCompiler) {
151
            $this->aopInfo = $compiler->getAopInfo($bind);
152
        }
153
154
        $class = $compiler->compile($className, $bind);
155
        $this->newInstance->weaveAspects($class, $bind);
156
    }
157
158
    /**
159
     * Get AOP information if available
160
     */
161
    public function getAopInfo(): ?AopInfo
162
    {
163
        return $this->aopInfo;
164
    }
165
166
    /** @inheritDoc */
167
    public function accept(VisitorInterface $visitor)
168
    {
169
        return $visitor->visitDependency(
170
            $this->newInstance,
171
            $this->postConstruct,
172
            $this->isSingleton
173
        );
174
    }
175
176
    public function isSingleton(): bool
177
    {
178
        return $this->isSingleton;
179
    }
180
}
181