File: /srv/www/event-csmcri/wp-content/plugins/wp-event-solution/base/Container/Container.php
<?php
namespace Eventin\Container;
use Eventin\Container\Exception\DependencyHasNoDefaultValueException;
use Eventin\Container\Exception\DependencyIsNotInstantiableException;
use Exception;
use ReflectionClass;
use ReflectionException;
use ReflectionParameter;
/**
* Container class
*
* @package Eventin\Base
*/
class Container {
protected $instances = [];
/**
* Finds an entry of the container by its identifier and returns it.
*
* @param string $id Identifier of the entry to look for.
*
* @throws NotFoundExceptionInterface No entry was found for **this** identifier.
* @throws ContainerExceptionInterface|ReflectionException Error while retrieving the entry.
*
* @return mixed Entry.
*/
public function get( string $id ): object {
if ( ! $this->has( $id ) ) {
$this->set( $id );
}
$instance = $this->instances[$id];
return $this->resolve( $instance );
}
/**
* Sets an entry of the container by its identifier
*
* @param string $id
* @param object|null $instance
*
* @return void
*/
public function set( string $id, mixed $instance = null ): void {
if ( $instance === null ) {
$instance = $id;
}
$this->instances[$id] = $instance;
}
/**
* Returns true if the container can return an entry for the given identifier.
* Returns false otherwise.
*
* `has($id)` returning true does not mean that `get($id)` will not throw an exception.
* It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
*
* @param string $id Identifier of the entry to look for.
*
* @return bool
*/
public function has( string $id ): bool {
return isset( $this->instances[$id] );
}
/**
* Resolves the service object by its name.
*
* @param string $class_name
*
* @throws DependencyHasNoDefaultValueException
* @throws DependencyIsNotInstantiableException
* @throws ReflectionException|Exception
*
* @return object
*/
public function resolve( string $class_name ): object {
if ( ! class_exists( $class_name ) ) {
throw new Exception( esc_html( "Class: {$class_name} does not exist" ) );
}
$reflection_class = new ReflectionClass( $class_name );
if ( ! $reflection_class->isInstantiable() ) {
throw new DependencyIsNotInstantiableException( esc_html( "Class: {$class_name} is not instantiable" ) );
}
if ( null === $reflection_class->getConstructor() ) {
return $reflection_class->newInstance();
}
$parameters = $reflection_class->getConstructor()->getParameters();
$dependencies = $this->build_dependencies( $parameters );
return $reflection_class->newInstanceArgs( $dependencies );
}
/**
* Builds the dependencies for the given parameters.
*
* @param ReflectionParameter[] $parameters
*
* @throws ReflectionException
* @throws DependencyHasNoDefaultValueException
*
* @return array
*/
public function build_dependencies( array $parameters ): array {
$dependencies = [];
foreach ( $parameters as $parameter ) {
$dependency = $parameter->getType() ? $parameter->getType()->getName() : null;
if ( is_null( $dependency ) ) {
if ( $parameter->isDefaultValueAvailable() ) {
$dependencies[] = $parameter->getDefaultValue();
} else {
throw new DependencyHasNoDefaultValueException( esc_html( "Class: {$parameter->name} dependency can not be resolved" ) );
}
} else {
$dependencies[] = $this->get( $dependency );
}
}
return $dependencies;
}
}