Completed
Pull Request — 2.x (#194)
by Akihito
01:27
created

Container::addPointcut()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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