Add src/Internal/Vendor/League to source control.

This commit is contained in:
Nestor Soriano 2020-11-05 17:21:38 +01:00
parent 8bb0f196e6
commit 5509e2185c
26 changed files with 1881 additions and 0 deletions

View File

@ -0,0 +1,28 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Argument;
use Automattic\WooCommerce\Internal\Vendor\League\Container\ContainerAwareInterface;
use ReflectionFunctionAbstract;
interface ArgumentResolverInterface extends ContainerAwareInterface
{
/**
* Resolve an array of arguments to their concrete implementations.
*
* @param array $arguments
*
* @return array
*/
public function resolveArguments(array $arguments) : array;
/**
* Resolves the correct arguments to be passed to a method.
*
* @param ReflectionFunctionAbstract $method
* @param array $args
*
* @return array
*/
public function reflectArguments(ReflectionFunctionAbstract $method, array $args = []) : array;
}

View File

@ -0,0 +1,120 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Argument;
use Automattic\WooCommerce\Internal\Vendor\League\Container\Container;
use Automattic\WooCommerce\Internal\Vendor\League\Container\Exception\{ContainerException, NotFoundException};
use Automattic\WooCommerce\Internal\Vendor\League\Container\ReflectionContainer;
use Psr\Container\ContainerInterface;
use ReflectionFunctionAbstract;
use ReflectionParameter;
trait ArgumentResolverTrait
{
/**
* {@inheritdoc}
*/
public function resolveArguments(array $arguments) : array
{
return array_map(function ($argument) {
$justStringValue = false;
if ($argument instanceof RawArgumentInterface) {
return $argument->getValue();
} elseif ($argument instanceof ClassNameInterface) {
$id = $argument->getClassName();
} elseif (!is_string($argument)) {
return $argument;
} else {
$justStringValue = true;
$id = $argument;
}
$container = null;
try {
$container = $this->getLeagueContainer();
} catch (ContainerException $e) {
if ($this instanceof ReflectionContainer) {
$container = $this;
}
}
if ($container !== null) {
try {
return $container->get($id);
} catch (NotFoundException $exception) {
if ($argument instanceof ClassNameWithOptionalValue) {
return $argument->getOptionalValue();
}
if ($justStringValue) {
return $id;
}
throw $exception;
}
}
if ($argument instanceof ClassNameWithOptionalValue) {
return $argument->getOptionalValue();
}
// Just a string value.
return $id;
}, $arguments);
}
/**
* {@inheritdoc}
*/
public function reflectArguments(ReflectionFunctionAbstract $method, array $args = []) : array
{
$arguments = array_map(function (ReflectionParameter $param) use ($method, $args) {
$name = $param->getName();
$type = $param->getType();
if (array_key_exists($name, $args)) {
return new RawArgument($args[$name]);
}
if ($type) {
if (PHP_VERSION_ID >= 70200) {
$typeName = $type->getName();
} else {
$typeName = (string) $type;
}
$typeName = ltrim($typeName, '?');
if ($param->isDefaultValueAvailable()) {
return new ClassNameWithOptionalValue($typeName, $param->getDefaultValue());
}
return new ClassName($typeName);
}
if ($param->isDefaultValueAvailable()) {
return new RawArgument($param->getDefaultValue());
}
throw new NotFoundException(sprintf(
'Unable to resolve a value for parameter (%s) in the function/method (%s)',
$name,
$method->getName()
));
}, $method->getParameters());
return $this->resolveArguments($arguments);
}
/**
* @return ContainerInterface
*/
abstract public function getContainer() : ContainerInterface;
/**
* @return Container
*/
abstract public function getLeagueContainer() : Container;
}

View File

@ -0,0 +1,29 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Argument;
class ClassName implements ClassNameInterface
{
/**
* @var string
*/
protected $value;
/**
* Construct.
*
* @param string $value
*/
public function __construct(string $value)
{
$this->value = $value;
}
/**
* {@inheritdoc}
*/
public function getClassName() : string
{
return $this->value;
}
}

View File

@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Argument;
interface ClassNameInterface
{
/**
* Return the class name.
*
* @return string
*/
public function getClassName() : string;
}

View File

@ -0,0 +1,39 @@
<?php
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Argument;
class ClassNameWithOptionalValue implements ClassNameInterface
{
/**
* @var string
*/
private $className;
/**
* @var mixed
*/
private $optionalValue;
/**
* @param string $className
* @param mixed $optionalValue
*/
public function __construct(string $className, $optionalValue)
{
$this->className = $className;
$this->optionalValue = $optionalValue;
}
/**
* @inheritDoc
*/
public function getClassName(): string
{
return $this->className;
}
public function getOptionalValue()
{
return $this->optionalValue;
}
}

