AbstractDependencyType.php
2 years ago
Container.php
2 years ago
FactoryType.php
2 years ago
SharedType.php
2 years ago
Container.php
99 lines
| 1 | <?php |
| 2 | namespace Automattic\WooCommerce\Blocks\Registry; |
| 3 | |
| 4 | use Closure; |
| 5 | use Exception; |
| 6 | |
| 7 | /** |
| 8 | * A simple Dependency Injection Container |
| 9 | * |
| 10 | * This is used to manage dependencies used throughout the plugin. |
| 11 | * |
| 12 | * @since 2.5.0 |
| 13 | */ |
| 14 | class Container { |
| 15 | |
| 16 | /** |
| 17 | * A map of Dependency Type objects used to resolve dependencies. |
| 18 | * |
| 19 | * @var AbstractDependencyType[] |
| 20 | */ |
| 21 | private $registry = []; |
| 22 | |
| 23 | /** |
| 24 | * Public api for adding a factory to the container. |
| 25 | * |
| 26 | * Factory dependencies will have the instantiation callback invoked |
| 27 | * every time the dependency is requested. |
| 28 | * |
| 29 | * Typical Usage: |
| 30 | * |
| 31 | * ``` |
| 32 | * $container->register( MyClass::class, $container->factory( $mycallback ) ); |
| 33 | * ``` |
| 34 | * |
| 35 | * @param Closure $instantiation_callback This will be invoked when the |
| 36 | * dependency is required. It will |
| 37 | * receive an instance of this |
| 38 | * container so the callback can |
| 39 | * retrieve dependencies from the |
| 40 | * container. |
| 41 | * |
| 42 | * @return FactoryType An instance of the FactoryType dependency. |
| 43 | */ |
| 44 | public function factory( Closure $instantiation_callback ) { |
| 45 | return new FactoryType( $instantiation_callback ); |
| 46 | } |
| 47 | |
| 48 | /** |
| 49 | * Interface for registering a new dependency with the container. |
| 50 | * |
| 51 | * By default, the $value will be added as a shared dependency. This means |
| 52 | * that it will be a single instance shared among any other classes having |
| 53 | * that dependency. |
| 54 | * |
| 55 | * If you want a new instance every time it's required, then wrap the value |
| 56 | * in a call to the factory method (@see Container::factory for example) |
| 57 | * |
| 58 | * Note: Currently if the provided id already is registered in the container, |
| 59 | * the provided value is ignored. |
| 60 | * |
| 61 | * @param string $id A unique string identifier for the provided value. |
| 62 | * Typically it's the fully qualified name for the |
| 63 | * dependency. |
| 64 | * @param mixed $value The value for the dependency. Typically, this is a |
| 65 | * closure that will create the class instance needed. |
| 66 | */ |
| 67 | public function register( $id, $value ) { |
| 68 | if ( empty( $this->registry[ $id ] ) ) { |
| 69 | if ( ! $value instanceof FactoryType ) { |
| 70 | $value = new SharedType( $value ); |
| 71 | } |
| 72 | $this->registry[ $id ] = $value; |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | /** |
| 77 | * Interface for retrieving the dependency stored in the container for the |
| 78 | * given identifier. |
| 79 | * |
| 80 | * @param string $id The identifier for the dependency being retrieved. |
| 81 | * @throws Exception If there is no dependency for the given identifier in |
| 82 | * the container. |
| 83 | * |
| 84 | * @return mixed Typically a class instance. |
| 85 | */ |
| 86 | public function get( $id ) { |
| 87 | if ( ! isset( $this->registry[ $id ] ) ) { |
| 88 | // this is a developer facing exception, hence it is not localized. |
| 89 | throw new Exception( |
| 90 | sprintf( |
| 91 | 'Cannot construct an instance of %s because it has not been registered.', |
| 92 | $id |
| 93 | ) |
| 94 | ); |
| 95 | } |
| 96 | return $this->registry[ $id ]->get( $this ); |
| 97 | } |
| 98 | } |
| 99 |