PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 5.8.1
Defender Security – Malware Scanner, Login Security & Firewall v5.8.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.8.1, at lib/packages/DI/Definition/Resolver/ObjectCreator.php

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