View File

@ -0,0 +1,29 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Argument;
class RawArgument implements RawArgumentInterface
{
/**
* @var mixed
*/
protected $value;
/**
* Construct.
*
* @param mixed $value
*/
public function __construct($value)
{
$this->value = $value;
}
/**
* {@inheritdoc}
*/
public function getValue()
{
return $this->value;
}
}

View File

@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Argument;
interface RawArgumentInterface
{
/**
* Return the value of the raw argument.
*
* @return mixed
*/
public function getValue();
}

View File

@ -0,0 +1,248 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container;
use Automattic\WooCommerce\Internal\Vendor\League\Container\Definition\{DefinitionAggregate, DefinitionInterface, DefinitionAggregateInterface};
use Automattic\WooCommerce\Internal\Vendor\League\Container\Exception\{NotFoundException, ContainerException};
use Automattic\WooCommerce\Internal\Vendor\League\Container\Inflector\{InflectorAggregate, InflectorInterface, InflectorAggregateInterface};
use Automattic\WooCommerce\Internal\Vendor\League\Container\ServiceProvider\{
ServiceProviderAggregate,
ServiceProviderAggregateInterface,
ServiceProviderInterface
};
use Psr\Container\ContainerInterface;
class Container implements ContainerInterface
{
/**
* @var boolean
*/
protected $defaultToShared = false;
/**
* @var DefinitionAggregateInterface
*/
protected $definitions;
/**
* @var ServiceProviderAggregateInterface
*/
protected $providers;
/**
* @var InflectorAggregateInterface
*/
protected $inflectors;
/**
* @var ContainerInterface[]
*/
protected $delegates = [];
/**
* Construct.
*
* @param DefinitionAggregateInterface|null $definitions
* @param ServiceProviderAggregateInterface|null $providers
* @param InflectorAggregateInterface|null $inflectors
*/
public function __construct(
DefinitionAggregateInterface $definitions = null,
ServiceProviderAggregateInterface $providers = null,
InflectorAggregateInterface $inflectors = null
) {
$this->definitions = $definitions ?? new DefinitionAggregate;
$this->providers = $providers ?? new ServiceProviderAggregate;
$this->inflectors = $inflectors ?? new InflectorAggregate;
if ($this->definitions instanceof ContainerAwareInterface) {
$this->definitions->setLeagueContainer($this);
}
if ($this->providers instanceof ContainerAwareInterface) {
$this->providers->setLeagueContainer($this);
}
if ($this->inflectors instanceof ContainerAwareInterface) {
$this->inflectors->setLeagueContainer($this);
}
}
/**
* Add an item to the container.
*
* @param string $id
* @param mixed $concrete
* @param boolean $shared
*
* @return DefinitionInterface
*/
public function add(string $id, $concrete = null, bool $shared = null) : DefinitionInterface
{
$concrete = $concrete ?? $id;
$shared = $shared ?? $this->defaultToShared;
return $this->definitions->add($id, $concrete, $shared);
}
/**
* Proxy to add with shared as true.
*
* @param string $id
* @param mixed $concrete
*
* @return DefinitionInterface
*/
public function share(string $id, $concrete = null) : DefinitionInterface
{
return $this->add($id, $concrete, true);
}
/**
* Whether the container should default to defining shared definitions.
*
* @param boolean $shared
*
* @return self
*/
public function defaultToShared(bool $shared = true) : ContainerInterface
{
$this->defaultToShared = $shared;
return $this;
}
/**
* Get a definition to extend.
*
* @param string $id [description]
*
* @return DefinitionInterface
*/
public function extend(string $id) : DefinitionInterface
{
if ($this->providers->provides($id)) {
$this->providers->register($id);
}
if ($this->definitions->has($id)) {
return $this->definitions->getDefinition($id);
}
throw new NotFoundException(
sprintf('Unable to extend alias (%s) as it is not being managed as a definition', $id)
);
}
/**
* Add a service provider.
*
* @param ServiceProviderInterface|string $provider
*
* @return self
*/
public function addServiceProvider($provider) : self
{
$this->providers->add($provider);
return $this;
}
/**
* {@inheritdoc}
*/
public function get($id, bool $new = false)
{
if ($this->definitions->has($id)) {
$resolved = $this->definitions->resolve($id, $new);
return $this->inflectors->inflect($resolved);
}
if ($this->definitions->hasTag($id)) {
$arrayOf = $this->definitions->resolveTagged($id, $new);
array_walk($arrayOf, function (&$resolved) {
$resolved = $this->inflectors->inflect($resolved);
});
return $arrayOf;
}
if ($this->providers->provides($id)) {
$this->providers->register($id);
if (!$this->definitions->has($id) && !$this->definitions->hasTag($id)) {
throw new ContainerException(sprintf('Service provider lied about providing (%s) service', $id));
}
return $this->get($id, $new);
}
foreach ($this->delegates as $delegate) {
if ($delegate->has($id)) {
$resolved = $delegate->get($id);
return $this->inflectors->inflect($resolved);
}
}
throw new NotFoundException(sprintf('Alias (%s) is not being managed by the container or delegates', $id));
}
/**
* {@inheritdoc}
*/
public function has($id) : bool
{
if ($this->definitions->has($id)) {
return true;
}
if ($this->definitions->hasTag($id)) {
return true;
}
if ($this->providers->provides($id)) {
return true;
}
foreach ($this->delegates as $delegate) {
if ($delegate->has($id)) {
return true;
}
}
return false;
}
/**
* Allows for manipulation of specific types on resolution.
*
* @param string $type
* @param callable|null $callback
*
* @return InflectorInterface
*/
public function inflector(string $type, callable $callback = null) : InflectorInterface
{
return $this->inflectors->add($type, $callback);
}
/**
* Delegate a backup container to be checked for services if it
* cannot be resolved via this container.
*
* @param ContainerInterface $container
*
* @return self
*/
public function delegate(ContainerInterface $container) : self
{
$this->delegates[] = $container;
if ($container instanceof ContainerAwareInterface) {
$container->setLeagueContainer($this);
}
return $this;
}
}

