PluginProbe ʕ •ᴥ•ʔ
Cookiebot by Usercentrics – Automatic Cookie Banner for GDPR/CCPA & Google Consent Mode / 3.11.1
Cookiebot by Usercentrics – Automatic Cookie Banner for GDPR/CCPA & Google Consent Mode v3.11.1
4.7.2 4.7.1 trunk 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 3.0.0 3.0.1 3.1.0 3.10.0 3.10.1 3.11.1 3.11.2 3.11.3 3.2.0 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.5 3.6.6 3.7.0 3.7.1 3.8.0 3.9.0 4.0.0 4.0.1 4.0.2 4.0.3 4.1.0 4.1.1 4.2.0 4.2.1 4.2.10 4.2.11 4.2.12 4.2.13 4.2.14 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.8 4.2.9 4.3.0 4.3.1 4.3.10 4.3.11 4.3.12 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.7.1 4.3.8 4.3.9 4.3.9.1 4.4.0 4.4.1 4.4.2 4.5.0 4.5.1 4.5.10 4.5.11 4.5.2 4.5.3 4.5.4 4.5.5 4.5.6 4.5.7 4.5.8 4.5.9 4.6.0 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.6.6 4.6.7 4.7.0
cookiebot / addons / inc / Dependencies / DI / Definition / Resolver / ObjectCreator.php
cookiebot / addons / inc / Dependencies / DI / Definition / Resolver Last commit date
AliasResolver.php 5 years ago ArrayResolver.php 5 years ago DecoratorResolver.php 5 years ago DefinitionResolver.php 5 years ago EnvironmentVariableResolver.php 5 years ago FactoryResolver.php 5 years ago InstanceInjector.php 5 years ago ObjectCreator.php 5 years ago ParameterResolver.php 5 years ago ResolverDispatcher.php 5 years ago StringResolver.php 5 years ago ValueResolver.php 5 years ago
ObjectCreator.php
267 lines
1 <?php
2 /**
3 * PHP-DI
4 *
5 * @link http://mnapoli.github.com/PHP-DI/
6 * @copyright Matthieu Napoli (http://mnapoli.fr/)
7 * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8 */
9
10 namespace Cybot\Dependencies\DI\Definition\Resolver;
11
12 use Cybot\Dependencies\DI\Definition\ObjectDefinition;
13 use Cybot\Dependencies\DI\Definition\Definition;
14 use Cybot\Dependencies\DI\Definition\Exception\DefinitionException;
15 use Cybot\Dependencies\DI\Definition\ObjectDefinition\PropertyInjection;
16 use Cybot\Dependencies\DI\Definition\Helper\DefinitionHelper;
17 use Cybot\Dependencies\DI\DependencyException;
18 use Cybot\Dependencies\DI\Proxy\ProxyFactory;
19 use Exception;
20 use Cybot\Dependencies\Interop\Container\Exception\NotFoundException;
21 use ProxyManager\Proxy\LazyLoadingInterface;
22 use ReflectionClass;
23 use ReflectionProperty;
24
25 /**
26 * Create objects based on an object definition.
27 *
28 * @since 4.0
29 * @author Matthieu Napoli <matthieu@mnapoli.fr>
30 */
31 class ObjectCreator implements DefinitionResolver
32 {
33 /**
34 * @var ProxyFactory
35 */
36 private $proxyFactory;
37
38 /**
39 * @var ParameterResolver
40 */
41 private $parameterResolver;
42
43 /**
44 * @var DefinitionResolver
45 */
46 private $definitionResolver;
47
48 /**
49 * @param DefinitionResolver $definitionResolver Used to resolve nested definitions.
50 * @param ProxyFactory $proxyFactory Used to create proxies for lazy injections.
51 */
52 public function __construct(
53 DefinitionResolver $definitionResolver,
54 ProxyFactory $proxyFactory
55 ) {
56 $this->definitionResolver = $definitionResolver;
57 $this->proxyFactory = $proxyFactory;
58 $this->parameterResolver = new ParameterResolver($definitionResolver);
59 }
60
61 /**
62 * Resolve a class definition to a value.
63 *
64 * This will create a new instance of the class using the injections points defined.
65 *
66 * @param ObjectDefinition $definition
67 *
68 * {@inheritdoc}
69 */
70 public function resolve(Definition $definition, array $parameters = [])
71 {
72 $this->assertIsObjectDefinition($definition);
73
74 // Lazy?
75 if ($definition->isLazy()) {
76 return $this->createProxy($definition, $parameters);
77 }
78
79 return $this->createInstance($definition, $parameters);
80 }
81
82 /**
83 * The definition is not resolvable if the class is not instantiable (interface or abstract)
84 * or if the class doesn't exist.
85 *
86 * @param ObjectDefinition $definition
87 *
88 * {@inheritdoc}
89 */
90 public function isResolvable(Definition $definition, array $parameters = [])
91 {
92 $this->assertIsObjectDefinition($definition);
93
94 if (! class_exists($definition->getClassName())) {
95 return false;
96 }
97
98 $classReflection = new ReflectionClass($definition->getClassName());
99
100 return $classReflection->isInstantiable();
101 }
102
103 /**
104 * Returns a proxy instance
105 *
106 * @param ObjectDefinition $definition
107 * @param array $parameters
108 *
109 * @return LazyLoadingInterface Proxy instance
110 */
111 private function createProxy(ObjectDefinition $definition, array $parameters)
112 {
113 /** @noinspection PhpUnusedParameterInspection */
114 $proxy = $this->proxyFactory->createProxy(
115 $definition->getClassName(),
116 function (& $wrappedObject, $proxy, $method, $params, & $initializer) use ($definition, $parameters) {
117 $wrappedObject = $this->createInstance($definition, $parameters);
118 $initializer = null; // turning off further lazy initialization
119 return true;
120 }
121 );
122
123 return $proxy;
124 }
125
126 /**
127 * Creates an instance of the class and injects dependencies..
128 *
129 * @param ObjectDefinition $definition
130 * @param array $parameters Optional parameters to use to create the instance.
131 *
132 * @throws DefinitionException
133 * @throws DependencyException
134 * @return object
135 */
136 private function createInstance(ObjectDefinition $definition, array $parameters)
137 {
138 $this->assertClassExists($definition);
139
140 $classReflection = new ReflectionClass($definition->getClassName());
141
142 $this->assertClassIsInstantiable($definition, $classReflection);
143
144 $constructorInjection = $definition->getConstructorInjection();
145
146 try {
147 $args = $this->parameterResolver->resolveParameters(
148 $constructorInjection,
149 $classReflection->getConstructor(),
150 $parameters
151 );
152
153 if (count($args) > 0) {
154 $object = $classReflection->newInstanceArgs($args);
155 } else {
156 $object = $classReflection->newInstance();
157 }
158
159 $this->injectMethodsAndProperties($object, $definition);
160 } catch (NotFoundException $e) {
161 throw new DependencyException(sprintf(
162 "Error while injecting dependencies into %s: %s",
163 $classReflection->getName(),
164 $e->getMessage()
165 ), 0, $e);
166 } catch (DefinitionException $e) {
167 throw DefinitionException::create($definition, sprintf(
168 "Entry %s cannot be resolved: %s",
169 $definition->getName(),
170 $e->getMessage()
171 ));
172 }
173
174 return $object;
175 }
176
177 protected function injectMethodsAndProperties($object, ObjectDefinition $objectDefinition)
178 {
179 // Property injections
180 foreach ($objectDefinition->getPropertyInjections() as $propertyInjection) {
181 $this->injectProperty($object, $propertyInjection);
182 }
183
184 // Method injections
185 foreach ($objectDefinition->getMethodInjections() as $methodInjection) {
186 $methodReflection = new \ReflectionMethod($object, $methodInjection->getMethodName());
187 $args = $this->parameterResolver->resolveParameters($methodInjection, $methodReflection);
188
189 $methodReflection->invokeArgs($object, $args);
190 }
191 }
192
193 /**
194 * Inject dependencies into properties.
195 *
196 * @param object $object Object to inject dependencies into
197 * @param PropertyInjection $propertyInjection Property injection definition
198 *
199 * @throws DependencyException
200 * @throws DefinitionException
201 */
202 private function injectProperty($object, PropertyInjection $propertyInjection)
203 {
204 $propertyName = $propertyInjection->getPropertyName();
205 $property = new ReflectionProperty(get_class($object), $propertyName);
206
207 $value = $propertyInjection->getValue();
208
209 if ($value instanceof DefinitionHelper) {
210 /** @var Definition $nestedDefinition */
211 $nestedDefinition = $value->getDefinition('');
212
213 try {
214 $value = $this->definitionResolver->resolve($nestedDefinition);
215 } catch (DependencyException $e) {
216 throw $e;
217 } catch (Exception $e) {
218 throw new DependencyException(sprintf(
219 "Error while injecting in %s::%s. %s",
220 get_class($object),
221 $propertyName,
222 $e->getMessage()
223 ), 0, $e);
224 }
225 }
226
227 if (! $property->isPublic()) {
228 $property->setAccessible(true);
229 }
230 $property->setValue($object, $value);
231 }
232
233 private function assertIsObjectDefinition(Definition $definition)
234 {
235 if (!$definition instanceof ObjectDefinition) {
236 throw new \InvalidArgumentException(sprintf(
237 'This definition resolver is only compatible with ObjectDefinition objects, %s given',
238 get_class($definition)
239 ));
240 }
241 }
242
243 private function assertClassExists(ObjectDefinition $definition)
244 {
245 if (!class_exists($definition->getClassName()) && !interface_exists($definition->getClassName())) {
246 throw DefinitionException::create($definition,
247 sprintf(
248 "Entry %s cannot be resolved: class %s doesn't exist",
249 $definition->getName(),
250 $definition->getClassName()
251 ));
252 }
253 }
254
255 private function assertClassIsInstantiable(ObjectDefinition $definition, ReflectionClass $classReflection)
256 {
257 if (!$classReflection->isInstantiable()) {
258 throw DefinitionException::create($definition,
259 sprintf(
260 "Entry %s cannot be resolved: class %s is not instantiable",
261 $definition->getName(),
262 $definition->getClassName()
263 ));
264 }
265 }
266 }
267