Completed
Push — 2.x ( 80f8d5...55e9fe )
by Akihito
12s
created

Bind::getClass()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Di;
6
7
use Ray\Di\Exception\NotFound;
8
9
final class Bind
10
{
11
    /**
12
     * @var Container
13
     */
14
    private $container;
15
16
    /**
17
     * @var string
18
     */
19
    private $interface;
20
21
    /**
22
     * @var string
23
     */
24
    private $name = Name::ANY;
25
26
    /**
27
     * @var DependencyInterface
28
     */
29
    private $bound;
30
31
    /**
32
     * @var BindValidator
33
     */
34
    private $validate;
35
36
    /**
37
     * @var null|Untarget
38
     */
39
    private $untarget;
40
41
    /**
42
     * @param Container $container dependency container
43 93
     * @param string    $interface interface or concrete class name
44
     */
45 93
    public function __construct(Container $container, string $interface)
46 93
    {
47 93
        $this->container = $container;
48 93
        $this->interface = $interface;
49 93
        $this->validate = new BindValidator;
50 50
        $bindUntarget = class_exists($interface) && ! (new \ReflectionClass($interface))->isAbstract() && ! $this->isRegistered($interface);
51
        if ($bindUntarget) {
52 50
            $this->untarget = new Untarget($interface);
53
54 92
            return;
55 91
        }
56
        $this->validate->constructor($interface);
57 87
    }
58
59 87
    public function __destruct()
60 43
    {
61 43
        if ($this->untarget) {
62
            ($this->untarget)($this->container, $this);
63 87
            $this->untarget = null;
64
        }
65 87
    }
66
67 87
    public function __toString()
68
    {
69
        return $this->interface . '-' . $this->name;
70
    }
71
72
    /**
73 31
     * Set dependency name
74
     */
75 31
    public function annotatedWith(string $name) : self
76
    {
77 31
        $this->name = $name;
78
79
        return $this;
80
    }
81
82
    /**
83 61
     * Bind to class
84
     */
85 61
    public function to(string $class) : self
86 61
    {
87 59
        $this->untarget = null;
88 59
        $refClass = $this->validate->to($this->interface, $class);
89
        $this->bound = (new DependencyFactory)->newAnnotatedDependency($refClass);
90 59
        $this->container->add($this);
91
92
        return $this;
93
    }
94
95
    /**
96
     * Bind to constructor
97
     *
98
     * @param string          $class           class name
99
     * @param string | array  $name            "varName=bindName,..." or [[$varName => $bindName],[$varName => $bindName]...]
100
     * @param InjectionPoints $injectionPoints injection points
101 4
     * @param string          $postConstruct   method name of initialization after all dependencies are injected*
102
     */
103 4
    public function toConstructor(string $class, $name, InjectionPoints $injectionPoints = null, string $postConstruct = null) : self
104 1
    {
105
        if (\is_array($name)) {
106 4
            $name = $this->getStringName($name);
107 4
        }
108 4
        $this->untarget = null;
109 4
        $postConstructRef = $postConstruct ? (new NewReflectionMethod)($class, $postConstruct) : null;
110
        $this->bound = (new DependencyFactory)->newToConstructor((new NewReflectionClass)($class), $name, $injectionPoints, $postConstructRef);
111 4
        $this->container->add($this);
112
113
        return $this;
114
    }
115
116
    /**
117 50
     * Bind to provider
118
     */
119 50
    public function toProvider(string $provider, string $context = '') : self
120 50
    {
121 48
        $this->untarget = null;
122 48
        $refClass = $this->validate->toProvider($provider);
123
        $this->bound = (new DependencyFactory)->newProvider($refClass, $context);
124 48
        $this->container->add($this);
125
126
        return $this;
127
    }
128
129
    /**
130 80
     * Bind to instance
131
     */
132 80
    public function toInstance($instance) : self
133 80
    {
134 80
        $this->untarget = null;
135
        $this->bound = new Instance($instance);
136 80
        $this->container->add($this);
137
138
        return $this;
139
    }
140
141
    /**
142 46
     * Set scope
143
     */
144 46
    public function in(string $scope) : self
145 45
    {
146
        if ($this->bound instanceof Dependency || $this->bound instanceof DependencyProvider) {
147 46
            $this->bound->setScope($scope);
148 41
        }
149
        if ($this->untarget) {
150
            $this->untarget->setScope($scope);
151 46
        }
152
153
        return $this;
154 86
    }
155
156 86
    public function getBound() : DependencyInterface
157
    {
158
        return $this->bound;
159 43
    }
160
161 43
    public function setBound(DependencyInterface $bound)
162 43
    {
163
        $this->bound = $bound;
164 50
    }
165
166 50
    /**
167
     * @throws \ReflectionException
168
     */
169
    private function getClass(string $class) : \ReflectionClass
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
170
    {
171
        if (! class_exists($class)) {
172
            throw new NotFound($class);
173
        }
174
175
        return new \ReflectionClass($class);
176
    }
177 1
178 1
    private function isRegistered(string $interface) : bool
179
    {
180 1
        return isset($this->container->getContainer()[$interface . '-' . Name::ANY]);
181 1
    }
182
183 1
    /**
184
     * Return string
185
     *
186
     * input: [['varA' => 'nameA'], ['varB' => 'nameB']]
187
     * output: "varA=nameA,varB=nameB"
188
     */
189
    private function getStringName(array $name) : string
190
    {
191
        $names = array_reduce(array_keys($name), function (array $carry, $key) use ($name) : array {
192
            $carry[] .= $key . '=' . $name[(string) $key];
193
194
            return $carry;
195
        }, []);
196
197
        return implode(',', $names);
198
    }
199
}
200