View File

@ -0,0 +1,40 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container;
use Psr\Container\ContainerInterface;
interface ContainerAwareInterface
{
/**
* Set a container
*
* @param ContainerInterface $container
*
* @return self
*/
public function setContainer(ContainerInterface $container) : self;
/**
* Get the container
*
* @return ContainerInterface
*/
public function getContainer() : ContainerInterface;
/**
* Set a container. This will be removed in favour of setContainer receiving Container in next major release.
*
* @param Container $container
*
* @return self
*/
public function setLeagueContainer(Container $container) : self;
/**
* Get the container. This will be removed in favour of getContainer returning Container in next major release.
*
* @return Container
*/
public function getLeagueContainer() : Container;
}

View File

@ -0,0 +1,76 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container;
use Automattic\WooCommerce\Internal\Vendor\League\Container\Exception\ContainerException;
use Psr\Container\ContainerInterface;
trait ContainerAwareTrait
{
/**
* @var ContainerInterface
*/
protected $container;
/**
* @var Container
*/
protected $leagueContainer;
/**
* Set a container.
*
* @param ContainerInterface $container
*
* @return self
*/
public function setContainer(ContainerInterface $container) : ContainerAwareInterface
{
$this->container = $container;
return $this;
}
/**
* Get the container.
*
* @return ContainerInterface
*/
public function getContainer() : ContainerInterface
{
if ($this->container instanceof ContainerInterface) {
return $this->container;
}
throw new ContainerException('No container implementation has been set.');
}
/**
* Set a container.
*
* @param Container $container
*
* @return self
*/
public function setLeagueContainer(Container $container) : ContainerAwareInterface
{
$this->container = $container;
$this->leagueContainer = $container;
return $this;
}
/**
* Get the container.
*
* @return Container
*/
public function getLeagueContainer() : Container
{
if ($this->leagueContainer instanceof Container) {
return $this->leagueContainer;
}
throw new ContainerException('No container implementation has been set.');
}
}

View File

