commit vendor
This commit is contained in:
73
vendor/laminas/laminas-servicemanager/src/AbstractFactory/ConfigAbstractFactory.php
vendored
Normal file
73
vendor/laminas/laminas-servicemanager/src/AbstractFactory/ConfigAbstractFactory.php
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\AbstractFactory;
|
||||
|
||||
use ArrayObject;
|
||||
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
|
||||
use Laminas\ServiceManager\Factory\AbstractFactoryInterface;
|
||||
|
||||
final class ConfigAbstractFactory implements AbstractFactoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Factory can create the service if there is a key for it in the config
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function canCreate(\Interop\Container\ContainerInterface $container, $requestedName)
|
||||
{
|
||||
if (! $container->has('config') || ! array_key_exists(self::class, $container->get('config'))) {
|
||||
return false;
|
||||
}
|
||||
$config = $container->get('config');
|
||||
$dependencies = $config[self::class];
|
||||
|
||||
return is_array($dependencies) && array_key_exists($requestedName, $dependencies);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function __invoke(\Interop\Container\ContainerInterface $container, $requestedName, array $options = null)
|
||||
{
|
||||
if (! $container->has('config')) {
|
||||
throw new ServiceNotCreatedException('Cannot find a config array in the container');
|
||||
}
|
||||
|
||||
$config = $container->get('config');
|
||||
|
||||
if (! (is_array($config) || $config instanceof ArrayObject)) {
|
||||
throw new ServiceNotCreatedException('Config must be an array or an instance of ArrayObject');
|
||||
}
|
||||
|
||||
if (! array_key_exists(self::class, $config)) {
|
||||
throw new ServiceNotCreatedException('Cannot find a `' . self::class . '` key in the config array');
|
||||
}
|
||||
|
||||
$dependencies = $config[self::class];
|
||||
|
||||
if (! is_array($dependencies)
|
||||
|| ! array_key_exists($requestedName, $dependencies)
|
||||
|| ! is_array($dependencies[$requestedName])
|
||||
) {
|
||||
throw new ServiceNotCreatedException('Dependencies config must exist and be an array');
|
||||
}
|
||||
|
||||
$serviceDependencies = $dependencies[$requestedName];
|
||||
|
||||
if ($serviceDependencies !== array_values(array_map('strval', $serviceDependencies))) {
|
||||
$problem = json_encode(array_map('gettype', $serviceDependencies));
|
||||
throw new ServiceNotCreatedException('Service message must be an array of strings, ' . $problem . ' given');
|
||||
}
|
||||
|
||||
$arguments = array_map([$container, 'get'], $serviceDependencies);
|
||||
|
||||
return new $requestedName(...$arguments);
|
||||
}
|
||||
}
|
||||
246
vendor/laminas/laminas-servicemanager/src/AbstractFactory/ReflectionBasedAbstractFactory.php
vendored
Normal file
246
vendor/laminas/laminas-servicemanager/src/AbstractFactory/ReflectionBasedAbstractFactory.php
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\AbstractFactory;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
|
||||
use Laminas\ServiceManager\Factory\AbstractFactoryInterface;
|
||||
use ReflectionClass;
|
||||
use ReflectionParameter;
|
||||
|
||||
/**
|
||||
* Reflection-based factory.
|
||||
*
|
||||
* To ease development, this factory may be used for classes with
|
||||
* type-hinted arguments that resolve to services in the application
|
||||
* container; this allows omitting the step of writing a factory for
|
||||
* each controller.
|
||||
*
|
||||
* You may use it as either an abstract factory:
|
||||
*
|
||||
* <code>
|
||||
* 'service_manager' => [
|
||||
* 'abstract_factories' => [
|
||||
* ReflectionBasedAbstractFactory::class,
|
||||
* ],
|
||||
* ],
|
||||
* </code>
|
||||
*
|
||||
* Or as a factory, mapping a class name to it:
|
||||
*
|
||||
* <code>
|
||||
* 'service_manager' => [
|
||||
* 'factories' => [
|
||||
* MyClassWithDependencies::class => ReflectionBasedAbstractFactory::class,
|
||||
* ],
|
||||
* ],
|
||||
* </code>
|
||||
*
|
||||
* The latter approach is more explicit, and also more performant.
|
||||
*
|
||||
* The factory has the following constraints/features:
|
||||
*
|
||||
* - A parameter named `$config` typehinted as an array will receive the
|
||||
* application "config" service (i.e., the merged configuration).
|
||||
* - Parameters type-hinted against array, but not named `$config` will
|
||||
* be injected with an empty array.
|
||||
* - Scalar parameters will result in an exception being thrown, unless
|
||||
* a default value is present; if the default is present, that will be used.
|
||||
* - If a service cannot be found for a given typehint, the factory will
|
||||
* raise an exception detailing this.
|
||||
* - Some services provided by Laminas components do not have
|
||||
* entries based on their class name (for historical reasons); the
|
||||
* factory allows defining a map of these class/interface names to the
|
||||
* corresponding service name to allow them to resolve.
|
||||
*
|
||||
* `$options` passed to the factory are ignored in all cases, as we cannot
|
||||
* make assumptions about which argument(s) they might replace.
|
||||
*
|
||||
* Based on the LazyControllerAbstractFactory from laminas-mvc.
|
||||
*/
|
||||
class ReflectionBasedAbstractFactory implements AbstractFactoryInterface
|
||||
{
|
||||
/**
|
||||
* Maps known classes/interfaces to the service that provides them; only
|
||||
* required for those services with no entry based on the class/interface
|
||||
* name.
|
||||
*
|
||||
* Extend the class if you wish to add to the list.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* <code>
|
||||
* [
|
||||
* \Laminas\Filter\FilterPluginManager::class => 'FilterManager',
|
||||
* \Laminas\Validator\ValidatorPluginManager::class => 'ValidatorManager',
|
||||
* ]
|
||||
* </code>
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $aliases = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Allows overriding the internal list of aliases. These should be of the
|
||||
* form `class name => well-known service name`; see the documentation for
|
||||
* the `$aliases` property for details on what is accepted.
|
||||
*
|
||||
* @param string[] $aliases
|
||||
*/
|
||||
public function __construct(array $aliases = [])
|
||||
{
|
||||
if (! empty($aliases)) {
|
||||
$this->aliases = $aliases;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return DispatchableInterface
|
||||
*/
|
||||
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
|
||||
{
|
||||
$reflectionClass = new ReflectionClass($requestedName);
|
||||
|
||||
if (null === ($constructor = $reflectionClass->getConstructor())) {
|
||||
return new $requestedName();
|
||||
}
|
||||
|
||||
$reflectionParameters = $constructor->getParameters();
|
||||
|
||||
if (empty($reflectionParameters)) {
|
||||
return new $requestedName();
|
||||
}
|
||||
|
||||
$resolver = $container->has('config')
|
||||
? $this->resolveParameterWithConfigService($container, $requestedName)
|
||||
: $this->resolveParameterWithoutConfigService($container, $requestedName);
|
||||
|
||||
$parameters = array_map($resolver, $reflectionParameters);
|
||||
|
||||
return new $requestedName(...$parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function canCreate(ContainerInterface $container, $requestedName)
|
||||
{
|
||||
return class_exists($requestedName) && $this->canCallConstructor($requestedName);
|
||||
}
|
||||
|
||||
private function canCallConstructor($requestedName)
|
||||
{
|
||||
$constructor = (new ReflectionClass($requestedName))->getConstructor();
|
||||
|
||||
return $constructor === null || $constructor->isPublic();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a parameter to a value.
|
||||
*
|
||||
* Returns a callback for resolving a parameter to a value, but without
|
||||
* allowing mapping array `$config` arguments to the `config` service.
|
||||
*
|
||||
* @param ContainerInterface $container
|
||||
* @param string $requestedName
|
||||
* @return callable
|
||||
*/
|
||||
private function resolveParameterWithoutConfigService(ContainerInterface $container, $requestedName)
|
||||
{
|
||||
/**
|
||||
* @param ReflectionParameter $parameter
|
||||
* @return mixed
|
||||
* @throws ServiceNotFoundException If type-hinted parameter cannot be
|
||||
* resolved to a service in the container.
|
||||
*/
|
||||
return function (ReflectionParameter $parameter) use ($container, $requestedName) {
|
||||
return $this->resolveParameter($parameter, $container, $requestedName);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a callback for resolving a parameter to a value, including mapping 'config' arguments.
|
||||
*
|
||||
* Unlike resolveParameter(), this version will detect `$config` array
|
||||
* arguments and have them return the 'config' service.
|
||||
*
|
||||
* @param ContainerInterface $container
|
||||
* @param string $requestedName
|
||||
* @return callable
|
||||
*/
|
||||
private function resolveParameterWithConfigService(ContainerInterface $container, $requestedName)
|
||||
{
|
||||
/**
|
||||
* @param ReflectionParameter $parameter
|
||||
* @return mixed
|
||||
* @throws ServiceNotFoundException If type-hinted parameter cannot be
|
||||
* resolved to a service in the container.
|
||||
*/
|
||||
return function (ReflectionParameter $parameter) use ($container, $requestedName) {
|
||||
if ($parameter->isArray() && $parameter->getName() === 'config') {
|
||||
return $container->get('config');
|
||||
}
|
||||
return $this->resolveParameter($parameter, $container, $requestedName);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Logic common to all parameter resolution.
|
||||
*
|
||||
* @param ReflectionParameter $parameter
|
||||
* @param ContainerInterface $container
|
||||
* @param string $requestedName
|
||||
* @return mixed
|
||||
* @throws ServiceNotFoundException If type-hinted parameter cannot be
|
||||
* resolved to a service in the container.
|
||||
*/
|
||||
private function resolveParameter(ReflectionParameter $parameter, ContainerInterface $container, $requestedName)
|
||||
{
|
||||
if ($parameter->isArray()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (! $parameter->getClass()) {
|
||||
if (! $parameter->isDefaultValueAvailable()) {
|
||||
throw new ServiceNotFoundException(sprintf(
|
||||
'Unable to create service "%s"; unable to resolve parameter "%s" '
|
||||
. 'to a class, interface, or array type',
|
||||
$requestedName,
|
||||
$parameter->getName()
|
||||
));
|
||||
}
|
||||
|
||||
return $parameter->getDefaultValue();
|
||||
}
|
||||
|
||||
$type = $parameter->getClass()->getName();
|
||||
$type = isset($this->aliases[$type]) ? $this->aliases[$type] : $type;
|
||||
|
||||
if ($container->has($type)) {
|
||||
return $container->get($type);
|
||||
}
|
||||
|
||||
if (! $parameter->isOptional()) {
|
||||
throw new ServiceNotFoundException(sprintf(
|
||||
'Unable to create service "%s"; unable to resolve parameter "%s" using type hint "%s"',
|
||||
$requestedName,
|
||||
$parameter->getName(),
|
||||
$type
|
||||
));
|
||||
}
|
||||
|
||||
// Type not available in container, but the value is optional and has a
|
||||
// default defined.
|
||||
return $parameter->getDefaultValue();
|
||||
}
|
||||
}
|
||||
59
vendor/laminas/laminas-servicemanager/src/AbstractFactoryInterface.php
vendored
Normal file
59
vendor/laminas/laminas-servicemanager/src/AbstractFactoryInterface.php
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager;
|
||||
|
||||
/**
|
||||
* Backwards-compatibility shim for AbstractFactoryInterface.
|
||||
*
|
||||
* Implementations should update to implement only Laminas\ServiceManager\Factory\AbstractFactoryInterface.
|
||||
*
|
||||
* If upgrading from v2, take the following steps:
|
||||
*
|
||||
* - rename the method `canCreateServiceWithName()` to `canCreate()`, and:
|
||||
* - rename the `$serviceLocator` argument to `$container`, and change the
|
||||
* typehint to `Interop\Container\ContainerInterface`
|
||||
* - merge the `$name` and `$requestedName` arguments
|
||||
* - rename the method `createServiceWithName()` to `__invoke()`, and:
|
||||
* - rename the `$serviceLocator` argument to `$container`, and change the
|
||||
* typehint to `Interop\Container\ContainerInterface`
|
||||
* - merge the `$name` and `$requestedName` arguments
|
||||
* - add the optional `array $options = null` argument.
|
||||
* - create a `canCreateServiceWithName()` method as defined in this interface, and have it
|
||||
* proxy to `canCreate()`, passing `$requestedName` as the second argument.
|
||||
* - create a `createServiceWithName()` method as defined in this interface, and have it
|
||||
* proxy to `__invoke()`, passing `$requestedName` as the second argument.
|
||||
*
|
||||
* Once you have tested your code, you can then update your class to only implement
|
||||
* Laminas\ServiceManager\Factory\AbstractFactoryInterface, and remove the `canCreateServiceWithName()`
|
||||
* and `createServiceWithName()` methods.
|
||||
*
|
||||
* @deprecated Use Laminas\ServiceManager\Factory\AbstractFactoryInterface instead.
|
||||
*/
|
||||
interface AbstractFactoryInterface extends Factory\AbstractFactoryInterface
|
||||
{
|
||||
/**
|
||||
* Determine if we can create a service with name
|
||||
*
|
||||
* @param ServiceLocatorInterface $serviceLocator
|
||||
* @param $name
|
||||
* @param $requestedName
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName);
|
||||
|
||||
/**
|
||||
* Create service with name
|
||||
*
|
||||
* @param ServiceLocatorInterface $serviceLocator
|
||||
* @param $name
|
||||
* @param $requestedName
|
||||
* @return mixed
|
||||
*/
|
||||
public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName);
|
||||
}
|
||||
202
vendor/laminas/laminas-servicemanager/src/AbstractPluginManager.php
vendored
Normal file
202
vendor/laminas/laminas-servicemanager/src/AbstractPluginManager.php
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Laminas\ServiceManager\Exception\InvalidServiceException;
|
||||
use Psr\Container\ContainerInterface as PsrContainerInterface;
|
||||
|
||||
/**
|
||||
* Abstract plugin manager.
|
||||
*
|
||||
* Abstract PluginManagerInterface implementation providing:
|
||||
*
|
||||
* - creation context support. The constructor accepts the parent container
|
||||
* instance, which is then used when creating instances.
|
||||
* - plugin validation. Implementations may define the `$instanceOf` property
|
||||
* to indicate what class types constitute valid plugins, omitting the
|
||||
* requirement to define the `validate()` method.
|
||||
*
|
||||
* The implementation extends `ServiceManager`, thus providing the same set
|
||||
* of capabilities as found in that implementation.
|
||||
*/
|
||||
abstract class AbstractPluginManager extends ServiceManager implements PluginManagerInterface
|
||||
{
|
||||
/**
|
||||
* Whether or not to auto-add a FQCN as an invokable if it exists.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoAddInvokableClass = true;
|
||||
|
||||
/**
|
||||
* An object type that the created instance must be instanced of
|
||||
*
|
||||
* @var null|string
|
||||
*/
|
||||
protected $instanceOf = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Sets the provided $parentLocator as the creation context for all
|
||||
* factories; for $config, {@see \Laminas\ServiceManager\ServiceManager::configure()}
|
||||
* for details on its accepted structure.
|
||||
*
|
||||
* @param null|ConfigInterface|ContainerInterface|PsrContainerInterface $configInstanceOrParentLocator
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct($configInstanceOrParentLocator = null, array $config = [])
|
||||
{
|
||||
if ($configInstanceOrParentLocator instanceof PsrContainerInterface
|
||||
&& ! $configInstanceOrParentLocator instanceof ContainerInterface
|
||||
) {
|
||||
/**
|
||||
* {@see \Laminas\ServiceManager\Factory\FactoryInterface} typehints
|
||||
* against interop container and as such cannot accept non-interop
|
||||
* psr container. Decorate it as interop.
|
||||
*/
|
||||
$configInstanceOrParentLocator = new PsrContainerDecorator($configInstanceOrParentLocator);
|
||||
}
|
||||
if (null !== $configInstanceOrParentLocator
|
||||
&& ! $configInstanceOrParentLocator instanceof ConfigInterface
|
||||
&& ! $configInstanceOrParentLocator instanceof ContainerInterface
|
||||
) {
|
||||
throw new Exception\InvalidArgumentException(sprintf(
|
||||
'%s expects a ConfigInterface or ContainerInterface instance as the first argument; received %s',
|
||||
__CLASS__,
|
||||
(is_object($configInstanceOrParentLocator)
|
||||
? get_class($configInstanceOrParentLocator)
|
||||
: gettype($configInstanceOrParentLocator)
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
if ($configInstanceOrParentLocator instanceof ConfigInterface) {
|
||||
trigger_error(sprintf(
|
||||
'Usage of %s as a constructor argument for %s is now deprecated',
|
||||
ConfigInterface::class,
|
||||
get_class($this)
|
||||
), E_USER_DEPRECATED);
|
||||
$config = $configInstanceOrParentLocator->toArray();
|
||||
}
|
||||
|
||||
parent::__construct($config);
|
||||
|
||||
if (! $configInstanceOrParentLocator instanceof ContainerInterface) {
|
||||
trigger_error(sprintf(
|
||||
'%s now expects a %s instance representing the parent container; please update your code',
|
||||
__METHOD__,
|
||||
ContainerInterface::class
|
||||
), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->creationContext = $configInstanceOrParentLocator instanceof ContainerInterface
|
||||
? $configInstanceOrParentLocator
|
||||
: $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override configure() to validate service instances.
|
||||
*
|
||||
* If an instance passed in the `services` configuration is invalid for the
|
||||
* plugin manager, this method will raise an InvalidServiceException.
|
||||
*
|
||||
* {@inheritDoc}
|
||||
* @throws InvalidServiceException
|
||||
*/
|
||||
public function configure(array $config)
|
||||
{
|
||||
if (isset($config['services'])) {
|
||||
foreach ($config['services'] as $service) {
|
||||
$this->validate($service);
|
||||
}
|
||||
}
|
||||
|
||||
parent::configure($config);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param string $name Service name of plugin to retrieve.
|
||||
* @param null|array $options Options to use when creating the instance.
|
||||
* @return mixed
|
||||
* @throws Exception\ServiceNotFoundException if the manager does not have
|
||||
* a service definition for the instance, and the service is not
|
||||
* auto-invokable.
|
||||
* @throws InvalidServiceException if the plugin created is invalid for the
|
||||
* plugin context.
|
||||
*/
|
||||
public function get($name, array $options = null)
|
||||
{
|
||||
if (! $this->has($name)) {
|
||||
if (! $this->autoAddInvokableClass || ! class_exists($name)) {
|
||||
throw new Exception\ServiceNotFoundException(sprintf(
|
||||
'A plugin by the name "%s" was not found in the plugin manager %s',
|
||||
$name,
|
||||
get_class($this)
|
||||
));
|
||||
}
|
||||
|
||||
$this->setFactory($name, Factory\InvokableFactory::class);
|
||||
}
|
||||
|
||||
$instance = empty($options) ? parent::get($name) : $this->build($name, $options);
|
||||
$this->validate($instance);
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function validate($instance)
|
||||
{
|
||||
if (method_exists($this, 'validatePlugin')) {
|
||||
trigger_error(sprintf(
|
||||
'%s::validatePlugin() has been deprecated as of 3.0; please define validate() instead',
|
||||
get_class($this)
|
||||
), E_USER_DEPRECATED);
|
||||
$this->validatePlugin($instance);
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($this->instanceOf) || $instance instanceof $this->instanceOf) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidServiceException(sprintf(
|
||||
'Plugin manager "%s" expected an instance of type "%s", but "%s" was received',
|
||||
__CLASS__,
|
||||
$this->instanceOf,
|
||||
is_object($instance) ? get_class($instance) : gettype($instance)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implemented for backwards compatibility only.
|
||||
*
|
||||
* Returns the creation context.
|
||||
*
|
||||
* @deprecated since 3.0.0. The creation context should be passed during
|
||||
* instantiation instead.
|
||||
* @param ContainerInterface $container
|
||||
* @return void
|
||||
*/
|
||||
public function setServiceLocator(ContainerInterface $container)
|
||||
{
|
||||
trigger_error(sprintf(
|
||||
'Usage of %s is deprecated since v3.0.0; please pass the container to the constructor instead',
|
||||
__METHOD__
|
||||
), E_USER_DEPRECATED);
|
||||
$this->creationContext = $container;
|
||||
}
|
||||
}
|
||||
120
vendor/laminas/laminas-servicemanager/src/Config.php
vendored
Normal file
120
vendor/laminas/laminas-servicemanager/src/Config.php
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager;
|
||||
|
||||
use Laminas\Stdlib\ArrayUtils\MergeRemoveKey;
|
||||
use Laminas\Stdlib\ArrayUtils\MergeReplaceKeyInterface;
|
||||
|
||||
/**
|
||||
* Object for defining configuration and configuring an existing service manager instance.
|
||||
*
|
||||
* In order to provide configuration merging capabilities, this class implements
|
||||
* the same functionality as `Laminas\Stdlib\ArrayUtils::merge()`. That routine
|
||||
* allows developers to specifically shape how values are merged:
|
||||
*
|
||||
* - A value which is an instance of `MergeRemoveKey` indicates the value should
|
||||
* be removed during merge.
|
||||
* - A value that is an instance of `MergeReplaceKeyInterface` indicates that the
|
||||
* value it contains should be used to replace any previous versions.
|
||||
*
|
||||
* These features are advanced, and not typically used. If you wish to use them,
|
||||
* you will need to require the laminas-stdlib package in your application.
|
||||
*/
|
||||
class Config implements ConfigInterface
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $allowedKeys = [
|
||||
'abstract_factories' => true,
|
||||
'aliases' => true,
|
||||
'delegators' => true,
|
||||
'factories' => true,
|
||||
'initializers' => true,
|
||||
'invokables' => true,
|
||||
'lazy_services' => true,
|
||||
'services' => true,
|
||||
'shared' => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config = [
|
||||
'abstract_factories' => [],
|
||||
'aliases' => [],
|
||||
'delegators' => [],
|
||||
'factories' => [],
|
||||
'initializers' => [],
|
||||
'invokables' => [],
|
||||
'lazy_services' => [],
|
||||
'services' => [],
|
||||
'shared' => [],
|
||||
];
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
// Only merge keys we're interested in
|
||||
foreach (array_keys($config) as $key) {
|
||||
if (! isset($this->allowedKeys[$key])) {
|
||||
unset($config[$key]);
|
||||
}
|
||||
}
|
||||
$this->config = $this->merge($this->config, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function configureServiceManager(ServiceManager $serviceManager)
|
||||
{
|
||||
return $serviceManager->configure($this->config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy paste from https://github.com/laminas/laminas-stdlib/commit/26fcc32a358aa08de35625736095cb2fdaced090
|
||||
* to keep compatibility with previous version
|
||||
*
|
||||
* @link https://github.com/zendframework/zend-servicemanager/pull/68
|
||||
*/
|
||||
private function merge(array $a, array $b)
|
||||
{
|
||||
foreach ($b as $key => $value) {
|
||||
if ($value instanceof MergeReplaceKeyInterface) {
|
||||
$a[$key] = $value->getData();
|
||||
} elseif (isset($a[$key]) || array_key_exists($key, $a)) {
|
||||
if ($value instanceof MergeRemoveKey) {
|
||||
unset($a[$key]);
|
||||
} elseif (is_int($key)) {
|
||||
$a[] = $value;
|
||||
} elseif (is_array($value) && is_array($a[$key])) {
|
||||
$a[$key] = $this->merge($a[$key], $value);
|
||||
} else {
|
||||
$a[$key] = $value;
|
||||
}
|
||||
} else {
|
||||
if (! $value instanceof MergeRemoveKey) {
|
||||
$a[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $a;
|
||||
}
|
||||
}
|
||||
47
vendor/laminas/laminas-servicemanager/src/ConfigInterface.php
vendored
Normal file
47
vendor/laminas/laminas-servicemanager/src/ConfigInterface.php
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager;
|
||||
|
||||
interface ConfigInterface
|
||||
{
|
||||
/**
|
||||
* Configure a service manager.
|
||||
*
|
||||
* Implementations should pull configuration from somewhere (typically
|
||||
* local properties) and pass it to a ServiceManager's withConfig() method,
|
||||
* returning a new instance.
|
||||
*
|
||||
* @param ServiceManager $serviceManager
|
||||
* @return ServiceManager
|
||||
*/
|
||||
public function configureServiceManager(ServiceManager $serviceManager);
|
||||
|
||||
/**
|
||||
* Return configuration for a service manager instance as an array.
|
||||
*
|
||||
* Implementations MUST return an array compatible with ServiceManager::configure,
|
||||
* containing one or more of the following keys:
|
||||
*
|
||||
* - abstract_factories
|
||||
* - aliases
|
||||
* - delegators
|
||||
* - factories
|
||||
* - initializers
|
||||
* - invokables
|
||||
* - lazy_services
|
||||
* - services
|
||||
* - shared
|
||||
*
|
||||
* In other words, this should return configuration that can be used to instantiate
|
||||
* a service manager or plugin manager, or pass to its `withConfig()` method.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray();
|
||||
}
|
||||
46
vendor/laminas/laminas-servicemanager/src/DelegatorFactoryInterface.php
vendored
Normal file
46
vendor/laminas/laminas-servicemanager/src/DelegatorFactoryInterface.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager;
|
||||
|
||||
/**
|
||||
* Backwards-compatibility shim for DelegatorFactoryInterface.
|
||||
*
|
||||
* Implementations should update to implement only Laminas\ServiceManager\Factory\DelegatorFactoryInterface.
|
||||
*
|
||||
* If upgrading from v2, take the following steps:
|
||||
*
|
||||
* - rename the method `createDelegatorWithName()` to `__invoke()`, and:
|
||||
* - rename the `$serviceLocator` argument to `$container`, and change the
|
||||
* typehint to `Interop\Container\ContainerInterface`
|
||||
* - merge the `$name` and `$requestedName` arguments
|
||||
* - add the `callable` typehint to the `$callback` argument
|
||||
* - add the optional `array $options = null` argument as a final argument
|
||||
* - create a `createDelegatorWithName()` method as defined in this interface, and have it
|
||||
* proxy to `__invoke()`, passing `$requestedName` as the second argument.
|
||||
*
|
||||
* Once you have tested your code, you can then update your class to only implement
|
||||
* Laminas\ServiceManager\Factory\DelegatorFactoryInterface, and remove the `createDelegatorWithName()`
|
||||
* method.
|
||||
*
|
||||
* @deprecated Use Laminas\ServiceManager\Factory\DelegatorFactoryInterface instead.
|
||||
*/
|
||||
interface DelegatorFactoryInterface extends Factory\DelegatorFactoryInterface
|
||||
{
|
||||
/**
|
||||
* A factory that creates delegates of a given service
|
||||
*
|
||||
* @param ServiceLocatorInterface $serviceLocator the service locator which requested the service
|
||||
* @param string $name the normalized service name
|
||||
* @param string $requestedName the requested service name
|
||||
* @param callable $callback the callback that is responsible for creating the service
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback);
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Exception;
|
||||
|
||||
use DomainException;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
class ContainerModificationsNotAllowedException extends DomainException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
138
vendor/laminas/laminas-servicemanager/src/Exception/CyclicAliasException.php
vendored
Normal file
138
vendor/laminas/laminas-servicemanager/src/Exception/CyclicAliasException.php
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Exception;
|
||||
|
||||
class CyclicAliasException extends InvalidArgumentException
|
||||
{
|
||||
/**
|
||||
* @param string[] $aliases map of referenced services, indexed by alias name (string)
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function fromAliasesMap(array $aliases)
|
||||
{
|
||||
$detectedCycles = array_filter(array_map(
|
||||
function ($alias) use ($aliases) {
|
||||
return self::getCycleFor($aliases, $alias);
|
||||
},
|
||||
array_keys($aliases)
|
||||
));
|
||||
|
||||
if (! $detectedCycles) {
|
||||
return new self(sprintf(
|
||||
"A cycle was detected within the following aliases map:\n\n%s",
|
||||
self::printReferencesMap($aliases)
|
||||
));
|
||||
}
|
||||
|
||||
return new self(sprintf(
|
||||
"Cycles were detected within the provided aliases:\n\n%s\n\n"
|
||||
. "The cycle was detected in the following alias map:\n\n%s",
|
||||
self::printCycles(self::deDuplicateDetectedCycles($detectedCycles)),
|
||||
self::printReferencesMap($aliases)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the cycle detected for the given $alias, or `null` if no cycle was detected
|
||||
*
|
||||
* @param string[] $aliases
|
||||
* @param string $alias
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
private static function getCycleFor(array $aliases, $alias)
|
||||
{
|
||||
$cycleCandidate = [];
|
||||
$targetName = $alias;
|
||||
|
||||
while (isset($aliases[$targetName])) {
|
||||
if (isset($cycleCandidate[$targetName])) {
|
||||
return $cycleCandidate;
|
||||
}
|
||||
|
||||
$cycleCandidate[$targetName] = true;
|
||||
|
||||
$targetName = $aliases[$targetName];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $aliases
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function printReferencesMap(array $aliases)
|
||||
{
|
||||
$map = [];
|
||||
|
||||
foreach ($aliases as $alias => $reference) {
|
||||
$map[] = '"' . $alias . '" => "' . $reference . '"';
|
||||
}
|
||||
|
||||
return "[\n" . implode("\n", $map) . "\n]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[][] $detectedCycles
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function printCycles(array $detectedCycles)
|
||||
{
|
||||
return "[\n" . implode("\n", array_map([__CLASS__, 'printCycle'], $detectedCycles)) . "\n]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $detectedCycle
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function printCycle(array $detectedCycle)
|
||||
{
|
||||
$fullCycle = array_keys($detectedCycle);
|
||||
$fullCycle[] = reset($fullCycle);
|
||||
|
||||
return implode(
|
||||
' => ',
|
||||
array_map(
|
||||
function ($cycle) {
|
||||
return '"' . $cycle . '"';
|
||||
},
|
||||
$fullCycle
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool[][] $detectedCycles
|
||||
*
|
||||
* @return bool[][] de-duplicated
|
||||
*/
|
||||
private static function deDuplicateDetectedCycles(array $detectedCycles)
|
||||
{
|
||||
$detectedCyclesByHash = [];
|
||||
|
||||
foreach ($detectedCycles as $detectedCycle) {
|
||||
$cycleAliases = array_keys($detectedCycle);
|
||||
|
||||
sort($cycleAliases);
|
||||
|
||||
$hash = serialize(array_values($cycleAliases));
|
||||
|
||||
$detectedCyclesByHash[$hash] = isset($detectedCyclesByHash[$hash])
|
||||
? $detectedCyclesByHash[$hash]
|
||||
: $detectedCycle;
|
||||
}
|
||||
|
||||
return array_values($detectedCyclesByHash);
|
||||
}
|
||||
}
|
||||
18
vendor/laminas/laminas-servicemanager/src/Exception/ExceptionInterface.php
vendored
Normal file
18
vendor/laminas/laminas-servicemanager/src/Exception/ExceptionInterface.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Exception;
|
||||
|
||||
use Interop\Container\Exception\ContainerException;
|
||||
|
||||
/**
|
||||
* Base exception for all Laminas\ServiceManager exceptions.
|
||||
*/
|
||||
interface ExceptionInterface extends ContainerException
|
||||
{
|
||||
}
|
||||
18
vendor/laminas/laminas-servicemanager/src/Exception/InvalidArgumentException.php
vendored
Normal file
18
vendor/laminas/laminas-servicemanager/src/Exception/InvalidArgumentException.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Exception;
|
||||
|
||||
use InvalidArgumentException as SplInvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
class InvalidArgumentException extends SplInvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
19
vendor/laminas/laminas-servicemanager/src/Exception/InvalidServiceException.php
vendored
Normal file
19
vendor/laminas/laminas-servicemanager/src/Exception/InvalidServiceException.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Exception;
|
||||
|
||||
use RuntimeException as SplRuntimeException;
|
||||
|
||||
/**
|
||||
* This exception is thrown by plugin managers when the created object does not match
|
||||
* the plugin manager's conditions
|
||||
*/
|
||||
class InvalidServiceException extends SplRuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
22
vendor/laminas/laminas-servicemanager/src/Exception/ServiceNotCreatedException.php
vendored
Normal file
22
vendor/laminas/laminas-servicemanager/src/Exception/ServiceNotCreatedException.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Exception;
|
||||
|
||||
use Interop\Container\Exception\ContainerException;
|
||||
use RuntimeException as SplRuntimeException;
|
||||
|
||||
/**
|
||||
* This exception is thrown when the service locator do not manage to create
|
||||
* the service (factory that has an error...)
|
||||
*/
|
||||
class ServiceNotCreatedException extends SplRuntimeException implements
|
||||
ContainerException,
|
||||
ExceptionInterface
|
||||
{
|
||||
}
|
||||
22
vendor/laminas/laminas-servicemanager/src/Exception/ServiceNotFoundException.php
vendored
Normal file
22
vendor/laminas/laminas-servicemanager/src/Exception/ServiceNotFoundException.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Exception;
|
||||
|
||||
use Interop\Container\Exception\NotFoundException;
|
||||
use InvalidArgumentException as SplInvalidArgumentException;
|
||||
|
||||
/**
|
||||
* This exception is thrown when the service locator do not manage to find a
|
||||
* valid factory to create a service
|
||||
*/
|
||||
class ServiceNotFoundException extends SplInvalidArgumentException implements
|
||||
ExceptionInterface,
|
||||
NotFoundException
|
||||
{
|
||||
}
|
||||
33
vendor/laminas/laminas-servicemanager/src/Factory/AbstractFactoryInterface.php
vendored
Normal file
33
vendor/laminas/laminas-servicemanager/src/Factory/AbstractFactoryInterface.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Factory;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Interface for an abstract factory.
|
||||
*
|
||||
* An abstract factory extends the factory interface, but also has an
|
||||
* additional "canCreate" method, which is called to check if the abstract
|
||||
* factory has the ability to create an instance for the given service. You
|
||||
* should limit the number of abstract factories to ensure good performance.
|
||||
* Starting from ServiceManager v3, remember that you can also attach multiple
|
||||
* names to the same factory, which reduces the need for abstract factories.
|
||||
*/
|
||||
interface AbstractFactoryInterface extends FactoryInterface
|
||||
{
|
||||
/**
|
||||
* Can the factory create an instance for the service?
|
||||
*
|
||||
* @param ContainerInterface $container
|
||||
* @param string $requestedName
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreate(ContainerInterface $container, $requestedName);
|
||||
}
|
||||
40
vendor/laminas/laminas-servicemanager/src/Factory/DelegatorFactoryInterface.php
vendored
Normal file
40
vendor/laminas/laminas-servicemanager/src/Factory/DelegatorFactoryInterface.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Factory;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Interop\Container\Exception\ContainerException;
|
||||
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
|
||||
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
|
||||
|
||||
/**
|
||||
* Delegator factory interface.
|
||||
*
|
||||
* Defines the capabilities required by a delegator factory. Delegator
|
||||
* factories are used to either decorate a service instance, or to allow
|
||||
* decorating the instantiation of a service instance (for instance, to
|
||||
* provide optional dependencies via setters, etc.).
|
||||
*/
|
||||
interface DelegatorFactoryInterface
|
||||
{
|
||||
/**
|
||||
* A factory that creates delegates of a given service
|
||||
*
|
||||
* @param ContainerInterface $container
|
||||
* @param string $name
|
||||
* @param callable $callback
|
||||
* @param null|array $options
|
||||
* @return object
|
||||
* @throws ServiceNotFoundException if unable to resolve the service.
|
||||
* @throws ServiceNotCreatedException if an exception is raised when
|
||||
* creating a service.
|
||||
* @throws ContainerException if any other error occurs
|
||||
*/
|
||||
public function __invoke(ContainerInterface $container, $name, callable $callback, array $options = null);
|
||||
}
|
||||
39
vendor/laminas/laminas-servicemanager/src/Factory/FactoryInterface.php
vendored
Normal file
39
vendor/laminas/laminas-servicemanager/src/Factory/FactoryInterface.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Factory;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Interop\Container\Exception\ContainerException;
|
||||
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
|
||||
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
|
||||
|
||||
/**
|
||||
* Interface for a factory
|
||||
*
|
||||
* A factory is an callable object that is able to create an object. It is
|
||||
* given the instance of the service locator, the requested name of the class
|
||||
* you want to create, and any additional options that could be used to
|
||||
* configure the instance state.
|
||||
*/
|
||||
interface FactoryInterface
|
||||
{
|
||||
/**
|
||||
* Create an object
|
||||
*
|
||||
* @param ContainerInterface $container
|
||||
* @param string $requestedName
|
||||
* @param null|array $options
|
||||
* @return object
|
||||
* @throws ServiceNotFoundException if unable to resolve the service.
|
||||
* @throws ServiceNotCreatedException if an exception is raised when
|
||||
* creating a service.
|
||||
* @throws ContainerException if any other error occurs
|
||||
*/
|
||||
public function __invoke(ContainerInterface $container, $requestedName, array $options = null);
|
||||
}
|
||||
33
vendor/laminas/laminas-servicemanager/src/Factory/InvokableFactory.php
vendored
Normal file
33
vendor/laminas/laminas-servicemanager/src/Factory/InvokableFactory.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Factory;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Factory for instantiating classes with no dependencies or which accept a single array.
|
||||
*
|
||||
* The InvokableFactory can be used for any class that:
|
||||
*
|
||||
* - has no constructor arguments;
|
||||
* - accepts a single array of arguments via the constructor.
|
||||
*
|
||||
* It replaces the "invokables" and "invokable class" functionality of the v2
|
||||
* service manager.
|
||||
*/
|
||||
final class InvokableFactory implements FactoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
|
||||
{
|
||||
return (null === $options) ? new $requestedName : new $requestedName($options);
|
||||
}
|
||||
}
|
||||
41
vendor/laminas/laminas-servicemanager/src/FactoryInterface.php
vendored
Normal file
41
vendor/laminas/laminas-servicemanager/src/FactoryInterface.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager;
|
||||
|
||||
/**
|
||||
* Backwards-compatibility shim for FactoryInterface.
|
||||
*
|
||||
* Implementations should update to implement only Laminas\ServiceManager\Factory\FactoryInterface.
|
||||
*
|
||||
* If upgrading from v2, take the following steps:
|
||||
*
|
||||
* - rename the method `createService()` to `__invoke()`, and:
|
||||
* - rename the `$serviceLocator` argument to `$container`, and change the
|
||||
* typehint to `Interop\Container\ContainerInterface`
|
||||
* - add the `$requestedName` as a second argument
|
||||
* - add the optional `array $options = null` argument as a final argument
|
||||
* - create a `createService()` method as defined in this interface, and have it
|
||||
* proxy to `__invoke()`.
|
||||
*
|
||||
* Once you have tested your code, you can then update your class to only implement
|
||||
* Laminas\ServiceManager\Factory\FactoryInterface, and remove the `createService()`
|
||||
* method.
|
||||
*
|
||||
* @deprecated Use Laminas\ServiceManager\Factory\FactoryInterface instead.
|
||||
*/
|
||||
interface FactoryInterface extends Factory\FactoryInterface
|
||||
{
|
||||
/**
|
||||
* Create service
|
||||
*
|
||||
* @param ServiceLocatorInterface $serviceLocator
|
||||
* @return mixed
|
||||
*/
|
||||
public function createService(ServiceLocatorInterface $serviceLocator);
|
||||
}
|
||||
29
vendor/laminas/laminas-servicemanager/src/Initializer/InitializerInterface.php
vendored
Normal file
29
vendor/laminas/laminas-servicemanager/src/Initializer/InitializerInterface.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Initializer;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Interface for an initializer
|
||||
*
|
||||
* An initializer can be registered to a service locator, and are run after an instance is created
|
||||
* to inject additional dependencies through setters
|
||||
*/
|
||||
interface InitializerInterface
|
||||
{
|
||||
/**
|
||||
* Initialize the given instance
|
||||
*
|
||||
* @param ContainerInterface $container
|
||||
* @param object $instance
|
||||
* @return void
|
||||
*/
|
||||
public function __invoke(ContainerInterface $container, $instance);
|
||||
}
|
||||
41
vendor/laminas/laminas-servicemanager/src/InitializerInterface.php
vendored
Normal file
41
vendor/laminas/laminas-servicemanager/src/InitializerInterface.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager;
|
||||
|
||||
/**
|
||||
* Backwards-compatibility shim for InitializerInterface.
|
||||
*
|
||||
* Implementations should update to implement only Laminas\ServiceManager\Initializer\InitializerInterface.
|
||||
*
|
||||
* If upgrading from v2, take the following steps:
|
||||
*
|
||||
* - rename the method `initialize()` to `__invoke()`, and:
|
||||
* - rename the `$serviceLocator` argument to `$container`, and change the
|
||||
* typehint to `Interop\Container\ContainerInterface`
|
||||
* - swap the order of the arguments (so that `$instance` comes second)
|
||||
* - create an `initialize()` method as defined in this interface, and have it
|
||||
* proxy to `__invoke()`, passing the arguments in the new order.
|
||||
*
|
||||
* Once you have tested your code, you can then update your class to only implement
|
||||
* Laminas\ServiceManager\Initializer\InitializerInterface, and remove the `initialize()`
|
||||
* method.
|
||||
*
|
||||
* @deprecated Use Laminas\ServiceManager\Initializer\InitializerInterface instead.
|
||||
*/
|
||||
interface InitializerInterface extends Initializer\InitializerInterface
|
||||
{
|
||||
/**
|
||||
* Initialize
|
||||
*
|
||||
* @param $instance
|
||||
* @param ServiceLocatorInterface $serviceLocator
|
||||
* @return mixed
|
||||
*/
|
||||
public function initialize($instance, ServiceLocatorInterface $serviceLocator);
|
||||
}
|
||||
31
vendor/laminas/laminas-servicemanager/src/PluginManagerInterface.php
vendored
Normal file
31
vendor/laminas/laminas-servicemanager/src/PluginManagerInterface.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager;
|
||||
|
||||
use Interop\Container\Exception\ContainerException;
|
||||
use Laminas\ServiceManager\Exception\InvalidServiceException;
|
||||
|
||||
/**
|
||||
* Interface for a plugin manager
|
||||
*
|
||||
* A plugin manager is a specialized service locator used to create homogeneous objects
|
||||
*/
|
||||
interface PluginManagerInterface extends ServiceLocatorInterface
|
||||
{
|
||||
/**
|
||||
* Validate an instance
|
||||
*
|
||||
* @param object $instance
|
||||
* @return void
|
||||
* @throws InvalidServiceException If created instance does not respect the
|
||||
* constraint on type imposed by the plugin manager
|
||||
* @throws ContainerException if any other error occurs
|
||||
*/
|
||||
public function validate($instance);
|
||||
}
|
||||
68
vendor/laminas/laminas-servicemanager/src/Proxy/LazyServiceFactory.php
vendored
Normal file
68
vendor/laminas/laminas-servicemanager/src/Proxy/LazyServiceFactory.php
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Proxy;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Laminas\ServiceManager\Exception;
|
||||
use Laminas\ServiceManager\Factory\DelegatorFactoryInterface;
|
||||
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
|
||||
use ProxyManager\Proxy\LazyLoadingInterface;
|
||||
|
||||
/**
|
||||
* Delegator factory responsible of instantiating lazy loading value holder proxies of
|
||||
* given services at runtime
|
||||
*
|
||||
* @link https://github.com/Ocramius/ProxyManager/blob/master/docs/lazy-loading-value-holder.md
|
||||
*/
|
||||
final class LazyServiceFactory implements DelegatorFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @var \ProxyManager\Factory\LazyLoadingValueHolderFactory
|
||||
*/
|
||||
private $proxyFactory;
|
||||
|
||||
/**
|
||||
* @var string[] map of service names to class names
|
||||
*/
|
||||
private $servicesMap;
|
||||
|
||||
/**
|
||||
* @param LazyLoadingValueHolderFactory $proxyFactory
|
||||
* @param string[] $servicesMap a map of service names to class names of their
|
||||
* respective classes
|
||||
*/
|
||||
public function __construct(LazyLoadingValueHolderFactory $proxyFactory, array $servicesMap)
|
||||
{
|
||||
$this->proxyFactory = $proxyFactory;
|
||||
$this->servicesMap = $servicesMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return \ProxyManager\Proxy\VirtualProxyInterface
|
||||
*/
|
||||
public function __invoke(ContainerInterface $container, $name, callable $callback, array $options = null)
|
||||
{
|
||||
if (isset($this->servicesMap[$name])) {
|
||||
$initializer = function (&$wrappedInstance, LazyLoadingInterface $proxy) use ($callback) {
|
||||
$proxy->setProxyInitializer(null);
|
||||
$wrappedInstance = $callback();
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return $this->proxyFactory->createProxy($this->servicesMap[$name], $initializer);
|
||||
}
|
||||
|
||||
throw new Exception\ServiceNotFoundException(
|
||||
sprintf('The requested service "%s" was not found in the provided services map', $name)
|
||||
);
|
||||
}
|
||||
}
|
||||
52
vendor/laminas/laminas-servicemanager/src/PsrContainerDecorator.php
vendored
Normal file
52
vendor/laminas/laminas-servicemanager/src/PsrContainerDecorator.php
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Psr\Container\ContainerInterface as PsrContainerInterface;
|
||||
|
||||
/**
|
||||
* @internal for use in abstract plugin manager
|
||||
*/
|
||||
final class PsrContainerDecorator implements ContainerInterface
|
||||
{
|
||||
/**
|
||||
* @var PsrContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
public function __construct(PsrContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($id)
|
||||
{
|
||||
return $this->container->get($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function has($id)
|
||||
{
|
||||
return $this->container->has($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PsrContainerInterface
|
||||
*/
|
||||
public function getContainer()
|
||||
{
|
||||
return $this->container;
|
||||
}
|
||||
}
|
||||
35
vendor/laminas/laminas-servicemanager/src/ServiceLocatorInterface.php
vendored
Normal file
35
vendor/laminas/laminas-servicemanager/src/ServiceLocatorInterface.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager;
|
||||
|
||||
use Interop\Container\ContainerInterface as InteropContainerInterface;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\ContainerInterface as PsrContainerInterface;
|
||||
|
||||
/**
|
||||
* Interface for service locator
|
||||
*/
|
||||
interface ServiceLocatorInterface extends
|
||||
PsrContainerInterface,
|
||||
InteropContainerInterface
|
||||
{
|
||||
/**
|
||||
* Build a service by its name, using optional options (such services are NEVER cached).
|
||||
*
|
||||
* @param string $name
|
||||
* @param null|array $options
|
||||
* @return mixed
|
||||
* @throws Exception\ServiceNotFoundException If no factory/abstract
|
||||
* factory could be found to create the instance.
|
||||
* @throws Exception\ServiceNotCreatedException If factory/delegator fails
|
||||
* to create the instance.
|
||||
* @throws ContainerExceptionInterface if any other error occurs
|
||||
*/
|
||||
public function build($name, array $options = null);
|
||||
}
|
||||
963
vendor/laminas/laminas-servicemanager/src/ServiceManager.php
vendored
Normal file
963
vendor/laminas/laminas-servicemanager/src/ServiceManager.php
vendored
Normal file
@ -0,0 +1,963 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager;
|
||||
|
||||
use Exception;
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Interop\Container\Exception\ContainerException;
|
||||
use Laminas\ServiceManager\Exception\ContainerModificationsNotAllowedException;
|
||||
use Laminas\ServiceManager\Exception\CyclicAliasException;
|
||||
use Laminas\ServiceManager\Exception\InvalidArgumentException;
|
||||
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
|
||||
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
|
||||
use ProxyManager\Configuration as ProxyConfiguration;
|
||||
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
|
||||
use ProxyManager\FileLocator\FileLocator;
|
||||
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
|
||||
use ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy;
|
||||
|
||||
/**
|
||||
* Service Manager.
|
||||
*
|
||||
* Default implementation of the ServiceLocatorInterface, providing capabilities
|
||||
* for object creation via:
|
||||
*
|
||||
* - factories
|
||||
* - abstract factories
|
||||
* - delegator factories
|
||||
* - lazy service factories (generated proxies)
|
||||
* - initializers (interface injection)
|
||||
*
|
||||
* It also provides the ability to inject specific service instances and to
|
||||
* define aliases.
|
||||
*/
|
||||
class ServiceManager implements ServiceLocatorInterface
|
||||
{
|
||||
/**
|
||||
* @var Factory\AbstractFactoryInterface[]
|
||||
*/
|
||||
protected $abstractFactories = [];
|
||||
|
||||
/**
|
||||
* A list of aliases
|
||||
*
|
||||
* Should map one alias to a service name, or another alias (aliases are recursively resolved)
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $aliases = [];
|
||||
|
||||
/**
|
||||
* Whether or not changes may be made to this instance.
|
||||
*
|
||||
* @param bool
|
||||
*/
|
||||
protected $allowOverride = false;
|
||||
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $creationContext;
|
||||
|
||||
/**
|
||||
* @var string[][]|Factory\DelegatorFactoryInterface[][]
|
||||
*/
|
||||
protected $delegators = [];
|
||||
|
||||
/**
|
||||
* A list of factories (either as string name or callable)
|
||||
*
|
||||
* @var string[]|callable[]
|
||||
*/
|
||||
protected $factories = [];
|
||||
|
||||
/**
|
||||
* @var Initializer\InitializerInterface[]|callable[]
|
||||
*/
|
||||
protected $initializers = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $lazyServices = [];
|
||||
|
||||
/**
|
||||
* @var null|Proxy\LazyServiceFactory
|
||||
*/
|
||||
private $lazyServicesDelegator;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $resolvedAliases = [];
|
||||
|
||||
/**
|
||||
* A list of already loaded services (this act as a local cache)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $services = [];
|
||||
|
||||
/**
|
||||
* Enable/disable shared instances by service name.
|
||||
*
|
||||
* Example configuration:
|
||||
*
|
||||
* 'shared' => [
|
||||
* MyService::class => true, // will be shared, even if "sharedByDefault" is false
|
||||
* MyOtherService::class => false // won't be shared, even if "sharedByDefault" is true
|
||||
* ]
|
||||
*
|
||||
* @var boolean[]
|
||||
*/
|
||||
protected $shared = [];
|
||||
|
||||
/**
|
||||
* Should the services be shared by default?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $sharedByDefault = true;
|
||||
|
||||
/**
|
||||
* Service manager was already configured?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $configured = false;
|
||||
|
||||
/**
|
||||
* Cached abstract factories from string.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $cachedAbstractFactories = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* See {@see \Laminas\ServiceManager\ServiceManager::configure()} for details
|
||||
* on what $config accepts.
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
$this->creationContext = $this;
|
||||
$this->configure($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implemented for backwards compatibility with previous plugin managers only.
|
||||
*
|
||||
* Returns the creation context.
|
||||
*
|
||||
* @deprecated since 3.0.0. Factories using 3.0 should use the container
|
||||
* instance passed to the factory instead.
|
||||
* @return ContainerInterface
|
||||
*/
|
||||
public function getServiceLocator()
|
||||
{
|
||||
trigger_error(sprintf(
|
||||
'Usage of %s is deprecated since v3.0.0; please use the container passed to the factory instead',
|
||||
__METHOD__
|
||||
), E_USER_DEPRECATED);
|
||||
return $this->creationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
$requestedName = $name;
|
||||
|
||||
// We start by checking if we have cached the requested service (this
|
||||
// is the fastest method).
|
||||
if (isset($this->services[$requestedName])) {
|
||||
return $this->services[$requestedName];
|
||||
}
|
||||
|
||||
$name = isset($this->resolvedAliases[$name]) ? $this->resolvedAliases[$name] : $name;
|
||||
|
||||
// Next, if the alias should be shared, and we have cached the resolved
|
||||
// service, use it.
|
||||
if ($requestedName !== $name
|
||||
&& (! isset($this->shared[$requestedName]) || $this->shared[$requestedName])
|
||||
&& isset($this->services[$name])
|
||||
) {
|
||||
$this->services[$requestedName] = $this->services[$name];
|
||||
return $this->services[$name];
|
||||
}
|
||||
|
||||
// At this point, we need to create the instance; we use the resolved
|
||||
// name for that.
|
||||
$object = $this->doCreate($name);
|
||||
|
||||
// Cache it for later, if it is supposed to be shared.
|
||||
if (($this->sharedByDefault && ! isset($this->shared[$name]))
|
||||
|| (isset($this->shared[$name]) && $this->shared[$name])
|
||||
) {
|
||||
$this->services[$name] = $object;
|
||||
}
|
||||
|
||||
// Also do so for aliases; this allows sharing based on service name used.
|
||||
if ($requestedName !== $name
|
||||
&& (($this->sharedByDefault && ! isset($this->shared[$requestedName]))
|
||||
|| (isset($this->shared[$requestedName]) && $this->shared[$requestedName]))
|
||||
) {
|
||||
$this->services[$requestedName] = $object;
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function build($name, array $options = null)
|
||||
{
|
||||
// We never cache when using "build"
|
||||
$name = isset($this->resolvedAliases[$name]) ? $this->resolvedAliases[$name] : $name;
|
||||
return $this->doCreate($name, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function has($name)
|
||||
{
|
||||
$name = isset($this->resolvedAliases[$name]) ? $this->resolvedAliases[$name] : $name;
|
||||
$found = isset($this->services[$name]) || isset($this->factories[$name]);
|
||||
|
||||
if ($found) {
|
||||
return $found;
|
||||
}
|
||||
|
||||
// Check abstract factories
|
||||
foreach ($this->abstractFactories as $abstractFactory) {
|
||||
if ($abstractFactory->canCreate($this->creationContext, $name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether or not the instance is immutable.
|
||||
*
|
||||
* @param bool $flag
|
||||
*/
|
||||
public function setAllowOverride($flag)
|
||||
{
|
||||
$this->allowOverride = (bool) $flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the flag indicating immutability status.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getAllowOverride()
|
||||
{
|
||||
return $this->allowOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the service manager
|
||||
*
|
||||
* Valid top keys are:
|
||||
*
|
||||
* - services: service name => service instance pairs
|
||||
* - invokables: service name => class name pairs for classes that do not
|
||||
* have required constructor arguments; internally, maps the class to an
|
||||
* InvokableFactory instance, and creates an alias if the service name
|
||||
* and class name do not match.
|
||||
* - factories: service name => factory pairs; factories may be any
|
||||
* callable, string name resolving to an invokable class, or string name
|
||||
* resolving to a FactoryInterface instance.
|
||||
* - abstract_factories: an array of abstract factories; these may be
|
||||
* instances of AbstractFactoryInterface, or string names resolving to
|
||||
* classes that implement that interface.
|
||||
* - delegators: service name => list of delegator factories for the given
|
||||
* service; each item in the list may be a callable, a string name
|
||||
* resolving to an invokable class, or a string name resolving to a class
|
||||
* implementing DelegatorFactoryInterface.
|
||||
* - shared: service name => flag pairs; the flag is a boolean indicating
|
||||
* whether or not the service is shared.
|
||||
* - aliases: alias => service name pairs.
|
||||
* - lazy_services: lazy service configuration; can contain the keys:
|
||||
* - class_map: service name => class name pairs.
|
||||
* - proxies_namespace: string namespace to use for generated proxy
|
||||
* classes.
|
||||
* - proxies_target_dir: directory in which to write generated proxy
|
||||
* classes; uses system temporary by default.
|
||||
* - write_proxy_files: boolean indicating whether generated proxy
|
||||
* classes should be written; defaults to boolean false.
|
||||
* - shared_by_default: boolean, indicating if services in this instance
|
||||
* should be shared by default.
|
||||
*
|
||||
* @param array $config
|
||||
* @return self
|
||||
* @throws ContainerModificationsNotAllowedException if the allow
|
||||
* override flag has been toggled off, and a service instance
|
||||
* exists for a given service.
|
||||
*/
|
||||
public function configure(array $config)
|
||||
{
|
||||
$this->validateOverrides($config);
|
||||
|
||||
if (isset($config['services'])) {
|
||||
$this->services = $config['services'] + $this->services;
|
||||
}
|
||||
|
||||
if (isset($config['invokables']) && ! empty($config['invokables'])) {
|
||||
$aliases = $this->createAliasesForInvokables($config['invokables']);
|
||||
$factories = $this->createFactoriesForInvokables($config['invokables']);
|
||||
|
||||
if (! empty($aliases)) {
|
||||
$config['aliases'] = (isset($config['aliases']))
|
||||
? array_merge($config['aliases'], $aliases)
|
||||
: $aliases;
|
||||
}
|
||||
|
||||
$config['factories'] = (isset($config['factories']))
|
||||
? array_merge($config['factories'], $factories)
|
||||
: $factories;
|
||||
}
|
||||
|
||||
if (isset($config['factories'])) {
|
||||
$this->factories = $config['factories'] + $this->factories;
|
||||
}
|
||||
|
||||
if (isset($config['delegators'])) {
|
||||
$this->delegators = array_merge_recursive($this->delegators, $config['delegators']);
|
||||
}
|
||||
|
||||
if (isset($config['shared'])) {
|
||||
$this->shared = $config['shared'] + $this->shared;
|
||||
}
|
||||
|
||||
if (isset($config['aliases'])) {
|
||||
$this->configureAliases($config['aliases']);
|
||||
} elseif (! $this->configured && ! empty($this->aliases)) {
|
||||
$this->resolveAliases($this->aliases);
|
||||
}
|
||||
|
||||
if (isset($config['shared_by_default'])) {
|
||||
$this->sharedByDefault = $config['shared_by_default'];
|
||||
}
|
||||
|
||||
// If lazy service configuration was provided, reset the lazy services
|
||||
// delegator factory.
|
||||
if (isset($config['lazy_services']) && ! empty($config['lazy_services'])) {
|
||||
$this->lazyServices = array_merge_recursive($this->lazyServices, $config['lazy_services']);
|
||||
$this->lazyServicesDelegator = null;
|
||||
}
|
||||
|
||||
// For abstract factories and initializers, we always directly
|
||||
// instantiate them to avoid checks during service construction.
|
||||
if (isset($config['abstract_factories'])) {
|
||||
$this->resolveAbstractFactories($config['abstract_factories']);
|
||||
}
|
||||
|
||||
if (isset($config['initializers'])) {
|
||||
$this->resolveInitializers($config['initializers']);
|
||||
}
|
||||
|
||||
$this->configured = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $aliases
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function configureAliases(array $aliases)
|
||||
{
|
||||
if (! $this->configured) {
|
||||
$this->aliases = $aliases + $this->aliases;
|
||||
|
||||
$this->resolveAliases($this->aliases);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Performance optimization. If there are no collisions, then we don't need to recompute loops
|
||||
$intersecting = $this->aliases && \array_intersect_key($this->aliases, $aliases);
|
||||
$this->aliases = $this->aliases ? \array_merge($this->aliases, $aliases) : $aliases;
|
||||
|
||||
if ($intersecting) {
|
||||
$this->resolveAliases($this->aliases);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->resolveAliases($aliases);
|
||||
$this->resolveNewAliasesWithPreviouslyResolvedAliases($aliases);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an alias.
|
||||
*
|
||||
* @param string $alias
|
||||
* @param string $target
|
||||
*/
|
||||
public function setAlias($alias, $target)
|
||||
{
|
||||
$this->configure(['aliases' => [$alias => $target]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an invokable class mapping.
|
||||
*
|
||||
* @param string $name Service name
|
||||
* @param null|string $class Class to which to map; if omitted, $name is
|
||||
* assumed.
|
||||
*/
|
||||
public function setInvokableClass($name, $class = null)
|
||||
{
|
||||
$this->configure(['invokables' => [$name => $class ?: $name]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a factory for a given service name.
|
||||
*
|
||||
* @param string $name Service name
|
||||
* @param string|callable|Factory\FactoryInterface $factory Factory to which
|
||||
* to map.
|
||||
*/
|
||||
public function setFactory($name, $factory)
|
||||
{
|
||||
$this->configure(['factories' => [$name => $factory]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a lazy service mapping to a class.
|
||||
*
|
||||
* @param string $name Service name to map
|
||||
* @param null|string $class Class to which to map; if not provided, $name
|
||||
* will be used for the mapping.
|
||||
*/
|
||||
public function mapLazyService($name, $class = null)
|
||||
{
|
||||
$this->configure(['lazy_services' => ['class_map' => [$name => $class ?: $name]]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an abstract factory for resolving services.
|
||||
*
|
||||
* @param string|Factory\AbstractFactoryInterface $factory Service name
|
||||
*/
|
||||
public function addAbstractFactory($factory)
|
||||
{
|
||||
$this->configure(['abstract_factories' => [$factory]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a delegator for a given service.
|
||||
*
|
||||
* @param string $name Service name
|
||||
* @param string|callable|Factory\DelegatorFactoryInterface $factory Delegator
|
||||
* factory to assign.
|
||||
*/
|
||||
public function addDelegator($name, $factory)
|
||||
{
|
||||
$this->configure(['delegators' => [$name => [$factory]]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an initializer.
|
||||
*
|
||||
* @param string|callable|Initializer\InitializerInterface $initializer
|
||||
*/
|
||||
public function addInitializer($initializer)
|
||||
{
|
||||
$this->configure(['initializers' => [$initializer]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a service.
|
||||
*
|
||||
* @param string $name Service name
|
||||
* @param array|object $service
|
||||
*/
|
||||
public function setService($name, $service)
|
||||
{
|
||||
$this->configure(['services' => [$name => $service]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a service sharing rule.
|
||||
*
|
||||
* @param string $name Service name
|
||||
* @param boolean $flag Whether or not the service should be shared.
|
||||
*/
|
||||
public function setShared($name, $flag)
|
||||
{
|
||||
$this->configure(['shared' => [$name => (bool) $flag]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate abstract factories for to avoid checks during service construction.
|
||||
*
|
||||
* @param string[]|Factory\AbstractFactoryInterface[] $abstractFactories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function resolveAbstractFactories(array $abstractFactories)
|
||||
{
|
||||
foreach ($abstractFactories as $abstractFactory) {
|
||||
if (is_string($abstractFactory) && class_exists($abstractFactory)) {
|
||||
//Cached string
|
||||
if (! isset($this->cachedAbstractFactories[$abstractFactory])) {
|
||||
$this->cachedAbstractFactories[$abstractFactory] = new $abstractFactory();
|
||||
}
|
||||
|
||||
$abstractFactory = $this->cachedAbstractFactories[$abstractFactory];
|
||||
}
|
||||
|
||||
if ($abstractFactory instanceof Factory\AbstractFactoryInterface) {
|
||||
$abstractFactoryObjHash = spl_object_hash($abstractFactory);
|
||||
$this->abstractFactories[$abstractFactoryObjHash] = $abstractFactory;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Error condition; let's find out why.
|
||||
|
||||
// If we still have a string, we have a class name that does not resolve
|
||||
if (is_string($abstractFactory)) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf(
|
||||
'An invalid abstract factory was registered; resolved to class "%s" ' .
|
||||
'which does not exist; please provide a valid class name resolving ' .
|
||||
'to an implementation of %s',
|
||||
$abstractFactory,
|
||||
AbstractFactoryInterface::class
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Otherwise, we have an invalid type.
|
||||
throw new InvalidArgumentException(
|
||||
sprintf(
|
||||
'An invalid abstract factory was registered. Expected an instance of "%s", ' .
|
||||
'but "%s" was received',
|
||||
AbstractFactoryInterface::class,
|
||||
(is_object($abstractFactory) ? get_class($abstractFactory) : gettype($abstractFactory))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate initializers for to avoid checks during service construction.
|
||||
*
|
||||
* @param string[]|Initializer\InitializerInterface[]|callable[] $initializers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function resolveInitializers(array $initializers)
|
||||
{
|
||||
foreach ($initializers as $initializer) {
|
||||
if (is_string($initializer) && class_exists($initializer)) {
|
||||
$initializer = new $initializer();
|
||||
}
|
||||
|
||||
if (is_callable($initializer)) {
|
||||
$this->initializers[] = $initializer;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Error condition; let's find out why.
|
||||
|
||||
if (is_string($initializer)) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf(
|
||||
'An invalid initializer was registered; resolved to class or function "%s" ' .
|
||||
'which does not exist; please provide a valid function name or class ' .
|
||||
'name resolving to an implementation of %s',
|
||||
$initializer,
|
||||
Initializer\InitializerInterface::class
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Otherwise, we have an invalid type.
|
||||
throw new InvalidArgumentException(
|
||||
sprintf(
|
||||
'An invalid initializer was registered. Expected a callable, or an instance of ' .
|
||||
'(or string class name resolving to) "%s", ' .
|
||||
'but "%s" was received',
|
||||
Initializer\InitializerInterface::class,
|
||||
(is_object($initializer) ? get_class($initializer) : gettype($initializer))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve aliases to their canonical service names.
|
||||
*
|
||||
* @param string[] $aliases
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function resolveAliases(array $aliases)
|
||||
{
|
||||
foreach ($aliases as $alias => $service) {
|
||||
$visited = [];
|
||||
$name = $alias;
|
||||
|
||||
while (isset($this->aliases[$name])) {
|
||||
if (isset($visited[$name])) {
|
||||
throw CyclicAliasException::fromAliasesMap($aliases);
|
||||
}
|
||||
|
||||
$visited[$name] = true;
|
||||
$name = $this->aliases[$name];
|
||||
}
|
||||
|
||||
$this->resolvedAliases[$alias] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites the map of aliases by resolving the given $aliases with the existing resolved ones.
|
||||
* This is mostly done for performance reasons.
|
||||
*
|
||||
* @param string[] $aliases
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function resolveNewAliasesWithPreviouslyResolvedAliases(array $aliases)
|
||||
{
|
||||
foreach ($this->resolvedAliases as $name => $target) {
|
||||
if (isset($aliases[$target])) {
|
||||
$this->resolvedAliases[$name] = $this->resolvedAliases[$target];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a factory for the given service name
|
||||
*
|
||||
* @param string $name
|
||||
* @return callable
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
private function getFactory($name)
|
||||
{
|
||||
$factory = isset($this->factories[$name]) ? $this->factories[$name] : null;
|
||||
|
||||
$lazyLoaded = false;
|
||||
if (is_string($factory) && class_exists($factory)) {
|
||||
$factory = new $factory();
|
||||
$lazyLoaded = true;
|
||||
}
|
||||
|
||||
if (is_callable($factory)) {
|
||||
if ($lazyLoaded) {
|
||||
$this->factories[$name] = $factory;
|
||||
}
|
||||
// PHP 5.6 fails on 'class::method' callables unless we explode them:
|
||||
if (PHP_MAJOR_VERSION < 7
|
||||
&& is_string($factory) && strpos($factory, '::') !== false
|
||||
) {
|
||||
$factory = explode('::', $factory);
|
||||
}
|
||||
return $factory;
|
||||
}
|
||||
|
||||
// Check abstract factories
|
||||
foreach ($this->abstractFactories as $abstractFactory) {
|
||||
if ($abstractFactory->canCreate($this->creationContext, $name)) {
|
||||
return $abstractFactory;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ServiceNotFoundException(sprintf(
|
||||
'Unable to resolve service "%s" to a factory; are you certain you provided it during configuration?',
|
||||
$name
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param null|array $options
|
||||
* @return object
|
||||
*/
|
||||
private function createDelegatorFromName($name, array $options = null)
|
||||
{
|
||||
$creationCallback = function () use ($name, $options) {
|
||||
// Code is inlined for performance reason, instead of abstracting the creation
|
||||
$factory = $this->getFactory($name);
|
||||
return $factory($this->creationContext, $name, $options);
|
||||
};
|
||||
|
||||
foreach ($this->delegators[$name] as $index => $delegatorFactory) {
|
||||
$delegatorFactory = $this->delegators[$name][$index];
|
||||
|
||||
if ($delegatorFactory === Proxy\LazyServiceFactory::class) {
|
||||
$delegatorFactory = $this->createLazyServiceDelegatorFactory();
|
||||
}
|
||||
|
||||
if (is_string($delegatorFactory) && class_exists($delegatorFactory)) {
|
||||
$delegatorFactory = new $delegatorFactory();
|
||||
}
|
||||
|
||||
if (! is_callable($delegatorFactory)) {
|
||||
if (is_string($delegatorFactory)) {
|
||||
throw new ServiceNotCreatedException(sprintf(
|
||||
'An invalid delegator factory was registered; resolved to class or function "%s" '
|
||||
. 'which does not exist; please provide a valid function name or class name resolving '
|
||||
. 'to an implementation of %s',
|
||||
$delegatorFactory,
|
||||
DelegatorFactoryInterface::class
|
||||
));
|
||||
}
|
||||
|
||||
throw new ServiceNotCreatedException(sprintf(
|
||||
'A non-callable delegator, "%s", was provided; expected a callable or instance of "%s"',
|
||||
is_object($delegatorFactory) ? get_class($delegatorFactory) : gettype($delegatorFactory),
|
||||
DelegatorFactoryInterface::class
|
||||
));
|
||||
}
|
||||
|
||||
$this->delegators[$name][$index] = $delegatorFactory;
|
||||
|
||||
$creationCallback = function () use ($delegatorFactory, $name, $creationCallback, $options) {
|
||||
return $delegatorFactory($this->creationContext, $name, $creationCallback, $options);
|
||||
};
|
||||
}
|
||||
|
||||
return $creationCallback($this->creationContext, $name, $creationCallback, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with an already resolved name
|
||||
*
|
||||
* This is a highly performance sensitive method, do not modify if you have not benchmarked it carefully
|
||||
*
|
||||
* @param string $resolvedName
|
||||
* @param null|array $options
|
||||
* @return mixed
|
||||
* @throws ServiceNotFoundException if unable to resolve the service.
|
||||
* @throws ServiceNotCreatedException if an exception is raised when
|
||||
* creating a service.
|
||||
* @throws ContainerException if any other error occurs
|
||||
*/
|
||||
private function doCreate($resolvedName, array $options = null)
|
||||
{
|
||||
try {
|
||||
if (! isset($this->delegators[$resolvedName])) {
|
||||
// Let's create the service by fetching the factory
|
||||
$factory = $this->getFactory($resolvedName);
|
||||
$object = $factory($this->creationContext, $resolvedName, $options);
|
||||
} else {
|
||||
$object = $this->createDelegatorFromName($resolvedName, $options);
|
||||
}
|
||||
} catch (ContainerException $exception) {
|
||||
throw $exception;
|
||||
} catch (Exception $exception) {
|
||||
throw new ServiceNotCreatedException(sprintf(
|
||||
'Service with name "%s" could not be created. Reason: %s',
|
||||
$resolvedName,
|
||||
$exception->getMessage()
|
||||
), (int) $exception->getCode(), $exception);
|
||||
}
|
||||
|
||||
foreach ($this->initializers as $initializer) {
|
||||
$initializer($this->creationContext, $object);
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the lazy services delegator factory.
|
||||
*
|
||||
* Creates the lazy services delegator factory based on the lazy_services
|
||||
* configuration present.
|
||||
*
|
||||
* @return Proxy\LazyServiceFactory
|
||||
* @throws ServiceNotCreatedException when the lazy service class_map
|
||||
* configuration is missing
|
||||
*/
|
||||
private function createLazyServiceDelegatorFactory()
|
||||
{
|
||||
if ($this->lazyServicesDelegator) {
|
||||
return $this->lazyServicesDelegator;
|
||||
}
|
||||
|
||||
if (! isset($this->lazyServices['class_map'])) {
|
||||
throw new ServiceNotCreatedException('Missing "class_map" config key in "lazy_services"');
|
||||
}
|
||||
|
||||
$factoryConfig = new ProxyConfiguration();
|
||||
|
||||
if (isset($this->lazyServices['proxies_namespace'])) {
|
||||
$factoryConfig->setProxiesNamespace($this->lazyServices['proxies_namespace']);
|
||||
}
|
||||
|
||||
if (isset($this->lazyServices['proxies_target_dir'])) {
|
||||
$factoryConfig->setProxiesTargetDir($this->lazyServices['proxies_target_dir']);
|
||||
}
|
||||
|
||||
if (! isset($this->lazyServices['write_proxy_files']) || ! $this->lazyServices['write_proxy_files']) {
|
||||
$factoryConfig->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
|
||||
} else {
|
||||
$factoryConfig->setGeneratorStrategy(new FileWriterGeneratorStrategy(
|
||||
new FileLocator($factoryConfig->getProxiesTargetDir())
|
||||
));
|
||||
}
|
||||
|
||||
spl_autoload_register($factoryConfig->getProxyAutoloader());
|
||||
|
||||
$this->lazyServicesDelegator = new Proxy\LazyServiceFactory(
|
||||
new LazyLoadingValueHolderFactory($factoryConfig),
|
||||
$this->lazyServices['class_map']
|
||||
);
|
||||
|
||||
return $this->lazyServicesDelegator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create aliases for invokable classes.
|
||||
*
|
||||
* If an invokable service name does not match the class it maps to, this
|
||||
* creates an alias to the class (which will later be mapped as an
|
||||
* invokable factory).
|
||||
*
|
||||
* @param array $invokables
|
||||
* @return array
|
||||
*/
|
||||
private function createAliasesForInvokables(array $invokables)
|
||||
{
|
||||
$aliases = [];
|
||||
foreach ($invokables as $name => $class) {
|
||||
if ($name === $class) {
|
||||
continue;
|
||||
}
|
||||
$aliases[$name] = $class;
|
||||
}
|
||||
return $aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create invokable factories for invokable classes.
|
||||
*
|
||||
* If an invokable service name does not match the class it maps to, this
|
||||
* creates an invokable factory entry for the class name; otherwise, it
|
||||
* creates an invokable factory for the entry name.
|
||||
*
|
||||
* @param array $invokables
|
||||
* @return array
|
||||
*/
|
||||
private function createFactoriesForInvokables(array $invokables)
|
||||
{
|
||||
$factories = [];
|
||||
foreach ($invokables as $name => $class) {
|
||||
if ($name === $class) {
|
||||
$factories[$name] = Factory\InvokableFactory::class;
|
||||
continue;
|
||||
}
|
||||
|
||||
$factories[$class] = Factory\InvokableFactory::class;
|
||||
}
|
||||
return $factories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if one or more services already exist in the container.
|
||||
*
|
||||
* If the allow override flag is true or it's first time configured,
|
||||
* this method does nothing.
|
||||
*
|
||||
* Otherwise, it checks against each of the following service types,
|
||||
* if present, and validates that none are defining services that
|
||||
* already exist; if they do, it raises an exception indicating
|
||||
* modification is not allowed.
|
||||
*
|
||||
* @param array $config
|
||||
* @throws ContainerModificationsNotAllowedException if any services
|
||||
* provided already have instances available.
|
||||
*/
|
||||
private function validateOverrides(array $config)
|
||||
{
|
||||
if ($this->allowOverride || ! $this->configured) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($config['services'])) {
|
||||
$this->validateOverrideSet(array_keys($config['services']), 'service');
|
||||
}
|
||||
|
||||
if (isset($config['aliases'])) {
|
||||
$this->validateOverrideSet(array_keys($config['aliases']), 'alias');
|
||||
}
|
||||
|
||||
if (isset($config['invokables'])) {
|
||||
$this->validateOverrideSet(array_keys($config['invokables']), 'invokable class');
|
||||
}
|
||||
|
||||
if (isset($config['factories'])) {
|
||||
$this->validateOverrideSet(array_keys($config['factories']), 'factory');
|
||||
}
|
||||
|
||||
if (isset($config['delegators'])) {
|
||||
$this->validateOverrideSet(array_keys($config['delegators']), 'delegator');
|
||||
}
|
||||
|
||||
if (isset($config['shared'])) {
|
||||
$this->validateOverrideSet(array_keys($config['shared']), 'sharing rule');
|
||||
}
|
||||
|
||||
if (isset($config['lazy_services']['class_map'])) {
|
||||
$this->validateOverrideSet(array_keys($config['lazy_services']['class_map']), 'lazy service');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if one or more services already exist for a given type.
|
||||
*
|
||||
* Loops through the provided service names, checking if any have current
|
||||
* service instances; if not, it returns, but otherwise, it raises an
|
||||
* exception indicating modification is not allowed.
|
||||
*
|
||||
* @param string[] $services
|
||||
* @param string $type Type of service being checked.
|
||||
* @throws ContainerModificationsNotAllowedException if any services
|
||||
* provided already have instances available.
|
||||
*/
|
||||
private function validateOverrideSet(array $services, $type)
|
||||
{
|
||||
$detected = [];
|
||||
foreach ($services as $service) {
|
||||
if (isset($this->services[$service])) {
|
||||
$detected[] = $service;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($detected)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ContainerModificationsNotAllowedException(sprintf(
|
||||
'An updated/new %s is not allowed, as the container does not allow '
|
||||
. 'changes for services with existing instances; the following '
|
||||
. 'already exist in the container: %s',
|
||||
$type,
|
||||
implode(', ', $detected)
|
||||
));
|
||||
}
|
||||
}
|
||||
115
vendor/laminas/laminas-servicemanager/src/Test/CommonPluginManagerTrait.php
vendored
Normal file
115
vendor/laminas/laminas-servicemanager/src/Test/CommonPluginManagerTrait.php
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Test;
|
||||
|
||||
use Laminas\ServiceManager\Exception\InvalidServiceException;
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
|
||||
/**
|
||||
* Trait for testing plugin managers for v2-v3 compatibility
|
||||
*
|
||||
* To use this trait:
|
||||
* * implement the `getPluginManager()` method to return your plugin manager
|
||||
* * implement the `getV2InvalidPluginException()` method to return the class `validatePlugin()` throws under v2
|
||||
*/
|
||||
trait CommonPluginManagerTrait
|
||||
{
|
||||
public function testInstanceOfMatches()
|
||||
{
|
||||
$manager = $this->getPluginManager();
|
||||
$reflection = new ReflectionProperty($manager, 'instanceOf');
|
||||
$reflection->setAccessible(true);
|
||||
$this->assertEquals($this->getInstanceOf(), $reflection->getValue($manager), 'instanceOf does not match');
|
||||
}
|
||||
|
||||
public function testShareByDefaultAndSharedByDefault()
|
||||
{
|
||||
$manager = $this->getPluginManager();
|
||||
$reflection = new ReflectionClass($manager);
|
||||
$shareByDefault = $sharedByDefault = true;
|
||||
|
||||
foreach ($reflection->getProperties() as $prop) {
|
||||
if ($prop->getName() == 'shareByDefault') {
|
||||
$prop->setAccessible(true);
|
||||
$shareByDefault = $prop->getValue($manager);
|
||||
}
|
||||
if ($prop->getName() == 'sharedByDefault') {
|
||||
$prop->setAccessible(true);
|
||||
$sharedByDefault = $prop->getValue($manager);
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertTrue(
|
||||
$shareByDefault == $sharedByDefault,
|
||||
'Values of shareByDefault and sharedByDefault do not match'
|
||||
);
|
||||
}
|
||||
|
||||
public function testRegisteringInvalidElementRaisesException()
|
||||
{
|
||||
$this->expectException($this->getServiceNotFoundException());
|
||||
$this->getPluginManager()->setService('test', $this);
|
||||
}
|
||||
|
||||
public function testLoadingInvalidElementRaisesException()
|
||||
{
|
||||
$manager = $this->getPluginManager();
|
||||
$manager->setInvokableClass('test', get_class($this));
|
||||
$this->expectException($this->getServiceNotFoundException());
|
||||
$manager->get('test');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider aliasProvider
|
||||
*/
|
||||
public function testPluginAliasesResolve($alias, $expected)
|
||||
{
|
||||
$this->assertInstanceOf($expected, $this->getPluginManager()->get($alias), "Alias '$alias' does not resolve'");
|
||||
}
|
||||
|
||||
public function aliasProvider()
|
||||
{
|
||||
$manager = $this->getPluginManager();
|
||||
$reflection = new ReflectionProperty($manager, 'aliases');
|
||||
$reflection->setAccessible(true);
|
||||
$data = [];
|
||||
foreach ($reflection->getValue($manager) as $alias => $expected) {
|
||||
$data[] = [$alias, $expected];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getServiceNotFoundException()
|
||||
{
|
||||
$manager = $this->getPluginManager();
|
||||
if (method_exists($manager, 'configure')) {
|
||||
return InvalidServiceException::class;
|
||||
}
|
||||
return $this->getV2InvalidPluginException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin manager to test
|
||||
* @return \Laminas\ServiceManager\AbstractPluginManager
|
||||
*/
|
||||
abstract protected function getPluginManager();
|
||||
|
||||
/**
|
||||
* Returns the FQCN of the exception thrown under v2 by `validatePlugin()`
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function getV2InvalidPluginException();
|
||||
|
||||
/**
|
||||
* Returns the value the instanceOf property has been set to
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getInstanceOf();
|
||||
}
|
||||
259
vendor/laminas/laminas-servicemanager/src/Tool/ConfigDumper.php
vendored
Normal file
259
vendor/laminas/laminas-servicemanager/src/Tool/ConfigDumper.php
vendored
Normal file
@ -0,0 +1,259 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Tool;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory;
|
||||
use Laminas\ServiceManager\Exception\InvalidArgumentException;
|
||||
use ReflectionClass;
|
||||
use ReflectionParameter;
|
||||
use Traversable;
|
||||
|
||||
class ConfigDumper
|
||||
{
|
||||
const CONFIG_TEMPLATE = <<<EOC
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file generated by %s.
|
||||
* Generated %s
|
||||
*/
|
||||
|
||||
return %s;
|
||||
EOC;
|
||||
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*/
|
||||
public function __construct(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @param string $className
|
||||
* @param bool $ignoreUnresolved
|
||||
* @return array
|
||||
* @throws InvalidArgumentException for invalid $className
|
||||
*/
|
||||
public function createDependencyConfig(array $config, $className, $ignoreUnresolved = false)
|
||||
{
|
||||
$this->validateClassName($className);
|
||||
|
||||
$reflectionClass = new ReflectionClass($className);
|
||||
|
||||
// class is an interface; do nothing
|
||||
if ($reflectionClass->isInterface()) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
// class has no constructor, treat it as an invokable
|
||||
if (! $reflectionClass->getConstructor()) {
|
||||
return $this->createInvokable($config, $className);
|
||||
}
|
||||
|
||||
$constructorArguments = $reflectionClass->getConstructor()->getParameters();
|
||||
$constructorArguments = array_filter(
|
||||
$constructorArguments,
|
||||
function (ReflectionParameter $argument) {
|
||||
return ! $argument->isOptional();
|
||||
}
|
||||
);
|
||||
|
||||
// has no required parameters, treat it as an invokable
|
||||
if (empty($constructorArguments)) {
|
||||
return $this->createInvokable($config, $className);
|
||||
}
|
||||
|
||||
$classConfig = [];
|
||||
|
||||
foreach ($constructorArguments as $constructorArgument) {
|
||||
$argumentType = $constructorArgument->getClass();
|
||||
if (is_null($argumentType)) {
|
||||
if ($ignoreUnresolved) {
|
||||
// don't throw an exception, just return the previous config
|
||||
return $config;
|
||||
}
|
||||
// don't throw an exception if the class is an already defined service
|
||||
if ($this->container && $this->container->has($className)) {
|
||||
return $config;
|
||||
}
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Cannot create config for constructor argument "%s", '
|
||||
. 'it has no type hint, or non-class/interface type hint',
|
||||
$constructorArgument->getName()
|
||||
));
|
||||
}
|
||||
$argumentName = $argumentType->getName();
|
||||
$config = $this->createDependencyConfig($config, $argumentName, $ignoreUnresolved);
|
||||
$classConfig[] = $argumentName;
|
||||
}
|
||||
|
||||
$config[ConfigAbstractFactory::class][$className] = $classConfig;
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $className
|
||||
* @throws InvalidArgumentException if class name is not a string or does
|
||||
* not exist.
|
||||
*/
|
||||
private function validateClassName($className)
|
||||
{
|
||||
if (! is_string($className)) {
|
||||
throw new InvalidArgumentException('Class name must be a string, ' . gettype($className) . ' given');
|
||||
}
|
||||
|
||||
if (! class_exists($className) && ! interface_exists($className)) {
|
||||
throw new InvalidArgumentException('Cannot find class or interface with name ' . $className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @param string $className
|
||||
* @return array
|
||||
*/
|
||||
private function createInvokable(array $config, $className)
|
||||
{
|
||||
$config[ConfigAbstractFactory::class][$className] = [];
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @return array
|
||||
* @throws InvalidArgumentException if ConfigAbstractFactory configuration
|
||||
* value is not an array.
|
||||
*/
|
||||
public function createFactoryMappingsFromConfig(array $config)
|
||||
{
|
||||
if (! array_key_exists(ConfigAbstractFactory::class, $config)) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
if (! is_array($config[ConfigAbstractFactory::class])) {
|
||||
throw new InvalidArgumentException(
|
||||
'Config key for ' . ConfigAbstractFactory::class . ' should be an array, ' . gettype(
|
||||
$config[ConfigAbstractFactory::class]
|
||||
) . ' given'
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($config[ConfigAbstractFactory::class] as $className => $dependency) {
|
||||
$config = $this->createFactoryMappings($config, $className);
|
||||
}
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @param string $className
|
||||
* @return array
|
||||
*/
|
||||
public function createFactoryMappings(array $config, $className)
|
||||
{
|
||||
$this->validateClassName($className);
|
||||
|
||||
if (array_key_exists('service_manager', $config)
|
||||
&& array_key_exists('factories', $config['service_manager'])
|
||||
&& array_key_exists($className, $config['service_manager']['factories'])
|
||||
) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
$config['service_manager']['factories'][$className] = ConfigAbstractFactory::class;
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
public function dumpConfigFile(array $config)
|
||||
{
|
||||
$prepared = $this->prepareConfig($config);
|
||||
return sprintf(
|
||||
self::CONFIG_TEMPLATE,
|
||||
get_class($this),
|
||||
date('Y-m-d H:i:s'),
|
||||
$prepared
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|Traversable $config
|
||||
* @param int $indentLevel
|
||||
* @return string
|
||||
*/
|
||||
private function prepareConfig($config, $indentLevel = 1)
|
||||
{
|
||||
$indent = str_repeat(' ', $indentLevel * 4);
|
||||
$entries = [];
|
||||
foreach ($config as $key => $value) {
|
||||
$key = $this->createConfigKey($key);
|
||||
$entries[] = sprintf(
|
||||
'%s%s%s,',
|
||||
$indent,
|
||||
$key ? sprintf('%s => ', $key) : '',
|
||||
$this->createConfigValue($value, $indentLevel)
|
||||
);
|
||||
}
|
||||
|
||||
$outerIndent = str_repeat(' ', ($indentLevel - 1) * 4);
|
||||
|
||||
return sprintf(
|
||||
"[\n%s\n%s]",
|
||||
implode("\n", $entries),
|
||||
$outerIndent
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|int|null $key
|
||||
* @return null|string
|
||||
*/
|
||||
private function createConfigKey($key)
|
||||
{
|
||||
if (is_string($key) && class_exists($key)) {
|
||||
return sprintf('\\%s::class', $key);
|
||||
}
|
||||
|
||||
if (is_int($key)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return sprintf("'%s'", $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param int $indentLevel
|
||||
* @return string
|
||||
*/
|
||||
private function createConfigValue($value, $indentLevel)
|
||||
{
|
||||
if (is_array($value) || $value instanceof Traversable) {
|
||||
return $this->prepareConfig($value, $indentLevel + 1);
|
||||
}
|
||||
|
||||
if (is_string($value) && class_exists($value)) {
|
||||
return sprintf('\\%s::class', $value);
|
||||
}
|
||||
|
||||
return var_export($value, true);
|
||||
}
|
||||
}
|
||||
229
vendor/laminas/laminas-servicemanager/src/Tool/ConfigDumperCommand.php
vendored
Normal file
229
vendor/laminas/laminas-servicemanager/src/Tool/ConfigDumperCommand.php
vendored
Normal file
@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Tool;
|
||||
|
||||
use Laminas\ServiceManager\Exception;
|
||||
use Laminas\Stdlib\ConsoleHelper;
|
||||
|
||||
class ConfigDumperCommand
|
||||
{
|
||||
const COMMAND_DUMP = 'dump';
|
||||
const COMMAND_ERROR = 'error';
|
||||
const COMMAND_HELP = 'help';
|
||||
|
||||
const DEFAULT_SCRIPT_NAME = __CLASS__;
|
||||
|
||||
const HELP_TEMPLATE = <<< EOH
|
||||
<info>Usage:</info>
|
||||
|
||||
%s [-h|--help|help] [-i|--ignore-unresolved] <configFile> <className>
|
||||
|
||||
<info>Arguments:</info>
|
||||
|
||||
<info>-h|--help|help</info> This usage message
|
||||
<info>-i|--ignore-unresolved</info> Ignore classes with unresolved direct dependencies.
|
||||
<info><configFile></info> Path to a config file for which to generate
|
||||
configuration. If the file does not exist, it will
|
||||
be created. If it does exist, it must return an
|
||||
array, and the file will be updated with new
|
||||
configuration.
|
||||
<info><className></info> Name of the class to reflect and for which to
|
||||
generate dependency configuration.
|
||||
|
||||
Reads the provided configuration file (creating it if it does not exist),
|
||||
and injects it with ConfigAbstractFactory dependency configuration for
|
||||
the provided class name, writing the changes back to the file.
|
||||
EOH;
|
||||
|
||||
/**
|
||||
* @var ConsoleHelper
|
||||
*/
|
||||
private $helper;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $scriptName;
|
||||
|
||||
/**
|
||||
* @param string $scriptName
|
||||
*/
|
||||
public function __construct($scriptName = self::DEFAULT_SCRIPT_NAME, ConsoleHelper $helper = null)
|
||||
{
|
||||
$this->scriptName = $scriptName;
|
||||
$this->helper = $helper ?: new ConsoleHelper();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $args Argument list, minus script name
|
||||
* @return int Exit status
|
||||
*/
|
||||
public function __invoke(array $args)
|
||||
{
|
||||
$arguments = $this->parseArgs($args);
|
||||
|
||||
switch ($arguments->command) {
|
||||
case self::COMMAND_HELP:
|
||||
$this->help();
|
||||
return 0;
|
||||
case self::COMMAND_ERROR:
|
||||
$this->helper->writeErrorMessage($arguments->message);
|
||||
$this->help(STDERR);
|
||||
return 1;
|
||||
case self::COMMAND_DUMP:
|
||||
// fall-through
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
$dumper = new ConfigDumper();
|
||||
try {
|
||||
$config = $dumper->createDependencyConfig(
|
||||
$arguments->config,
|
||||
$arguments->class,
|
||||
$arguments->ignoreUnresolved
|
||||
);
|
||||
} catch (Exception\InvalidArgumentException $e) {
|
||||
$this->helper->writeErrorMessage(sprintf(
|
||||
'Unable to create config for "%s": %s',
|
||||
$arguments->class,
|
||||
$e->getMessage()
|
||||
));
|
||||
$this->help(STDERR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
file_put_contents($arguments->configFile, $dumper->dumpConfigFile($config));
|
||||
|
||||
$this->helper->writeLine(sprintf(
|
||||
'<info>[DONE]</info> Changes written to %s',
|
||||
$arguments->configFile
|
||||
));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $args
|
||||
* @return \stdClass
|
||||
*/
|
||||
private function parseArgs(array $args)
|
||||
{
|
||||
if (! count($args)) {
|
||||
return $this->createHelpArgument();
|
||||
}
|
||||
|
||||
$arg1 = array_shift($args);
|
||||
|
||||
if (in_array($arg1, ['-h', '--help', 'help'], true)) {
|
||||
return $this->createHelpArgument();
|
||||
}
|
||||
|
||||
$ignoreUnresolved = false;
|
||||
if (in_array($arg1, ['-i', '--ignore-unresolved'], true)) {
|
||||
$ignoreUnresolved = true;
|
||||
$arg1 = array_shift($args);
|
||||
}
|
||||
|
||||
if (! count($args)) {
|
||||
return $this->createErrorArgument('Missing class name');
|
||||
}
|
||||
|
||||
$configFile = $arg1;
|
||||
switch (file_exists($configFile)) {
|
||||
case true:
|
||||
$config = require $configFile;
|
||||
|
||||
if (! is_array($config)) {
|
||||
return $this->createErrorArgument(sprintf(
|
||||
'Configuration at path "%s" does not return an array.',
|
||||
$configFile
|
||||
));
|
||||
}
|
||||
|
||||
break;
|
||||
case false:
|
||||
// fall-through
|
||||
default:
|
||||
if (! is_writable(dirname($configFile))) {
|
||||
return $this->createErrorArgument(sprintf(
|
||||
'Cannot create configuration at path "%s"; not writable.',
|
||||
$configFile
|
||||
));
|
||||
}
|
||||
|
||||
$config = [];
|
||||
break;
|
||||
}
|
||||
|
||||
$class = array_shift($args);
|
||||
|
||||
if (! class_exists($class)) {
|
||||
return $this->createErrorArgument(sprintf(
|
||||
'Class "%s" does not exist or could not be autoloaded.',
|
||||
$class
|
||||
));
|
||||
}
|
||||
|
||||
return $this->createArguments(self::COMMAND_DUMP, $configFile, $config, $class, $ignoreUnresolved);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $resource Defaults to STDOUT
|
||||
* @return void
|
||||
*/
|
||||
private function help($resource = STDOUT)
|
||||
{
|
||||
$this->helper->writeLine(sprintf(
|
||||
self::HELP_TEMPLATE,
|
||||
$this->scriptName
|
||||
), true, $resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $command
|
||||
* @param string $configFile File from which config originates, and to
|
||||
* which it will be written.
|
||||
* @param array $config Parsed configuration.
|
||||
* @param string $class Name of class to reflect.
|
||||
* @param bool $ignoreUnresolved If to ignore classes with unresolved direct dependencies.
|
||||
* @return \stdClass
|
||||
*/
|
||||
private function createArguments($command, $configFile, $config, $class, $ignoreUnresolved)
|
||||
{
|
||||
return (object) [
|
||||
'command' => $command,
|
||||
'configFile' => $configFile,
|
||||
'config' => $config,
|
||||
'class' => $class,
|
||||
'ignoreUnresolved' => $ignoreUnresolved,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @return \stdClass
|
||||
*/
|
||||
private function createErrorArgument($message)
|
||||
{
|
||||
return (object) [
|
||||
'command' => self::COMMAND_ERROR,
|
||||
'message' => $message,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \stdClass
|
||||
*/
|
||||
private function createHelpArgument()
|
||||
{
|
||||
return (object) [
|
||||
'command' => self::COMMAND_HELP,
|
||||
];
|
||||
}
|
||||
}
|
||||
143
vendor/laminas/laminas-servicemanager/src/Tool/FactoryCreator.php
vendored
Normal file
143
vendor/laminas/laminas-servicemanager/src/Tool/FactoryCreator.php
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Tool;
|
||||
|
||||
use Laminas\ServiceManager\Exception\InvalidArgumentException;
|
||||
use ReflectionClass;
|
||||
use ReflectionParameter;
|
||||
|
||||
class FactoryCreator
|
||||
{
|
||||
const FACTORY_TEMPLATE = <<<'EOT'
|
||||
<?php
|
||||
|
||||
namespace %s;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Laminas\ServiceManager\Factory\FactoryInterface;
|
||||
use %s;
|
||||
|
||||
class %sFactory implements FactoryInterface
|
||||
{
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
* @param string $requestedName
|
||||
* @param null|array $options
|
||||
* @return %s
|
||||
*/
|
||||
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
|
||||
{
|
||||
return new %s(%s);
|
||||
}
|
||||
}
|
||||
|
||||
EOT;
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @return string
|
||||
*/
|
||||
public function createFactory($className)
|
||||
{
|
||||
$class = $this->getClassName($className);
|
||||
|
||||
return sprintf(
|
||||
self::FACTORY_TEMPLATE,
|
||||
str_replace('\\' . $class, '', $className),
|
||||
$className,
|
||||
$class,
|
||||
$class,
|
||||
$class,
|
||||
$this->createArgumentString($className)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $className
|
||||
* @return string
|
||||
*/
|
||||
private function getClassName($className)
|
||||
{
|
||||
$class = substr($className, strrpos($className, '\\') + 1);
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @return array
|
||||
*/
|
||||
private function getConstructorParameters($className)
|
||||
{
|
||||
$reflectionClass = new ReflectionClass($className);
|
||||
|
||||
if (! $reflectionClass || ! $reflectionClass->getConstructor()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$constructorParameters = $reflectionClass->getConstructor()->getParameters();
|
||||
|
||||
if (empty($constructorParameters)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$constructorParameters = array_filter(
|
||||
$constructorParameters,
|
||||
function (ReflectionParameter $argument) {
|
||||
if ($argument->isOptional()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null === $argument->getClass()) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Cannot identify type for constructor argument "%s"; '
|
||||
. 'no type hint, or non-class/interface type hint',
|
||||
$argument->getName()
|
||||
));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (empty($constructorParameters)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_map(function (ReflectionParameter $parameter) {
|
||||
return $parameter->getClass()->getName();
|
||||
}, $constructorParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @return string
|
||||
*/
|
||||
private function createArgumentString($className)
|
||||
{
|
||||
$arguments = array_map(function ($dependency) {
|
||||
return sprintf('$container->get(\\%s::class)', $dependency);
|
||||
}, $this->getConstructorParameters($className));
|
||||
|
||||
switch (count($arguments)) {
|
||||
case 0:
|
||||
return '';
|
||||
case 1:
|
||||
return array_shift($arguments);
|
||||
default:
|
||||
$argumentPad = str_repeat(' ', 12);
|
||||
$closePad = str_repeat(' ', 8);
|
||||
return sprintf(
|
||||
"\n%s%s\n%s",
|
||||
$argumentPad,
|
||||
implode(",\n" . $argumentPad, $arguments),
|
||||
$closePad
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
150
vendor/laminas/laminas-servicemanager/src/Tool/FactoryCreatorCommand.php
vendored
Normal file
150
vendor/laminas/laminas-servicemanager/src/Tool/FactoryCreatorCommand.php
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
|
||||
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
|
||||
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
|
||||
*/
|
||||
|
||||
namespace Laminas\ServiceManager\Tool;
|
||||
|
||||
use Laminas\ServiceManager\Exception;
|
||||
use Laminas\Stdlib\ConsoleHelper;
|
||||
|
||||
class FactoryCreatorCommand
|
||||
{
|
||||
const COMMAND_DUMP = 'dump';
|
||||
const COMMAND_ERROR = 'error';
|
||||
const COMMAND_HELP = 'help';
|
||||
|
||||
const DEFAULT_SCRIPT_NAME = __CLASS__;
|
||||
|
||||
const HELP_TEMPLATE = <<< EOH
|
||||
<info>Usage:</info>
|
||||
|
||||
%s [-h|--help|help] <className>
|
||||
|
||||
<info>Arguments:</info>
|
||||
|
||||
<info>-h|--help|help</info> This usage message
|
||||
<info><className></info> Name of the class to reflect and for which to generate
|
||||
a factory.
|
||||
|
||||
Generates to STDOUT a factory for creating the specified class; this may then
|
||||
be added to your application, and configured as a factory for the class.
|
||||
EOH;
|
||||
|
||||
/**
|
||||
* @var ConsoleHelper
|
||||
*/
|
||||
private $helper;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $scriptName;
|
||||
|
||||
/**
|
||||
* @param string $scriptName
|
||||
* @param ConsoleHelper $helper
|
||||
*/
|
||||
public function __construct($scriptName = self::DEFAULT_SCRIPT_NAME, ConsoleHelper $helper = null)
|
||||
{
|
||||
$this->scriptName = $scriptName;
|
||||
$this->helper = $helper ?: new ConsoleHelper();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $args Argument list, minus script name
|
||||
* @return int Exit status
|
||||
*/
|
||||
public function __invoke(array $args)
|
||||
{
|
||||
$arguments = $this->parseArgs($args);
|
||||
|
||||
switch ($arguments->command) {
|
||||
case self::COMMAND_HELP:
|
||||
$this->help();
|
||||
return 0;
|
||||
case self::COMMAND_ERROR:
|
||||
$this->helper->writeErrorMessage($arguments->message);
|
||||
$this->help(STDERR);
|
||||
return 1;
|
||||
case self::COMMAND_DUMP:
|
||||
// fall-through
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
$generator = new FactoryCreator();
|
||||
try {
|
||||
$factory = $generator->createFactory($arguments->class);
|
||||
} catch (Exception\InvalidArgumentException $e) {
|
||||
$this->helper->writeErrorMessage(sprintf(
|
||||
'Unable to create factory for "%s": %s',
|
||||
$arguments->class,
|
||||
$e->getMessage()
|
||||
));
|
||||
$this->help(STDERR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
$this->helper->write($factory, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $args
|
||||
* @return \stdClass
|
||||
*/
|
||||
private function parseArgs(array $args)
|
||||
{
|
||||
if (! count($args)) {
|
||||
return $this->createArguments(self::COMMAND_HELP);
|
||||
}
|
||||
|
||||
$arg1 = array_shift($args);
|
||||
|
||||
if (in_array($arg1, ['-h', '--help', 'help'], true)) {
|
||||
return $this->createArguments(self::COMMAND_HELP);
|
||||
}
|
||||
|
||||
$class = $arg1;
|
||||
|
||||
if (! class_exists($class)) {
|
||||
return $this->createArguments(self::COMMAND_ERROR, null, sprintf(
|
||||
'Class "%s" does not exist or could not be autoloaded.',
|
||||
$class
|
||||
));
|
||||
}
|
||||
|
||||
return $this->createArguments(self::COMMAND_DUMP, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $resource Defaults to STDOUT
|
||||
* @return void
|
||||
*/
|
||||
private function help($resource = STDOUT)
|
||||
{
|
||||
$this->helper->writeLine(sprintf(
|
||||
self::HELP_TEMPLATE,
|
||||
$this->scriptName
|
||||
), true, $resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $command
|
||||
* @param string|null $class Name of class to reflect.
|
||||
* @param string|null $error Error message, if any.
|
||||
* @return \stdClass
|
||||
*/
|
||||
private function createArguments($command, $class = null, $error = null)
|
||||
{
|
||||
return (object) [
|
||||
'command' => $command,
|
||||
'class' => $class,
|
||||
'message' => $error,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user