PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.2.2
Defender Security – Malware Scanner, Login Security & Firewall v6.2.2
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 / src / component / container / class-builder.php

class-builder.php in Defender Security – Malware Scanner, Login Security & Firewall 6.2.2, at src/component/container/class-builder.php

101 lines 2.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Dependency injection container object builder.
4 *
5 * @package WP_Defender\Component\Container
6 */
7
8 namespace WP_Defender\Component\Container;
9
10 use Throwable;
11 use ReflectionClass;
12 use RuntimeException;
13 use WP_Defender\Component\Container;
14
15 /**
16 * Constructs objects requested by the container.
17 *
18 * @internal
19 */
20 final class Builder {
21
22 /**
23 * Entries currently being resolved.
24 *
25 * @var array<string, true>
26 */
27 private array $resolving = array();
28
29 /**
30 * Constructor parameter resolver.
31 *
32 * @var Parameter_Resolver
33 */
34 private Parameter_Resolver $parameter_resolver;
35
36 /**
37 * Initialize the builder.
38 *
39 * @param Container $container Dependency injection container.
40 */
41 public function __construct( Container $container ) {
42 $this->parameter_resolver = new Parameter_Resolver( $container );
43 }
44
45 /**
46 * Construct a class with named overrides and autowired dependencies.
47 *
48 * @param string $id Class name.
49 * @param array<string, mixed> $parameters Named constructor parameters.
50 *
51 * @throws RuntimeException Entry does not exist or cannot be resolved.
52 */
53 public function build( string $id, array $parameters = array() ): object {
54 if ( ! $this->type_exists( $id ) ) {
55 throw new RuntimeException( 'Container entry was not found.' );
56 }
57
58 if ( isset( $this->resolving[ $id ] ) ) {
59 throw new RuntimeException( 'Circular dependency detected.' );
60 }
61
62 $this->resolving[ $id ] = true;
63
64 try {
65 $reflection = new ReflectionClass( $id );
66 if ( ! $reflection->isInstantiable() ) {
67 throw new RuntimeException( 'Container entry is not instantiable.' );
68 }
69
70 $constructor = $reflection->getConstructor();
71 if ( null === $constructor ) {
72 return $reflection->newInstance();
73 }
74
75 $arguments = array();
76 foreach ( $constructor->getParameters() as $parameter ) {
77 $arguments[] = $this->parameter_resolver->resolve( $parameter, $parameters );
78 }
79
80 return $reflection->newInstanceArgs( $arguments );
81 } catch ( RuntimeException $exception ) {
82 // This exception is rethrown, not rendered as output.
83 // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
84 throw $exception;
85 } catch ( Throwable $exception ) {
86 throw new RuntimeException( esc_html( sprintf( 'Unable to resolve container entry "%s".', $id ) ), 0, $exception );
87 } finally {
88 unset( $this->resolving[ $id ] );
89 }
90 }
91
92 /**
93 * Determine whether a PHP type exists.
94 *
95 * @param string $id Type name.
96 */
97 private function type_exists( string $id ): bool {
98 return class_exists( $id ) || interface_exists( $id ) || trait_exists( $id );
99 }
100 }
101