Completed
Push — master ( ce140e...44a168 )
by Matthieu
03:17 queued 01:39
created

ObjectDefinition::completeFirstMethodInjection()   A

Complexity

Conditions 2
Paths 2

Duplication

Lines 0
Ratio 0 %

Size

Total Lines 12
Code Lines 6

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 1
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace DI\Definition;
6
7
use DI\Definition\Dumper\ObjectDefinitionDumper;
8
use DI\Definition\ObjectDefinition\MethodInjection;
9
use DI\Definition\ObjectDefinition\PropertyInjection;
10
use ReflectionClass;
11
12
/**
13
 * Defines how an object can be instantiated.
14
 *
15
 * @author Matthieu Napoli <[email protected]>
16
 */
17
class ObjectDefinition implements Definition
18
{
19
    /**
20
     * Entry name (most of the time, same as $classname).
21
     * @var string
22
     */
23
    private $name;
24
25
    /**
26
     * Class name (if null, then the class name is $name).
27
     * @var string|null
28
     */
29
    protected $className;
30
31
    /**
32
     * Constructor parameter injection.
33
     * @var MethodInjection|null
34
     */
35
    protected $constructorInjection;
36
37
    /**
38
     * Property injections.
39
     * @var PropertyInjection[]
40
     */
41
    protected $propertyInjections = [];
42
43
    /**
44
     * Method calls.
45
     * @var MethodInjection[][]
46
     */
47
    protected $methodInjections = [];
48
49
    /**
50
     * @var bool|null
51
     */
52
    protected $lazy;
53
54
    /**
55
     * Store if the class exists. Storing it (in cache) avoids recomputing this.
56
     *
57
     * @var bool
58
     */
59
    private $classExists;
60
61
    /**
62
     * Store if the class is instantiable. Storing it (in cache) avoids recomputing this.
63
     *
64
     * @var bool
65
     */
66
    private $isInstantiable;
67
68
    /**
69
     * @param string $name Entry name
70
     */
71
    public function __construct(string $name, string $className = null)
72
    {
73
        $this->name = $name;
74
        $this->setClassName($className);
75
    }
76
77
    public function getName() : string
78
    {
79
        return $this->name;
80
    }
81
82
    public function setClassName(string $className = null)
83
    {
84
        $this->className = $className;
85
86
        $this->updateCache();
87
    }
88
89
    public function getClassName() : string
90
    {
91
        if ($this->className !== null) {
92
            return $this->className;
93
        }
94
95
        return $this->name;
96
    }
97
98
    /**
99
     * @return MethodInjection|null
100
     */
101
    public function getConstructorInjection()
102
    {
103
        return $this->constructorInjection;
104
    }
105
106
    public function setConstructorInjection(MethodInjection $constructorInjection)
107
    {
108
        $this->constructorInjection = $constructorInjection;
109
    }
110
111
    public function completeConstructorInjection(MethodInjection $injection)
112
    {
113
        if ($this->constructorInjection !== null) {
114
            // Merge
115
            $this->constructorInjection->merge($injection);
116
        } else {
117
            // Set
118
            $this->constructorInjection = $injection;
119
        }
120
    }
121
122
    /**
123
     * @return PropertyInjection[] Property injections
124
     */
125
    public function getPropertyInjections() : array
126
    {
127
        return $this->propertyInjections;
128
    }
129
130
    public function addPropertyInjection(PropertyInjection $propertyInjection)
131
    {
132
        $className = $propertyInjection->getClassName();
133
        if ($className) {
0 ignored issues
show
Bug Best Practice introduced by Matthieu Napoli
The expression $className of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
134
            // Index with the class name to avoid collisions between parent and
135
            // child private properties with the same name
136
            $key = $className . '::' . $propertyInjection->getPropertyName();
137
        } else {
138
            $key = $propertyInjection->getPropertyName();
139
        }
140
141
        $this->propertyInjections[$key] = $propertyInjection;
142
    }
143
144
    /**
145
     * @return MethodInjection[] Method injections
146
     */
147
    public function getMethodInjections() : array
148
    {
149
        // Return array leafs
150
        $injections = [];
151
        array_walk_recursive($this->methodInjections, function ($injection) use (&$injections) {
152
            $injections[] = $injection;
153
        });
154
155
        return $injections;
156
    }
157
158
    public function addMethodInjection(MethodInjection $methodInjection)
159
    {
160
        $method = $methodInjection->getMethodName();
161
        if (! isset($this->methodInjections[$method])) {
162
            $this->methodInjections[$method] = [];
163
        }
164
        $this->methodInjections[$method][] = $methodInjection;
165
    }
166
167
    public function completeFirstMethodInjection(MethodInjection $injection)
168
    {
169
        $method = $injection->getMethodName();
170
171
        if (isset($this->methodInjections[$method][0])) {
172
            // Merge
173
            $this->methodInjections[$method][0]->merge($injection);
174
        } else {
175
            // Set
176
            $this->addMethodInjection($injection);
177
        }
178
    }
179
180
    public function setLazy(bool $lazy = null)
181
    {
182
        $this->lazy = $lazy;
183
    }
184
185
    public function isLazy() : bool
186
    {
187
        if ($this->lazy !== null) {
188
            return $this->lazy;
189
        }
190
        // Default value
191
        return false;
192
    }
193
194
    public function classExists() : bool
195
    {
196
        return $this->classExists;
197
    }
198
199
    public function isInstantiable() : bool
200
    {
201
        return $this->isInstantiable;
202
    }
203
204
    public function __toString()
205
    {
206
        return (new ObjectDefinitionDumper)->dump($this);
207
    }
208
209
    private function updateCache()
210
    {
211
        $className = $this->getClassName();
212
213
        $this->classExists = class_exists($className) || interface_exists($className);
214
215
        if (! $this->classExists) {
216
            $this->isInstantiable = false;
217
218
            return;
219
        }
220
221
        $class = new ReflectionClass($className);
222
        $this->isInstantiable = $class->isInstantiable();
223
    }
224
}
225