PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 5.5.1
Defender Security – Malware Scanner, Login Security & Firewall v5.5.1
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / lib / packages / DI / Definition / Resolver / ObjectCreator.php

ObjectCreator.php in Defender Security – Malware Scanner, Login Security & Firewall 5.5.1, at lib/packages/DI/Definition/Resolver/ObjectCreator.php

223 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace WPMU_DEV\Defender\Vendor\DI\Definition\Resolver;
6
7 use WPMU_DEV\Defender\Vendor\DI\Definition\Definition;
8 use WPMU_DEV\Defender\Vendor\DI\Definition\Exception\InvalidDefinition;
9 use WPMU_DEV\Defender\Vendor\DI\Definition\ObjectDefinition;
10 use WPMU_DEV\Defender\Vendor\DI\Definition\ObjectDefinition\PropertyInjection;
11 use WPMU_DEV\Defender\Vendor\DI\DependencyException;
12 use WPMU_DEV\Defender\Vendor\DI\Proxy\ProxyFactory;
13 use Exception;
14 use ProxyManager\Proxy\LazyLoadingInterface;
15 use WPMU_DEV\Defender\Vendor\Psr\Container\NotFoundExceptionInterface;
16 use ReflectionClass;
17 use ReflectionProperty;
18
19 /**
20 * Create objects based on an object definition.
21 *
22 * @since 4.0
23 * @author Matthieu Napoli <[email protected]>
24 */
25 class ObjectCreator implements DefinitionResolver
26 {
27 /**
28 * @var ProxyFactory
29 */
30 private $proxyFactory;
31
32 /**
33 * @var ParameterResolver
34 */
35 private $parameterResolver;
36
37 /**
38 * @var DefinitionResolver
39 */
40 private $definitionResolver;
41
42 /**
43 * @param DefinitionResolver $definitionResolver Used to resolve nested definitions.
44 * @param ProxyFactory $proxyFactory Used to create proxies for lazy injections.
45 */
46 public function __construct(
47 DefinitionResolver $definitionResolver,
48 ProxyFactory $proxyFactory
49 ) {
50 $this->definitionResolver = $definitionResolver;
51 $this->proxyFactory = $proxyFactory;
52 $this->parameterResolver = new ParameterResolver($definitionResolver);
53 }
54
55 /**
56 * Resolve a class definition to a value.
57 *
58 * This will create a new instance of the class using the injections points defined.
59 *
60 * @param ObjectDefinition $definition
61 *
62 * @return object|null
63 */
64 public function resolve(Definition $definition, array $parameters = [])
65 {
66 // Lazy?
67 if ($definition->isLazy()) {
68 return $this->createProxy($definition, $parameters);
69 }
70
71 return $this->createInstance($definition, $parameters);
72 }
73
74 /**
75 * The definition is not resolvable if the class is not instantiable (interface or abstract)
76 * or if the class doesn't exist.
77 *
78 * @param ObjectDefinition $definition
79 */
80 public function isResolvable(Definition $definition, array $parameters = []) : bool
81 {
82 return $definition->isInstantiable();
83 }
84
85 /**
86 * Returns a proxy instance.
87 */
88 private function createProxy(ObjectDefinition $definition, array $parameters) : LazyLoadingInterface
89 {
90 /** @noinspection PhpUnusedParameterInspection */
91 $proxy = $this->proxyFactory->createProxy(
92 $definition->getClassName(),
93 function (& $wrappedObject, $proxy, $method, $params, & $initializer) use ($definition, $parameters) {
94 $wrappedObject = $this->createInstance($definition, $parameters);
95 $initializer = null; // turning off further lazy initialization
96
97 return true;
98 }
99 );
100
101 return $proxy;
102 }
103
104 /**
105 * Creates an instance of the class and injects dependencies..
106 *
107 * @param array $parameters Optional parameters to use to create the instance.
108 *
109 * @throws InvalidDefinition
110 * @throws DependencyException
111 * @return object
112 */
113 private function createInstance(ObjectDefinition $definition, array $parameters)
114 {
115 // Check that the class is instantiable
116 if (! $definition->isInstantiable()) {
117 // Check that the class exists
118 if (! $definition->classExists()) {
119 throw InvalidDefinition::create($definition, sprintf(
120 'Entry "%s" cannot be resolved: the class doesn\'t exist',
121 $definition->getName()
122 ));
123 }
124
125 throw InvalidDefinition::create($definition, sprintf(
126 'Entry "%s" cannot be resolved: the class is not instantiable',
127 $definition->getName()
128 ));
129 }
130
131 $classname = $definition->getClassName();
132 $classReflection = new ReflectionClass($classname);
133
134 $constructorInjection = $definition->getConstructorInjection();
135
136 try {
137 $args = $this->parameterResolver->resolveParameters(
138 $constructorInjection,
139 $classReflection->getConstructor(),
140 $parameters
141 );
142
143 $object = new $classname(...$args);
144
145 $this->injectMethodsAndProperties($object, $definition);
146 } catch (NotFoundExceptionInterface $e) {
147 throw new DependencyException(sprintf(
148 'Error while injecting dependencies into %s: %s',
149 $classReflection->getName(),
150 $e->getMessage()
151 ), 0, $e);
152 } catch (InvalidDefinition $e) {
153 throw InvalidDefinition::create($definition, sprintf(
154 'Entry "%s" cannot be resolved: %s',
155 $definition->getName(),
156 $e->getMessage()
157 ));
158 }
159
160 return $object;
161 }
162
163 protected function injectMethodsAndProperties($object, ObjectDefinition $objectDefinition)
164 {
165 // Property injections
166 foreach ($objectDefinition->getPropertyInjections() as $propertyInjection) {
167 $this->injectProperty($object, $propertyInjection);
168 }
169
170 // Method injections
171 foreach ($objectDefinition->getMethodInjections() as $methodInjection) {
172 $methodReflection = new \ReflectionMethod($object, $methodInjection->getMethodName());
173 $args = $this->parameterResolver->resolveParameters($methodInjection, $methodReflection);
174
175 $methodReflection->invokeArgs($object, $args);
176 }
177 }
178
179 /**
180 * Inject dependencies into properties.
181 *
182 * @param object $object Object to inject dependencies into
183 * @param PropertyInjection $propertyInjection Property injection definition
184 *
185 * @throws DependencyException
186 * @throws InvalidDefinition
187 */
188 private function injectProperty($object, PropertyInjection $propertyInjection)
189 {
190 $propertyName = $propertyInjection->getPropertyName();
191
192 $value = $propertyInjection->getValue();
193
194 if ($value instanceof Definition) {
195 try {
196 $value = $this->definitionResolver->resolve($value);
197 } catch (DependencyException $e) {
198 throw $e;
199 } catch (Exception $e) {
200 throw new DependencyException(sprintf(
201 'Error while injecting in %s::%s. %s',
202 get_class($object),
203 $propertyName,
204 $e->getMessage()
205 ), 0, $e);
206 }
207 }
208
209 self::setPrivatePropertyValue($propertyInjection->getClassName(), $object, $propertyName, $value);
210 }
211
212 public static function setPrivatePropertyValue(string $className = null, $object, string $propertyName, $propertyValue)
213 {
214 $className = $className ?: get_class($object);
215
216 $property = new ReflectionProperty($className, $propertyName);
217 if (! $property->isPublic()) {
218 $property->setAccessible(true);
219 }
220 $property->setValue($object, $propertyValue);
221 }
222 }
223