Completed
Push — 2.x ( e1da9c...c98d72 )
by Akihito
02:48
created

Bind::getClass()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
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
     * @param string    $interface interface or concrete class name
44
     */
45
    public function __construct(Container $container, string $interface)
46
    {
47
        $this->container = $container;
48 93
        $this->interface = $interface;
49
        $this->validate = new BindValidator;
50 93
        $bindUntarget = class_exists($interface) && ! (new \ReflectionClass($interface))->isAbstract() && ! $this->isRegistered($interface);
51 93
        if ($bindUntarget) {
52 93
            $this->untarget = new Untarget($interface);
53 93
54 93
            return;
55 50
        }
56
        $this->validate->constructor($interface);
57 50
    }
58
59 92
    public function __destruct()
60 91
    {
61
        if ($this->untarget) {
62 87
            ($this->untarget)($this->container, $this);
63
            $this->untarget = null;
64 87
        }
65 43
    }
66 43
67
    public function __toString()
68 87
    {
69
        return $this->interface . '-' . $this->name;
70 87
    }
71
72 87
    /**
73
     * Set dependency name
74
     */
75
    public function annotatedWith(string $name) : self
76
    {
77
        $this->name = $name;
78 31
79
        return $this;
80 31
    }
81
82 31
    /**
83
     * Bind to class
84
     */
85
    public function to(string $class) : self
86
    {
87
        $this->untarget = null;
88 61
        $refClass = $this->validate->to($this->interface, $class);
89
        $this->bound = (new DependencyFactory)->newAnnotatedDependency($refClass);
90 61
        $this->container->add($this);
91 61
92 59
        return $this;
93 59
    }
94
95 59
    /**
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
     * @param string          $postConstruct   method name of initialization after all dependencies are injected*
102
     */
103
    public function toConstructor(string $class, $name, InjectionPoints $injectionPoints = null, string $postConstruct = null) : self
104
    {
105
        if (\is_array($name)) {
106 4
            $name = $this->getStringName($name);
107
        }
108 4
        $this->untarget = null;
109 1
        $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 4
113 4
        return $this;
114 4
    }
115
116 4
    /**
117
     * Bind to provider
118
     */
119
    public function toProvider(string $provider, string $context = '') : self
120
    {
121
        $this->untarget = null;
122 50
        $refClass = $this->validate->toProvider($provider);
123
        $this->bound = (new DependencyFactory)->newProvider($refClass, $context);
124 50
        $this->container->add($this);
125 50
126 48
        return $this;
127 48
    }
128
129 48
    /**
130
     * Bind to instance
131
     */
132
    public function toInstance($instance) : self
133
    {
134
        $this->untarget = null;
135
        $this->bound = new Instance($instance);
136
        $this->container->add($this);
137 80
138
        return $this;
139 80
    }
140 80
141 80
    /**
142
     * Set scope
143 80
     */
144
    public function in(string $scope) : self
145
    {
146
        if ($this->bound instanceof Dependency || $this->bound instanceof DependencyProvider) {
147
            $this->bound->setScope($scope);
148
        }
149 46
        if ($this->untarget) {
150
            $this->untarget->setScope($scope);
151 46
        }
152 45
153
        return $this;
154 46
    }
155 41
156
    public function getBound() : DependencyInterface
157
    {
158 46
        return $this->bound;
159
    }
160
161 86
    public function setBound(DependencyInterface $bound)
162
    {
163 86
        $this->bound = $bound;
164
    }
165
166 43
    /**
167
     * @throws \ReflectionException
168 43
     */
169 43
    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 50
        if (! class_exists($class)) {
172
            throw new NotFound($class);
173 50
        }
174
175 50
        return new \ReflectionClass($class);
176
    }
177
178
    private function isRegistered(string $interface) : bool
179
    {
180
        return isset($this->container->getContainer()[$interface . '-' . Name::ANY]);
181
    }
182
183
    /**
184
     * Return string
185
     *
186 1
     * input: [['varA' => 'nameA'], ['varB' => 'nameB']]
187 1
     * output: "varA=nameA,varB=nameB"
188
     */
189 1
    private function getStringName(array $name) : string
190 1
    {
191
        $names = array_reduce(array_keys($name), function (array $carry, string $key) use ($name) : array {
192 1
            $carry[] = $key . '=' . $name[$key];
193
194
            return $carry;
195
        }, []);
196
197
        return implode(',', $names);
198
    }
199
}
200