Completed
Push — master ( ff0374...3c2b88 )
by Matthieu
02:06
created

ObjectDefinition   A

↳ Parent: Project

Coupling/Cohesion

Components 5
Dependencies 3

Complexity

Total Complexity 25

Size/Duplication

Total Lines 234
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 234
rs 10
c 0
b 0
f 0
wmc 25
lcom 5
cbo 3

18 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getName() 0 4 1
A getConstructorInjection() 0 4 1
A setConstructorInjection() 0 4 1
A getPropertyInjections() 0 4 1
A addMethodInjection() 0 8 2
A setScope() 0 4 1
A getScope() 0 4 2
A setLazy() 0 4 1
A isLazy() 0 9 2
A setClassName() 0 6 1
A classExists() 0 4 1
A isInstantiable() 0 4 1
A getClassName() 0 8 2
A addPropertyInjection() 0 13 2
A getMethodInjections() 0 10 1
A __toString() 0 4 1
A updateCache() 0 15 3
1
<?php
2
3
namespace DI\Definition;
4
5
use DI\Definition\Dumper\ObjectDefinitionDumper;
6
use DI\Definition\ObjectDefinition\MethodInjection;
7
use DI\Definition\ObjectDefinition\PropertyInjection;
8
use DI\Scope;
9
use ReflectionClass;
10
11
/**
12
 * Defines how an object can be instantiated.
13
 *
14
 * @author Matthieu Napoli <[email protected]>
15
 */
16
class ObjectDefinition implements Definition, CacheableDefinition
17
{
18
    /**
19
     * Entry name (most of the time, same as $classname).
20
     * @var string
21
     */
22
    private $name;
23
24
    /**
25
     * Class name (if null, then the class name is $name).
26
     * @var string|null
27
     */
28
    protected $className;
29
30
    /**
31
     * Constructor parameter injection.
32
     * @var MethodInjection|null
33
     */
34
    protected $constructorInjection;
35
36
    /**
37
     * Property injections.
38
     * @var PropertyInjection[]
39
     */
40
    protected $propertyInjections = [];
41
42
    /**
43
     * Method calls.
44
     * @var MethodInjection[][]
45
     */
46
    protected $methodInjections = [];
47
48
    /**
49
     * @var string|null
50
     */
51
    protected $scope;
52
53
    /**
54
     * @var bool|null
55
     */
56
    protected $lazy;
57
58
    /**
59
     * Store if the class exists. Storing it (in cache) avoids recomputing this.
60
     *
61
     * @var bool
62
     */
63
    private $classExists;
64
65
    /**
66
     * Store if the class is instantiable. Storing it (in cache) avoids recomputing this.
67
     *
68
     * @var bool
69
     */
70
    private $isInstantiable;
71
72
    /**
73
     * @param string $name Class name
74
     * @param string $className
75
     */
76
    public function __construct($name, $className = null)
77
    {
78
        $this->name = (string) $name;
79
        $this->setClassName($className);
80
    }
81
82
    /**
83
     * @return string Entry name
84
     */
85
    public function getName()
86
    {
87
        return $this->name;
88
    }
89
90
    /**
91
     * @param string|null $className
92
     */
93
    public function setClassName($className)
94
    {
95
        $this->className = $className;
96
97
        $this->updateCache();
98
    }
99
100
    /**
101
     * @return string Class name
102
     */
103
    public function getClassName()
104
    {
105
        if ($this->className !== null) {
106
            return $this->className;
107
        }
108
109
        return $this->name;
110
    }
111
112
    /**
113
     * @return MethodInjection|null
114
     */
115
    public function getConstructorInjection()
116
    {
117
        return $this->constructorInjection;
118
    }
119
120
    /**
121
     * @param MethodInjection $constructorInjection
122
     */
123
    public function setConstructorInjection(MethodInjection $constructorInjection)
124
    {
125
        $this->constructorInjection = $constructorInjection;
126
    }
127
128
    /**
129
     * @return PropertyInjection[] Property injections
130
     */
131
    public function getPropertyInjections()
132
    {
133
        return $this->propertyInjections;
134
    }
135
136
    public function addPropertyInjection(PropertyInjection $propertyInjection)
137
    {
138
        $className = $propertyInjection->getClassName();
139
        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...
140
            // Index with the class name to avoid collisions between parent and
141
            // child private properties with the same name
142
            $key = $className . '::' . $propertyInjection->getPropertyName();
143
        } else {
144
            $key = $propertyInjection->getPropertyName();
145
        }
146
147
        $this->propertyInjections[$key] = $propertyInjection;
148
    }
149
150
    /**
151
     * @return MethodInjection[] Method injections
152
     */
153
    public function getMethodInjections()
154
    {
155
        // Return array leafs
156
        $injections = [];
157
        array_walk_recursive($this->methodInjections, function ($injection) use (&$injections) {
158
            $injections[] = $injection;
159
        });
160
161
        return $injections;
162
    }
163
164
    /**
165
     * @param MethodInjection $methodInjection
166
     */
167
    public function addMethodInjection(MethodInjection $methodInjection)
168
    {
169
        $method = $methodInjection->getMethodName();
170
        if (! isset($this->methodInjections[$method])) {
171
            $this->methodInjections[$method] = [];
172
        }
173
        $this->methodInjections[$method][] = $methodInjection;
174
    }
175
176
    /**
177
     * @param string $scope
178
     */
179
    public function setScope($scope)
180
    {
181
        $this->scope = $scope;
182
    }
183
184
    /**
185
     * [email protected]}
186
     */
187
    public function getScope()
188
    {
189
        return $this->scope ?: Scope::SINGLETON;
190
    }
191
192
    /**
193
     * @param bool|null $lazy
194
     */
195
    public function setLazy($lazy)
196
    {
197
        $this->lazy = $lazy;
198
    }
199
200
    /**
201
     * @return bool
202
     */
203
    public function isLazy()
204
    {
205
        if ($this->lazy !== null) {
206
            return $this->lazy;
207
        } else {
208
            // Default value
209
            return false;
210
        }
211
    }
212
213
    /**
214
     * @return bool
215
     */
216
    public function classExists()
217
    {
218
        return $this->classExists;
219
    }
220
221
    /**
222
     * @return bool
223
     */
224
    public function isInstantiable()
225
    {
226
        return $this->isInstantiable;
227
    }
228
229
    public function __toString()
230
    {
231
        return (new ObjectDefinitionDumper)->dump($this);
232
    }
233
234
    private function updateCache()
235
    {
236
        $className = $this->getClassName();
237
238
        $this->classExists = class_exists($className) || interface_exists($className);
239
240
        if (! $this->classExists) {
241
            $this->isInstantiable = false;
242
243
            return;
244
        }
245
246
        $class = new ReflectionClass($className);
247
        $this->isInstantiable = $class->isInstantiable();
248
    }
249
}
250