1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Created by Vitaly Iegorov <[email protected]>. |
4
|
|
|
* on 22.01.16 at 23:53 |
5
|
|
|
*/ |
6
|
|
|
namespace samsonframework\di; |
7
|
|
|
|
8
|
|
|
use Interop\Container\ContainerInterface; |
9
|
|
|
use samsonframework\di\exception\ContainerException; |
10
|
|
|
use samsonframework\di\exception\NotFoundException; |
11
|
|
|
use samsonphp\generator\Generator; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* Abstract dependency injection container. |
15
|
|
|
* |
16
|
|
|
* @package samsonframework\di |
17
|
|
|
*/ |
18
|
|
|
abstract class AbstractContainer implements ContainerInterface |
19
|
|
|
{ |
20
|
|
|
/** Default logic function name */ |
21
|
|
|
const LOGIC_FUNCTION_NAME = 'diContainer'; |
22
|
|
|
|
23
|
|
|
/** @var array[string] Collection of alias => class name for alias resolving */ |
24
|
|
|
protected $aliases = array(); |
25
|
|
|
|
26
|
|
|
/** @var array[string] Collection of entity name resolving */ |
27
|
|
|
protected $resolver = array(); |
28
|
|
|
|
29
|
|
|
/** @var array[string] Collection of class name dependencies trees */ |
30
|
|
|
protected $dependencies = array(); |
31
|
|
|
|
32
|
|
|
/** @var ContainerInterface[] Collection of delegated containers */ |
33
|
|
|
protected $delegates = array(); |
34
|
|
|
|
35
|
|
|
/** @var array[string] Collection of dependency parameters */ |
36
|
|
|
protected $parameters = array(); |
37
|
|
|
|
38
|
|
|
/** @var \samsonphp\generator\Generator */ |
39
|
|
|
protected $generator; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Container constructor. |
43
|
|
|
* |
44
|
|
|
* @param Generator $generator |
45
|
|
|
*/ |
46
|
9 |
|
public function __construct(Generator $generator) |
47
|
|
|
{ |
48
|
9 |
|
$this->generator = $generator; |
49
|
9 |
|
} |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Help container resolving interfaces and abstract classes or any entities to |
53
|
|
|
* different one. |
54
|
|
|
* |
55
|
|
|
* @param string $source Source entity name |
56
|
|
|
* @param string $destination Destination entity name |
57
|
|
|
* |
58
|
|
|
* @return self Chaining |
59
|
|
|
*/ |
60
|
|
|
public function resolve($source, $destination) |
61
|
|
|
{ |
62
|
|
|
$this->resolver[$source] = $destination; |
63
|
|
|
|
64
|
|
|
return $this; |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Internal logic handler. Calls generated logic function |
69
|
|
|
* for performing entity creation or search. This is encapsulated |
70
|
|
|
* method for further overriding. |
71
|
|
|
* |
72
|
|
|
* @param string $alias Entity alias |
73
|
|
|
* |
74
|
|
|
* @return mixed Created instance or null |
75
|
|
|
* @throws ContainerException |
76
|
|
|
*/ |
77
|
|
|
protected function logic($alias) |
78
|
|
|
{ |
79
|
|
|
if (!function_exists(self::LOGIC_FUNCTION_NAME)) { |
80
|
|
|
throw new ContainerException('Logic function does not exists'); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
return call_user_func(self::LOGIC_FUNCTION_NAME, $alias); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Finds an entry of the container by its identifier and returns it. |
88
|
|
|
* |
89
|
|
|
* @param string $alias Identifier of the entry to look for. |
90
|
|
|
* |
91
|
|
|
* @throws NotFoundException No entry was found for this identifier. |
92
|
|
|
* @throws ContainerException Error while retrieving the entry. |
93
|
|
|
* |
94
|
|
|
* @return mixed Entry. |
95
|
|
|
*/ |
96
|
|
|
public function get($alias) |
97
|
|
|
{ |
98
|
|
|
// Get pointer from logic |
99
|
|
|
$module = $this->logic($alias); |
100
|
|
|
|
101
|
|
|
// Try delegate lookup |
102
|
|
|
if (null === $module) { |
103
|
|
|
foreach ($this->delegates as $delegate) { |
104
|
|
|
try { |
105
|
|
|
$module = $delegate->get($alias); |
106
|
|
|
} catch (ContainerException $e) { |
107
|
|
|
// Catch all delegated exceptions |
108
|
|
|
} catch (NotFoundException $e) { |
|
|
|
|
109
|
|
|
// Catch all delegated exceptions |
110
|
|
|
} |
111
|
|
|
} |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
if (null === $module) { |
115
|
|
|
throw new NotFoundException($alias); |
116
|
|
|
} else { |
117
|
|
|
return $module; |
118
|
|
|
} |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* Implementing delegate lookup feature. |
123
|
|
|
* If current container cannot resolve entity dependency |
124
|
|
|
* resolving process is passed to delegated container. |
125
|
|
|
* |
126
|
|
|
* @param ContainerInterface $container Container for delegate lookup |
127
|
|
|
*/ |
128
|
|
|
public function delegate(ContainerInterface $container) |
129
|
|
|
{ |
130
|
|
|
$this->delegates[] = $container; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* Returns true if the container can return an entry for the given identifier. |
135
|
|
|
* Returns false otherwise. |
136
|
|
|
* |
137
|
|
|
* @param string $alias Identifier of the entry to look for. |
138
|
|
|
* |
139
|
|
|
* @return boolean |
140
|
|
|
*/ |
141
|
|
|
public function has($alias) |
142
|
|
|
{ |
143
|
|
|
$found = array_key_exists($alias, $this->dependencies) |
144
|
|
|
|| in_array($alias, $this->aliases); |
145
|
|
|
|
146
|
|
|
if (!$found) { |
147
|
|
|
foreach ($this->delegates as $delegate) { |
148
|
|
|
if ($delegate->has($alias)) { |
149
|
|
|
return true; |
150
|
|
|
} |
151
|
|
|
} |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
return $found; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* Generate logic conditions and their implementation for container and its delegates. |
159
|
|
|
* |
160
|
|
|
* @param string $inputVariable Input condition parameter variable name |
161
|
|
|
* @param bool|false $started Flag if condition branching has been started |
162
|
|
|
*/ |
163
|
|
|
public function generateConditions($inputVariable = '$alias', $started = false) |
164
|
|
|
{ |
165
|
|
|
// Iterate all container dependencies |
166
|
|
|
foreach ($this->dependencies as $alias => $entity) { |
167
|
|
|
// Generate condition statement to define if this class is needed |
168
|
|
|
$conditionFunc = !$started ? 'defIfCondition' : 'defElseIfCondition'; |
169
|
|
|
|
170
|
|
|
// Create condition branch |
171
|
|
|
$condition = $inputVariable . ' === \'' . $alias . '\''; |
172
|
|
|
// If we have an alias for this - add it to condition |
173
|
|
|
$condition .= array_key_exists($alias, $this->aliases) |
174
|
|
|
? ' || ' . $inputVariable . ' === \'' . $this->aliases[$alias] . '\'' |
175
|
|
|
: ''; |
176
|
|
|
// Output condition branch |
177
|
|
|
$this->generator->$conditionFunc($condition); |
178
|
|
|
|
179
|
|
|
// Generate condition for each dependency |
180
|
|
|
$this->generateCondition($alias, $entity); |
181
|
|
|
|
182
|
|
|
// Set flag that condition is started |
183
|
|
|
$started = true; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** @var self $delegate Iterate delegated container to get their conditions */ |
187
|
|
|
foreach ($this->delegates as $delegate) { |
188
|
|
|
// Set current generator |
189
|
|
|
if ($delegate instanceof AbstractContainer) { |
190
|
|
|
$delegate->generator = $this->generator; |
191
|
|
|
} |
192
|
|
|
$delegate->generateConditions($inputVariable, $started); |
193
|
|
|
} |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* Generate dependency injection logic function. |
198
|
|
|
* |
199
|
|
|
* @param string $functionName |
200
|
|
|
* |
201
|
|
|
* @return string PHP logic function code |
202
|
|
|
*/ |
203
|
|
|
public function generateFunction($functionName = self::LOGIC_FUNCTION_NAME) |
204
|
|
|
{ |
205
|
|
|
$inputVariable = '$aliasOrClassName'; |
206
|
|
|
$this->generator |
207
|
|
|
->defFunction($functionName, array($inputVariable)) |
208
|
|
|
->defVar('static $services') |
209
|
|
|
->defVar($inputVariable) |
210
|
|
|
->newLine(); |
211
|
|
|
|
212
|
|
|
// Generate all container and delegate conditions |
213
|
|
|
$this->generateConditions($inputVariable, false); |
214
|
|
|
|
215
|
|
|
// Add method not found |
216
|
|
|
return $this->generator |
217
|
|
|
->endIfCondition() |
218
|
|
|
->endFunction() |
219
|
|
|
->flush(); |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
/** |
223
|
|
|
* Set container dependency. |
224
|
|
|
* |
225
|
|
|
* @param mixed $entity Entity |
226
|
|
|
* @param string|null $alias Entity alias for simplier finding |
227
|
|
|
* @param array $parameters Collection of additional parameters |
228
|
|
|
* |
229
|
|
|
* @return self Chaining |
230
|
|
|
*/ |
231
|
|
|
abstract public function set($entity, $alias = null, array $parameters = array()); |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* Generate container dependency condition code. |
235
|
|
|
* |
236
|
|
|
* @param string $alias Entity alias |
237
|
|
|
* @param mixed $entity Entity |
238
|
|
|
*/ |
239
|
|
|
abstract protected function generateCondition($alias, &$entity); |
240
|
|
|
} |
241
|
|
|
|
Scrutinizer analyzes your
composer.json
/composer.lock
file if available to determine the classes, and functions that are defined by your dependencies.It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.