first commit

This commit is contained in:
2024-07-15 12:33:27 +02:00
commit ce50ae282b
22084 changed files with 2623791 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument;
interface ArgumentInterface
{
/**
* @return mixed
*/
public function getValue();
}

View File

@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument;
use League\Container\ContainerAwareInterface;
use ReflectionFunctionAbstract;
interface ArgumentResolverInterface extends ContainerAwareInterface
{
public function resolveArguments(array $arguments): array;
public function reflectArguments(ReflectionFunctionAbstract $method, array $args = []): array;
}

View File

@@ -0,0 +1,111 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument;
use League\Container\DefinitionContainerInterface;
use League\Container\Exception\{ContainerException, NotFoundException};
use League\Container\ReflectionContainer;
use Psr\Container\ContainerInterface;
use ReflectionFunctionAbstract;
use ReflectionNamedType;
trait ArgumentResolverTrait
{
public function resolveArguments(array $arguments): array
{
try {
$container = $this->getContainer();
} catch (ContainerException $e) {
$container = ($this instanceof ReflectionContainer) ? $this : null;
}
foreach ($arguments as &$arg) {
// if we have a literal, we don't want to do anything more with it
if ($arg instanceof LiteralArgumentInterface) {
$arg = $arg->getValue();
continue;
}
if ($arg instanceof ArgumentInterface) {
$argValue = $arg->getValue();
} else {
$argValue = $arg;
}
if (!is_string($argValue)) {
continue;
}
// resolve the argument from the container, if it happens to be another
// argument wrapper, use that value
if ($container instanceof ContainerInterface && $container->has($argValue)) {
try {
$arg = $container->get($argValue);
if ($arg instanceof ArgumentInterface) {
$arg = $arg->getValue();
}
continue;
} catch (NotFoundException $e) {
}
}
// if we have a default value, we use that, no more resolution as
// we expect a default/optional argument value to be literal
if ($arg instanceof DefaultValueInterface) {
$arg = $arg->getDefaultValue();
}
}
return $arguments;
}
public function reflectArguments(ReflectionFunctionAbstract $method, array $args = []): array
{
$params = $method->getParameters();
$arguments = [];
foreach ($params as $param) {
$name = $param->getName();
// if we've been given a value for the argument, treat as literal
if (array_key_exists($name, $args)) {
$arguments[] = new LiteralArgument($args[$name]);
continue;
}
$type = $param->getType();
if ($type instanceof ReflectionNamedType) {
// in PHP 8, nullable arguments have "?" prefix
$typeHint = ltrim($type->getName(), '?');
if ($param->isDefaultValueAvailable()) {
$arguments[] = new DefaultValueArgument($typeHint, $param->getDefaultValue());
continue;
}
$arguments[] = new ResolvableArgument($typeHint);
continue;
}
if ($param->isDefaultValueAvailable()) {
$arguments[] = new LiteralArgument($param->getDefaultValue());
continue;
}
throw new NotFoundException(sprintf(
'Unable to resolve a value for parameter (%s) in the function/method (%s)',
$name,
$method->getName()
));
}
return $this->resolveArguments($arguments);
}
abstract public function getContainer(): DefinitionContainerInterface;
}

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument;
class DefaultValueArgument extends ResolvableArgument implements DefaultValueInterface
{
protected $defaultValue;
public function __construct(string $value, $defaultValue = null)
{
$this->defaultValue = $defaultValue;
parent::__construct($value);
}
/**
* @return mixed|null
*/
public function getDefaultValue()
{
return $this->defaultValue;
}
}

View File

@@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument;
interface DefaultValueInterface extends ArgumentInterface
{
/**
* @return mixed
*/
public function getDefaultValue();
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument\Literal;
use League\Container\Argument\LiteralArgument;
class ArrayArgument extends LiteralArgument
{
public function __construct(array $value)
{
parent::__construct($value, LiteralArgument::TYPE_ARRAY);
}
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument\Literal;
use League\Container\Argument\LiteralArgument;
class BooleanArgument extends LiteralArgument
{
public function __construct(bool $value)
{
parent::__construct($value, LiteralArgument::TYPE_BOOL);
}
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument\Literal;
use League\Container\Argument\LiteralArgument;
class CallableArgument extends LiteralArgument
{
public function __construct(callable $value)
{
parent::__construct($value, LiteralArgument::TYPE_CALLABLE);
}
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument\Literal;
use League\Container\Argument\LiteralArgument;
class FloatArgument extends LiteralArgument
{
public function __construct(float $value)
{
parent::__construct($value, LiteralArgument::TYPE_FLOAT);
}
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument\Literal;
use League\Container\Argument\LiteralArgument;
class IntegerArgument extends LiteralArgument
{
public function __construct(int $value)
{
parent::__construct($value, LiteralArgument::TYPE_INT);
}
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument\Literal;
use League\Container\Argument\LiteralArgument;
class ObjectArgument extends LiteralArgument
{
public function __construct(object $value)
{
parent::__construct($value, LiteralArgument::TYPE_OBJECT);
}
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument\Literal;
use League\Container\Argument\LiteralArgument;
class StringArgument extends LiteralArgument
{
public function __construct(string $value)
{
parent::__construct($value, LiteralArgument::TYPE_STRING);
}
}

View File

@@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument;
use InvalidArgumentException;
class LiteralArgument implements LiteralArgumentInterface
{
public const TYPE_ARRAY = 'array';
public const TYPE_BOOL = 'boolean';
public const TYPE_BOOLEAN = 'boolean';
public const TYPE_CALLABLE = 'callable';
public const TYPE_DOUBLE = 'double';
public const TYPE_FLOAT = 'double';
public const TYPE_INT = 'integer';
public const TYPE_INTEGER = 'integer';
public const TYPE_OBJECT = 'object';
public const TYPE_STRING = 'string';
/**
* @var mixed
*/
protected $value;
public function __construct($value, string $type = null)
{
if (
null === $type
|| ($type === self::TYPE_CALLABLE && is_callable($value))
|| ($type === self::TYPE_OBJECT && is_object($value))
|| gettype($value) === $type
) {
$this->value = $value;
} else {
throw new InvalidArgumentException('Incorrect type for value.');
}
}
/**
* {@inheritdoc}
*/
public function getValue()
{
return $this->value;
}
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument;
interface LiteralArgumentInterface extends ArgumentInterface
{
}

View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument;
class ResolvableArgument implements ResolvableArgumentInterface
{
protected $value;
public function __construct(string $value)
{
$this->value = $value;
}
public function getValue(): string
{
return $this->value;
}
}

View File

@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace League\Container\Argument;
interface ResolvableArgumentInterface extends ArgumentInterface
{
public function getValue(): string;
}