*/ private array $factories = []; /** * Shared instances keyed by service id. * * @var array */ private array $instances = []; /** * Register a factory that returns a new instance each resolve. * * @param string $id Service id (usually a class name). * @param Closure $factory Factory receiving the container. */ public function set( string $id, Closure $factory ): void { $this->factories[ $id ] = $factory; unset( $this->instances[ $id ] ); } /** * Register a singleton factory. * * @param string $id Service id. * @param Closure $factory Factory receiving the container. */ public function singleton( string $id, Closure $factory ): void { $this->set( $id, function ( self $c ) use ( $id, $factory ) { if ( ! array_key_exists( $id, $this->instances ) ) { $this->instances[ $id ] = $factory( $c ); } return $this->instances[ $id ]; } ); } /** * Whether a service is registered. * * @param string $id Service id. */ public function has( string $id ): bool { return isset( $this->factories[ $id ] ); } /** * Resolve a service. * * @param string $id Service id. * @return mixed * * @throws InvalidArgumentException When the id is unknown. * @throws RuntimeException When resolution fails. */ public function get( string $id ): mixed { if ( ! $this->has( $id ) ) { throw new InvalidArgumentException( sprintf( 'Bookline container has no service "%s".', esc_html( $id ) ) ); } try { return ( $this->factories[ $id ] )( $this ); } catch ( \Throwable $e ) { throw new RuntimeException( sprintf( 'Failed to resolve Bookline service "%s": %s', esc_html( $id ), esc_html( $e->getMessage() ) ), 0, $e ); } } }