@ -0,0 +1,274 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Definition;
use Automattic\WooCommerce\Internal\Vendor\League\Container\Argument\{
ArgumentResolverInterface, ArgumentResolverTrait, ClassNameInterface, RawArgumentInterface
};
use Automattic\WooCommerce\Internal\Vendor\League\Container\ContainerAwareTrait;
use ReflectionClass;
use ReflectionException;
class Definition implements ArgumentResolverInterface, DefinitionInterface
{
use ArgumentResolverTrait;
use ContainerAwareTrait;
/**
* @var string
*/
protected $alias;
/**
* @var mixed
*/
protected $concrete;
/**
* @var boolean
*/
protected $shared = false;
/**
* @var array
*/
protected $tags = [];
/**
* @var array
*/
protected $arguments = [];
/**
* @var array
*/
protected $methods = [];
/**
* @var mixed
*/
protected $resolved;
/**
* Constructor.
*
* @param string $id
* @param mixed $concrete
*/
public function __construct(string $id, $concrete = null)
{
$concrete = $concrete ?? $id;
$this->alias = $id;
$this->concrete = $concrete;
}
/**
* {@inheritdoc}
*/
public function addTag(string $tag) : DefinitionInterface
{
$this->tags[$tag] = true;
return $this;
}
/**
* {@inheritdoc}
*/
public function hasTag(string $tag) : bool
{
return isset($this->tags[$tag]);
}
/**
* {@inheritdoc}
*/
public function setAlias(string $id) : DefinitionInterface
{
$this->alias = $id;
return $this;
}
/**
* {@inheritdoc}
*/
public function getAlias() : string
{
return $this->alias;
}
/**
* {@inheritdoc}
*/
public function setShared(bool $shared = true) : DefinitionInterface
{
$this->shared = $shared;
return $this;
}
/**
* {@inheritdoc}
*/
public function isShared() : bool
{
return $this->shared;
}
/**
* {@inheritdoc}
*/
public function getConcrete()
{
return $this->concrete;
}
/**
* {@inheritdoc}
*/
public function setConcrete($concrete) : DefinitionInterface
{
$this->concrete = $concrete;
$this->resolved = null;
return $this;
}
/**
* {@inheritdoc}
*/
public function addArgument($arg) : DefinitionInterface
{
$this->arguments[] = $arg;
return $this;
}
/**
* {@inheritdoc}
*/
public function addArguments(array $args) : DefinitionInterface
{
foreach ($args as $arg) {
$this->addArgument($arg);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function addMethodCall(string $method, array $args = []) : DefinitionInterface
{
$this->methods[] = [
'method' => $method,
'arguments' => $args
];
return $this;
}
/**
* {@inheritdoc}
*/
public function addMethodCalls(array $methods = []) : DefinitionInterface
{
foreach ($methods as $method => $args) {
$this->addMethodCall($method, $args);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function resolve(bool $new = false)
{
$concrete = $this->concrete;
if ($this->isShared() && $this->resolved !== null && $new === false) {
return $this->resolved;
}
if (is_callable($concrete)) {
$concrete = $this->resolveCallable($concrete);
}
if ($concrete instanceof RawArgumentInterface) {
$this->resolved = $concrete->getValue();
return $concrete->getValue();
}
if ($concrete instanceof ClassNameInterface) {
$concrete = $concrete->getClassName();
}
if (is_string($concrete) && class_exists($concrete)) {
$concrete = $this->resolveClass($concrete);
}
if (is_object($concrete)) {
$concrete = $this->invokeMethods($concrete);
}
$this->resolved = $concrete;
return $concrete;
}
/**
* Resolve a callable.
*
* @param callable $concrete
*
* @return mixed
*/
protected function resolveCallable(callable $concrete)
{
$resolved = $this->resolveArguments($this->arguments);
return call_user_func_array($concrete, $resolved);
}
/**
* Resolve a class.
*
* @param string $concrete
*
* @return object
*
* @throws ReflectionException
*/
protected function resolveClass(string $concrete)
{
$resolved = $this->resolveArguments($this->arguments);
$reflection = new ReflectionClass($concrete);
return $reflection->newInstanceArgs($resolved);
}
/**
* Invoke methods on resolved instance.
*
* @param object $instance
*
* @return object
*/
protected function invokeMethods($instance)
{
foreach ($this->methods as $method) {
$args = $this->resolveArguments($method['arguments']);
/** @var callable $callable */
$callable = [$instance, $method['method']];
call_user_func_array($callable, $args);
}
return $instance;
}
}

View File

@ -0,0 +1,124 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Definition;
use Generator;
use Automattic\WooCommerce\Internal\Vendor\League\Container\ContainerAwareTrait;
use Automattic\WooCommerce\Internal\Vendor\League\Container\Exception\NotFoundException;
class DefinitionAggregate implements DefinitionAggregateInterface
{
use ContainerAwareTrait;
/**
* @var DefinitionInterface[]
*/
protected $definitions = [];
/**
* Construct.
*
* @param DefinitionInterface[] $definitions
*/
public function __construct(array $definitions = [])
{
$this->definitions = array_filter($definitions, function ($definition) {
return ($definition instanceof DefinitionInterface);
});
}
/**
* {@inheritdoc}
*/
public function add(string $id, $definition, bool $shared = false) : DefinitionInterface
{
if (!$definition instanceof DefinitionInterface) {
$definition = new Definition($id, $definition);
}
$this->definitions[] = $definition
->setAlias($id)
->setShared($shared)
;
return $definition;
}
/**
* {@inheritdoc}
*/
public function has(string $id) : bool
{
foreach ($this->getIterator() as $definition) {
if ($id === $definition->getAlias()) {
return true;
}
}
return false;
}
/**
* {@inheritdoc}
*/
public function hasTag(string $tag) : bool
{
foreach ($this->getIterator() as $definition) {
if ($definition->hasTag($tag)) {
return true;
}
}
return false;
}
/**
* {@inheritdoc}
*/
public function getDefinition(string $id) : DefinitionInterface
{
foreach ($this->getIterator() as $definition) {
if ($id === $definition->getAlias()) {
return $definition->setLeagueContainer($this->getLeagueContainer());
}
}
throw new NotFoundException(sprintf('Alias (%s) is not being handled as a definition.', $id));
}
/**
* {@inheritdoc}
*/
public function resolve(string $id, bool $new = false)
{
return $this->getDefinition($id)->resolve($new);
}
/**
* {@inheritdoc}
*/
public function resolveTagged(string $tag, bool $new = false) : array
{
$arrayOf = [];
foreach ($this->getIterator() as $definition) {
if ($definition->hasTag($tag)) {
$arrayOf[] = $definition->setLeagueContainer($this->getLeagueContainer())->resolve($new);
}
}
return $arrayOf;
}
/**
* {@inheritdoc}
*/
public function getIterator() : Generator
{
$count = count($this->definitions);
for ($i = 0; $i < $count; $i++) {
yield $this->definitions[$i];
}
}
}

View File

@ -0,0 +1,67 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Definition;
use IteratorAggregate;
use Automattic\WooCommerce\Internal\Vendor\League\Container\ContainerAwareInterface;
interface DefinitionAggregateInterface extends ContainerAwareInterface, IteratorAggregate
{
/**
* Add a definition to the aggregate.
*
* @param string $id
* @param mixed $definition
* @param boolean $shared
*
* @return DefinitionInterface
*/
public function add(string $id, $definition, bool $shared = false) : DefinitionInterface;
/**
* Checks whether alias exists as definition.
*
* @param string $id
*
* @return boolean
*/
public function has(string $id) : bool;
/**
* Checks whether tag exists as definition.
*
* @param string $tag
*
* @return boolean
*/
public function hasTag(string $tag) : bool;
/**
* Get the definition to be extended.
*
* @param string $id
*
* @return DefinitionInterface
*/
public function getDefinition(string $id) : DefinitionInterface;
/**
* Resolve and build a concrete value from an id/alias.
*
* @param string $id
* @param boolean $new
*
* @return mixed
*/
public function resolve(string $id, bool $new = false);
/**
* Resolve and build an array of concrete values from a tag.
*
* @param string $tag
* @param boolean $new
*
* @return mixed
*/
public function resolveTagged(string $tag, bool $new = false);
}

View File

@ -0,0 +1,120 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Definition;
use Automattic\WooCommerce\Internal\Vendor\League\Container\ContainerAwareInterface;
interface DefinitionInterface extends ContainerAwareInterface
{
/**
* Add a tag to the definition.
*
* @param string $tag
*
* @return self
*/
public function addTag(string $tag) : DefinitionInterface;
/**
* Does the definition have a tag?
*
* @param string $tag
*
* @return boolean
*/
public function hasTag(string $tag) : bool;
/**
* Set the alias of the definition.
*
* @param string $id
*
* @return DefinitionInterface
*/
public function setAlias(string $id) : DefinitionInterface;
/**
* Get the alias of the definition.
*
* @return string
*/
public function getAlias() : string;
/**
* Set whether this is a shared definition.
*
* @param boolean $shared
*
* @return self
*/
public function setShared(bool $shared) : DefinitionInterface;
/**
* Is this a shared definition?
*
* @return boolean
*/
public function isShared() : bool;
/**
* Get the concrete of the definition.
*
* @return mixed
*/
public function getConcrete();
/**
* Set the concrete of the definition.
*
* @param mixed $concrete
*
* @return DefinitionInterface
*/
public function setConcrete($concrete) : DefinitionInterface;
/**
* Add an argument to be injected.
*
* @param mixed $arg
*
* @return self
*/
public function addArgument($arg) : DefinitionInterface;
/**
* Add multiple arguments to be injected.
*
* @param array $args
*
* @return self
*/
public function addArguments(array $args) : DefinitionInterface;
/**
* Add a method to be invoked
*
* @param string $method
* @param array $args
*
* @return self
*/
public function addMethodCall(string $method, array $args = []) : DefinitionInterface;
/**
* Add multiple methods to be invoked
*
* @param array $methods
*
* @return self
*/
public function addMethodCalls(array $methods = []) : DefinitionInterface;
/**
* Handle instantiation and manipulation of value and return.
*
* @param boolean $new
*
* @return mixed
*/
public function resolve(bool $new = false);
}

View File

@ -0,0 +1,10 @@
<?php
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Exception;
use Psr\Container\ContainerExceptionInterface;
use RuntimeException;
class ContainerException extends RuntimeException implements ContainerExceptionInterface
{
}

View File

@ -0,0 +1,10 @@
<?php
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Exception;
use Psr\Container\NotFoundExceptionInterface;
use InvalidArgumentException;
class NotFoundException extends InvalidArgumentException implements NotFoundExceptionInterface
{
}

View File

@ -0,0 +1,123 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Inflector;
use Automattic\WooCommerce\Internal\Vendor\League\Container\Argument\ArgumentResolverInterface;
use Automattic\WooCommerce\Internal\Vendor\League\Container\Argument\ArgumentResolverTrait;
use Automattic\WooCommerce\Internal\Vendor\League\Container\ContainerAwareTrait;
class Inflector implements ArgumentResolverInterface, InflectorInterface
{
use ArgumentResolverTrait;
use ContainerAwareTrait;
/**
* @var string
*/
protected $type;
/**
* @var callable|null
*/
protected $callback;
/**
* @var array
*/
protected $methods = [];
/**
* @var array
*/
protected $properties = [];
/**
* Construct.
*
* @param string $type
* @param callable|null $callback
*/
public function __construct(string $type, callable $callback = null)
{
$this->type = $type;
$this->callback = $callback;
}
/**
* {@inheritdoc}
*/
public function getType() : string
{
return $this->type;
}
/**
* {@inheritdoc}
*/
public function invokeMethod(string $name, array $args) : InflectorInterface
{
$this->methods[$name] = $args;
return $this;
}
/**
* {@inheritdoc}
*/
public function invokeMethods(array $methods) : InflectorInterface
{
foreach ($methods as $name => $args) {
$this->invokeMethod($name, $args);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function setProperty(string $property, $value) : InflectorInterface
{
$this->properties[$property] = $this->resolveArguments([$value])[0];
return $this;
}
/**
* {@inheritdoc}
*/
public function setProperties(array $properties) : InflectorInterface
{
foreach ($properties as $property => $value) {
$this->setProperty($property, $value);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function inflect($object)
{
$properties = $this->resolveArguments(array_values($this->properties));
$properties = array_combine(array_keys($this->properties), $properties);
// array_combine() can technically return false
foreach ($properties ?: [] as $property => $value) {
$object->{$property} = $value;
}
foreach ($this->methods as $method => $args) {
$args = $this->resolveArguments($args);
/** @var callable $callable */
$callable = [$object, $method];
call_user_func_array($callable, $args);
}
if ($this->callback !== null) {
call_user_func($this->callback, $object);
}
}
}

View File

@ -0,0 +1,58 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Inflector;
use Generator;
use Automattic\WooCommerce\Internal\Vendor\League\Container\ContainerAwareTrait;
class InflectorAggregate implements InflectorAggregateInterface
{
use ContainerAwareTrait;
/**
* @var Inflector[]
*/
protected $inflectors = [];
/**
* {@inheritdoc}
*/
public function add(string $type, callable $callback = null) : Inflector
{
$inflector = new Inflector($type, $callback);
$this->inflectors[] = $inflector;
return $inflector;
}
/**
* {@inheritdoc}
*/
public function getIterator() : Generator
{
$count = count($this->inflectors);
for ($i = 0; $i < $count; $i++) {
yield $this->inflectors[$i];
}
}
/**
* {@inheritdoc}
*/
public function inflect($object)
{
foreach ($this->getIterator() as $inflector) {
$type = $inflector->getType();
if (! $object instanceof $type) {
continue;
}
$inflector->setLeagueContainer($this->getLeagueContainer());
$inflector->inflect($object);
}
return $object;
}
}

View File

@ -0,0 +1,27 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Inflector;
use IteratorAggregate;
use Automattic\WooCommerce\Internal\Vendor\League\Container\ContainerAwareInterface;
interface InflectorAggregateInterface extends ContainerAwareInterface, IteratorAggregate
{
/**
* Add an inflector to the aggregate.
*
* @param string $type
* @param callable $callback
*
* @return Inflector
*/
public function add(string $type, callable $callback = null) : Inflector;
/**
* Applies all inflectors to an object.
*
* @param object $object
* @return object
*/
public function inflect($object);
}

View File

@ -0,0 +1,60 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\Inflector;
interface InflectorInterface
{
/**
* Get the type.
*
* @return string
*/
public function getType() : string;
/**
* Defines a method to be invoked on the subject object.
*
* @param string $name
* @param array $args
*
* @return self
*/
public function invokeMethod(string $name, array $args) : InflectorInterface;
/**
* Defines multiple methods to be invoked on the subject object.
*
* @param array $methods
*
* @return self
*/
public function invokeMethods(array $methods) : InflectorInterface;
/**
* Defines a property to be set on the subject object.
*
* @param string $property
* @param mixed $value
*
* @return self
*/
public function setProperty(string $property, $value) : InflectorInterface;
/**
* Defines multiple properties to be set on the subject object.
*
* @param array $properties
*
* @return self
*/
public function setProperties(array $properties) : InflectorInterface;
/**
* Apply inflections to an object.
*
* @param object $object
*
* @return void
*/
public function inflect($object);
}

View File

@ -0,0 +1,125 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container;
use Automattic\WooCommerce\Internal\Vendor\League\Container\Argument\{ArgumentResolverInterface, ArgumentResolverTrait};
use Automattic\WooCommerce\Internal\Vendor\League\Container\Exception\NotFoundException;
use Psr\Container\ContainerInterface;
use ReflectionClass;
use ReflectionException;
use ReflectionFunction;
use ReflectionMethod;
class ReflectionContainer implements ArgumentResolverInterface, ContainerInterface
{
use ArgumentResolverTrait;
use ContainerAwareTrait;
/**
* @var boolean
*/
protected $cacheResolutions = false;
/**
* Cache of resolutions.
*
* @var array
*/
protected $cache = [];
/**
* {@inheritdoc}
*
* @throws ReflectionException
*/
public function get($id, array $args = [])
{
if ($this->cacheResolutions === true && array_key_exists($id, $this->cache)) {
return $this->cache[$id];
}
if (! $this->has($id)) {
throw new NotFoundException(
sprintf('Alias (%s) is not an existing class and therefore cannot be resolved', $id)
);
}
$reflector = new ReflectionClass($id);
$construct = $reflector->getConstructor();
$resolution = $construct === null
? new $id
: $resolution = $reflector->newInstanceArgs($this->reflectArguments($construct, $args))
;
if ($this->cacheResolutions === true) {
$this->cache[$id] = $resolution;
}
return $resolution;
}
/**
* {@inheritdoc}
*/
public function has($id) : bool
{
return class_exists($id);
}
/**
* Invoke a callable via the container.
*
* @param callable $callable
* @param array $args
*
* @return mixed
*
* @throws ReflectionException
*/
public function call(callable $callable, array $args = [])
{
if (is_string($callable) && strpos($callable, '::') !== false) {
$callable = explode('::', $callable);
}
if (is_array($callable)) {
if (is_string($callable[0])) {
$callable[0] = $this->getContainer()->get($callable[0]);
}
$reflection = new ReflectionMethod($callable[0], $callable[1]);
if ($reflection->isStatic()) {
$callable[0] = null;
}
return $reflection->invokeArgs($callable[0], $this->reflectArguments($reflection, $args));
}
if (is_object($callable)) {
$reflection = new ReflectionMethod($callable, '__invoke');
return $reflection->invokeArgs($callable, $this->reflectArguments($reflection, $args));
}
$reflection = new ReflectionFunction(\Closure::fromCallable($callable));
return $reflection->invokeArgs($this->reflectArguments($reflection, $args));
}
/**
* Whether the container should default to caching resolutions and returning
* the cache on following calls.
*
* @param boolean $option
*
* @return self
*/
public function cacheResolutions(bool $option = true) : ContainerInterface
{
$this->cacheResolutions = $option;
return $this;
}
}

View File

@ -0,0 +1,46 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\ServiceProvider;
use Automattic\WooCommerce\Internal\Vendor\League\Container\ContainerAwareTrait;
abstract class AbstractServiceProvider implements ServiceProviderInterface
{
use ContainerAwareTrait;
/**
* @var array
*/
protected $provides = [];
/**
* @var string
*/
protected $identifier;
/**
* {@inheritdoc}
*/
public function provides(string $alias) : bool
{
return in_array($alias, $this->provides, true);
}
/**
* {@inheritdoc}
*/
public function setIdentifier(string $id) : ServiceProviderInterface
{
$this->identifier = $id;
return $this;
}
/**
* {@inheritdoc}
*/
public function getIdentifier() : string
{
return $this->identifier ?? get_class($this);
}
}

View File

@ -0,0 +1,14 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\ServiceProvider;
interface BootableServiceProviderInterface extends ServiceProviderInterface
{
/**
* Method will be invoked on registration of a service provider implementing
* this interface. Provides ability for eager loading of Service Providers.
*
* @return void
*/
public function boot();
}

View File

@ -0,0 +1,106 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\ServiceProvider;
use Generator;
use Automattic\WooCommerce\Internal\Vendor\League\Container\{ContainerAwareInterface, ContainerAwareTrait};
use Automattic\WooCommerce\Internal\Vendor\League\Container\Exception\ContainerException;
class ServiceProviderAggregate implements ServiceProviderAggregateInterface
{
use ContainerAwareTrait;
/**
* @var ServiceProviderInterface[]
*/
protected $providers = [];
/**
* @var array
*/
protected $registered = [];
/**
* {@inheritdoc}
*/
public function add($provider) : ServiceProviderAggregateInterface
{
if (is_string($provider) && $this->getContainer()->has($provider)) {
$provider = $this->getContainer()->get($provider);
} elseif (is_string($provider) && class_exists($provider)) {
$provider = new $provider;
}
if (in_array($provider, $this->providers, true)) {
return $this;
}
if ($provider instanceof ContainerAwareInterface) {
$provider->setLeagueContainer($this->getLeagueContainer());
}
if ($provider instanceof BootableServiceProviderInterface) {
$provider->boot();
}
if ($provider instanceof ServiceProviderInterface) {
$this->providers[] = $provider;
return $this;
}
throw new ContainerException(
'A service provider must be a fully qualified class name or instance ' .
'of (\Automattic\WooCommerce\Internal\Vendor\League\Container\ServiceProvider\ServiceProviderInterface)'
);
}
/**
* {@inheritdoc}
*/
public function provides(string $service) : bool
{
foreach ($this->getIterator() as $provider) {
if ($provider->provides($service)) {
return true;
}
}
return false;
}
/**
* {@inheritdoc}
*/
public function getIterator() : Generator
{
$count = count($this->providers);
for ($i = 0; $i < $count; $i++) {
yield $this->providers[$i];
}
}
/**
* {@inheritdoc}
*/
public function register(string $service)
{
if (false === $this->provides($service)) {
throw new ContainerException(
sprintf('(%s) is not provided by a service provider', $service)
);
}
foreach ($this->getIterator() as $provider) {
if (in_array($provider->getIdentifier(), $this->registered, true)) {
continue;
}
if ($provider->provides($service)) {
$provider->register();
$this->registered[] = $provider->getIdentifier();
}
}
}
}

View File

@ -0,0 +1,36 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\ServiceProvider;
use IteratorAggregate;
use Automattic\WooCommerce\Internal\Vendor\League\Container\ContainerAwareInterface;
interface ServiceProviderAggregateInterface extends ContainerAwareInterface, IteratorAggregate
{
/**
* Add a service provider to the aggregate.
*
* @param string|ServiceProviderInterface $provider
*
* @return self
*/
public function add($provider) : ServiceProviderAggregateInterface;
/**
* Determines whether a service is provided by the aggregate.
*
* @param string $service
*
* @return boolean
*/
public function provides(string $service) : bool;
/**
* Invokes the register method of a provider that provides a specific service.
*
* @param string $service
*
* @return void
*/
public function register(string $service);
}

View File

@ -0,0 +1,46 @@
<?php declare(strict_types=1);
namespace Automattic\WooCommerce\Internal\Vendor\League\Container\ServiceProvider;
use Automattic\WooCommerce\Internal\Vendor\League\Container\ContainerAwareInterface;
interface ServiceProviderInterface extends ContainerAwareInterface
{
/**
* Returns a boolean if checking whether this provider provides a specific
* service or returns an array of provided services if no argument passed.
*
* @param string $service
*
* @return boolean
*/
public function provides(string $service) : bool;
/**
* Use the register method to register items with the container via the
* protected $this->leagueContainer property or the `getLeagueContainer` method
* from the ContainerAwareTrait.
*
* @return void
*/
public function register();
/**
* Set a custom id for the service provider. This enables
* registering the same service provider multiple times.
*
* @param string $id
*
* @return self
*/
public function setIdentifier(string $id) : ServiceProviderInterface;
/**
* The id of the service provider uniquely identifies it, so
* that we can quickly determine if it has already been registered.
* Defaults to get_class($provider).
*
* @return string
*/
public function getIdentifier() : string;
}