Completed
Push — 2.x ( 39dc4e...b7fd10 )
by Akihito
01:28
created

Container   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 159
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 21
lcom 2
cbo 5
dl 0
loc 159
ccs 46
cts 46
cp 1
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __sleep() 0 4 1
A addPointcut() 0 4 1
A add() 0 5 1
A getInstance() 0 4 1
A getInstanceWithArgs() 0 13 3
A getDependency() 0 9 2
A move() 0 10 2
A unbound() 0 9 3
A getContainer() 0 4 1
A getPointcuts() 0 4 1
A merge() 0 5 1
A weaveAspects() 0 9 3
A weaveAspect() 0 6 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Di;
6
7
use Ray\Aop\Compiler;
8
use Ray\Aop\CompilerInterface;
9
use Ray\Aop\Pointcut;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Ray\Di\Pointcut.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
10
use Ray\Di\Exception\Unbound;
11
use Ray\Di\Exception\Untargeted;
12
13
final class Container
14
{
15
    /**
16
     * @var DependencyInterface[]
17
     */
18
    private $container = [];
19
20
    /**
21
     * @var Pointcut[]
22
     */
23
    private $pointcuts = [];
24
25
    public function __sleep()
26
    {
27
        return ['container', 'pointcuts'];
28
    }
29 4
30
    /**
31 4
     * Add binding to container
32
     */
33
    public function add(Bind $bind)
34
    {
35
        $dependency = $bind->getBound();
36
        $dependency->register($this->container, $bind);
37
    }
38
39 86
    /**
40
     * Add Pointcut to container
41 86
     */
42 86
    public function addPointcut(Pointcut $pointcut)
43 86
    {
44
        $this->pointcuts[] = $pointcut;
45
    }
46
47
    /**
48
     * Return instance by interface + name(interface namespace)
49
     */
50 42
    public function getInstance(string $interface, string $name)
51
    {
52 42
        return $this->getDependency($interface . '-' . $name);
53 42
    }
54
55
    /**
56
     * Return dependency injected instance
57
     *
58
     * @throws Unbound
59
     */
60 53
    public function getInstanceWithArgs(string $interface, array $params)
61
    {
62 53
        $index = $interface . '-';
63
        if (! isset($this->container[$index])) {
64
            throw $this->unbound($index);
65
        }
66
        $dependency = $this->container[$index];
67
        if (! $dependency instanceof Dependency) {
68
            throw new \BadMethodCallException($interface);
69
        }
70
71
        return $dependency->injectWithArgs($this, $params);
72 73
    }
73
74 73
    /**
75 28
     * Return dependency injected instance
76
     *
77 69
     * @throws Unbound
78
     */
79 69
    public function getDependency(string $index)
80
    {
81
        if (! isset($this->container[$index])) {
82
            throw $this->unbound($index);
83
        }
84
        $dependency = $this->container[$index];
85 3
86
        return $dependency->inject($this);
87 3
    }
88 3
89 1
    /**
90
     * Rename existing dependency interface + name
91 2
     */
92 2
    public function move(string $sourceInterface, string $sourceName, string $targetInterface, string $targetName)
93 2
    {
94 2
        $sourceIndex = $sourceInterface . '-' . $sourceName;
95
        if (! isset($this->container[$sourceIndex])) {
96
            throw $this->unbound($sourceIndex);
97
        }
98
        $targetIndex = $targetInterface . '-' . $targetName;
99
        $this->container[$targetIndex] = $this->container[$sourceIndex];
100
        unset($this->container[$sourceIndex]);
101
    }
102
103 29
    /**
104
     * Return Unbound exception
105 29
     *
106 29
     * @param string $index {interface}-{bind name}
107 16
     *
108
     * @return Unbound|Untargeted
109
     */
110 16
    public function unbound(string $index)
111
    {
112
        list($class, $name) = explode('-', $index);
113
        if (class_exists($class) && ! (new \ReflectionClass($class))->isAbstract()) {
114
            return new Untargeted($class);
115
        }
116
117
        return new Unbound("{$class}-{$name}");
118 56
    }
119
120 56
    /**
121
     * Return container
122
     *
123
     * @return DependencyInterface[]
124
     */
125
    public function getContainer() : array
126
    {
127
        return $this->container;
128 45
    }
129
130 45
    /**
131
     * Return pointcuts
132
     *
133
     * @return Pointcut[]
134
     */
135
    public function getPointcuts() : array
136 44
    {
137
        return $this->pointcuts;
138 44
    }
139 44
140 44
    /**
141
     * Merge container
142
     */
143
    public function merge(self $container)
144
    {
145 40
        $this->container += $container->getContainer();
146
        $this->pointcuts = array_merge($this->pointcuts, $container->getPointcuts());
147 40
    }
148 40
149 40
    /**
150
     * Weave aspects to all dependency in container
151 40
     */
152
    public function weaveAspects(CompilerInterface $compiler)
153 40
    {
154
        foreach ($this->container as $dependency) {
155
            if (! $dependency instanceof Dependency) {
156
                continue;
157
            }
158 16
            $dependency->weaveAspects($compiler, $this->pointcuts);
159
        }
160 16
    }
161
162 16
    /**
163
     * Weave aspect to single dependency
164
     */
165
    public function weaveAspect(Compiler $compiler, Dependency $dependency) : self
166
    {
167
        $dependency->weaveAspects($compiler, $this->pointcuts);
168
169
        return $this;
170
    }
171
}
172