Dependency   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 21
eloc 46
c 2
b 0
f 0
dl 0
loc 138
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A inject() 0 17 4
A injectWithArgs() 0 17 4
A __toString() 0 5 1
A __sleep() 0 3 1
A setScope() 0 4 2
A register() 0 3 1
A __construct() 0 4 1
A weaveAspects() 0 22 5
A isSingleton() 0 3 1
A accept() 0 6 1
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 ReflectionClass;
12
use ReflectionMethod;
13
14
use function assert;
15
use function method_exists;
16
use function sprintf;
17
18
/**
19
 * @psalm-import-type MethodArguments from Types
20
 * @psalm-import-type PointcutList from Types
21
 */
22
final class Dependency implements DependencyInterface, AcceptInterface
23
{
24
    /** @var NewInstance */
25
    private $newInstance;
26
27
    /** @var ?string */
28
    private $postConstruct;
29
    private bool $isSingleton = false;
30
31
    /** @var ?mixed */
32
    private $instance;
33
34
    public function __construct(NewInstance $newInstance, ?ReflectionMethod $postConstruct = null)
35
    {
36
        $this->newInstance = $newInstance;
37
        $this->postConstruct = $postConstruct->name ?? null;
38
    }
39
40
    /**
41
     * @return array<string>
42
     */
43
    public function __sleep()
44
    {
45
        return ['newInstance', 'postConstruct', 'isSingleton'];
46
    }
47
48
    public function __toString(): string
49
    {
50
        return sprintf(
51
            '(dependency) %s',
52
            (string) $this->newInstance
53
        );
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59
    public function register(array &$container, Bind $bind): void
60
    {
61
        $container[(string) $bind] = $bind->getBound();
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     */
67
    public function inject(Container $container)
68
    {
69
        // singleton ?
70
        if ($this->isSingleton === true && $this->instance !== null) {
71
            return $this->instance;
72
        }
73
74
        // create dependency injected instance
75
        $this->instance = ($this->newInstance)($container);
76
77
        // @PostConstruct
78
        if ($this->postConstruct !== null) {
79
            assert(method_exists($this->instance, $this->postConstruct));
80
            $this->instance->{$this->postConstruct}();
81
        }
82
83
        return $this->instance;
84
    }
85
86
    /**
87
     * @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...
88
     *
89
     * @return mixed
90
     */
91
    public function injectWithArgs(Container $container, array $params)
92
    {
93
        // singleton ?
94
        if ($this->isSingleton === true && $this->instance !== null) {
95
            return $this->instance;
96
        }
97
98
        // create dependency injected instance
99
        $this->instance = $this->newInstance->newInstanceArgs($container, $params);
100
101
        // @PostConstruct
102
        if ($this->postConstruct !== null) {
103
            assert(method_exists($this->instance, $this->postConstruct));
104
            $this->instance->{$this->postConstruct}();
105
        }
106
107
        return $this->instance;
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113
    public function setScope($scope): void
114
    {
115
        if ($scope === Scope::SINGLETON) {
116
            $this->isSingleton = true;
117
        }
118
    }
119
120
    /**
121
     * @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...
122
     */
123
    public function weaveAspects(CompilerInterface $compiler, array $pointcuts): void
124
    {
125
        $class = (string) $this->newInstance;
126
        if ((new ReflectionClass($class))->isFinal()) {
127
            return;
128
        }
129
130
        $isInterceptor = (new ReflectionClass($class))->implementsInterface(MethodInterceptor::class);
131
        $isWeaved = (new ReflectionClass($class))->implementsInterface(WeavedInterface::class);
132
        if ($isInterceptor || $isWeaved) {
133
            return;
134
        }
135
136
        $bind = new AopBind();
137
        $className = (string) $this->newInstance;
138
        $bind->bind($className, $pointcuts);
139
        if (! $bind->getBindings()) {
140
            return;
141
        }
142
143
        $class = $compiler->compile($className, $bind);
144
        $this->newInstance->weaveAspects($class, $bind);
145
    }
146
147
    /** @inheritDoc */
148
    public function accept(VisitorInterface $visitor)
149
    {
150
        return $visitor->visitDependency(
151
            $this->newInstance,
152
            $this->postConstruct,
153
            $this->isSingleton
154
        );
155
    }
156
157
    public function isSingleton(): bool
158
    {
159
        return $this->isSingleton;
160
    }
161
}
162