mirror of
https://github.com/danog/Valinor.git
synced 2024-11-30 04:39:05 +01:00
misc: introduce functions container to wrap definition handling
This commit is contained in:
parent
fdef93074c
commit
fd11177b06
20
src/Definition/Exception/CallbackNotFound.php
Normal file
20
src/Definition/Exception/CallbackNotFound.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace CuyZ\Valinor\Definition\Exception;
|
||||||
|
|
||||||
|
use CuyZ\Valinor\Definition\FunctionDefinition;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
final class CallbackNotFound extends RuntimeException
|
||||||
|
{
|
||||||
|
public function __construct(FunctionDefinition $function)
|
||||||
|
{
|
||||||
|
parent::__construct(
|
||||||
|
"The callback associated to `{$function->signature()}` could not be found.",
|
||||||
|
1647523495
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
22
src/Definition/Exception/FunctionNotFound.php
Normal file
22
src/Definition/Exception/FunctionNotFound.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace CuyZ\Valinor\Definition\Exception;
|
||||||
|
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
final class FunctionNotFound extends RuntimeException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string|int $key
|
||||||
|
*/
|
||||||
|
public function __construct($key)
|
||||||
|
{
|
||||||
|
parent::__construct(
|
||||||
|
"The function `$key` was not found.",
|
||||||
|
1647523444
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
89
src/Definition/FunctionsContainer.php
Normal file
89
src/Definition/FunctionsContainer.php
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace CuyZ\Valinor\Definition;
|
||||||
|
|
||||||
|
use CuyZ\Valinor\Definition\Exception\CallbackNotFound;
|
||||||
|
use CuyZ\Valinor\Definition\Exception\FunctionNotFound;
|
||||||
|
use CuyZ\Valinor\Definition\Repository\FunctionDefinitionRepository;
|
||||||
|
use IteratorAggregate;
|
||||||
|
use Traversable;
|
||||||
|
|
||||||
|
use function array_keys;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @implements IteratorAggregate<FunctionDefinition>
|
||||||
|
*/
|
||||||
|
final class FunctionsContainer implements IteratorAggregate
|
||||||
|
{
|
||||||
|
private FunctionDefinitionRepository $functionDefinitionRepository;
|
||||||
|
|
||||||
|
/** @var array<callable> */
|
||||||
|
private array $callables;
|
||||||
|
|
||||||
|
/** @var array<array{definition: FunctionDefinition, callback: callable}> */
|
||||||
|
private array $functions = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<callable> $callables
|
||||||
|
*/
|
||||||
|
public function __construct(FunctionDefinitionRepository $functionDefinitionRepository, array $callables)
|
||||||
|
{
|
||||||
|
$this->functionDefinitionRepository = $functionDefinitionRepository;
|
||||||
|
$this->callables = $callables;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|int $key
|
||||||
|
*/
|
||||||
|
public function has($key): bool
|
||||||
|
{
|
||||||
|
return isset($this->callables[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|int $key
|
||||||
|
*/
|
||||||
|
public function get($key): FunctionDefinition
|
||||||
|
{
|
||||||
|
if (! $this->has($key)) {
|
||||||
|
throw new FunctionNotFound($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->function($key)['definition'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function callback(FunctionDefinition $function): callable
|
||||||
|
{
|
||||||
|
foreach ($this->functions as $data) {
|
||||||
|
if ($function === $data['definition']) {
|
||||||
|
return $data['callback'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new CallbackNotFound($function);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIterator(): Traversable
|
||||||
|
{
|
||||||
|
foreach (array_keys($this->callables) as $key) {
|
||||||
|
yield $key => $this->function($key)['definition'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|int $key
|
||||||
|
* @return array{definition: FunctionDefinition, callback: callable}
|
||||||
|
*/
|
||||||
|
private function function($key): array
|
||||||
|
{
|
||||||
|
/** @infection-ignore-all */
|
||||||
|
return $this->functions[$key] ??= [
|
||||||
|
'callback' => $this->callables[$key],
|
||||||
|
'definition' => $this->functionDefinitionRepository->for($this->callables[$key]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ use CuyZ\Valinor\Cache\RuntimeCache;
|
|||||||
use CuyZ\Valinor\Cache\VersionedCache;
|
use CuyZ\Valinor\Cache\VersionedCache;
|
||||||
use CuyZ\Valinor\Definition\ClassDefinition;
|
use CuyZ\Valinor\Definition\ClassDefinition;
|
||||||
use CuyZ\Valinor\Definition\FunctionDefinition;
|
use CuyZ\Valinor\Definition\FunctionDefinition;
|
||||||
|
use CuyZ\Valinor\Definition\FunctionsContainer;
|
||||||
use CuyZ\Valinor\Definition\Repository\AttributesRepository;
|
use CuyZ\Valinor\Definition\Repository\AttributesRepository;
|
||||||
use CuyZ\Valinor\Definition\Repository\Cache\CacheClassDefinitionRepository;
|
use CuyZ\Valinor\Definition\Repository\Cache\CacheClassDefinitionRepository;
|
||||||
use CuyZ\Valinor\Definition\Repository\Cache\CacheFunctionDefinitionRepository;
|
use CuyZ\Valinor\Definition\Repository\Cache\CacheFunctionDefinitionRepository;
|
||||||
@ -124,17 +125,21 @@ final class Container
|
|||||||
|
|
||||||
$builder = new InterfaceNodeBuilder(
|
$builder = new InterfaceNodeBuilder(
|
||||||
$builder,
|
$builder,
|
||||||
$this->get(FunctionDefinitionRepository::class),
|
new FunctionsContainer(
|
||||||
|
$this->get(FunctionDefinitionRepository::class),
|
||||||
|
$settings->interfaceMapping
|
||||||
|
),
|
||||||
$this->get(TypeParser::class),
|
$this->get(TypeParser::class),
|
||||||
$settings->interfaceMapping,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$builder = new CasterProxyNodeBuilder($builder);
|
$builder = new CasterProxyNodeBuilder($builder);
|
||||||
$builder = new VisitorNodeBuilder($builder, $settings->nodeVisitors);
|
$builder = new VisitorNodeBuilder($builder, $settings->nodeVisitors);
|
||||||
$builder = new ValueAlteringNodeBuilder(
|
$builder = new ValueAlteringNodeBuilder(
|
||||||
$builder,
|
$builder,
|
||||||
$this->get(FunctionDefinitionRepository::class),
|
new FunctionsContainer(
|
||||||
$settings->valueModifier
|
$this->get(FunctionDefinitionRepository::class),
|
||||||
|
$settings->valueModifier
|
||||||
|
)
|
||||||
);
|
);
|
||||||
$builder = new ShellVisitorNodeBuilder($builder, $this->get(ShellVisitor::class));
|
$builder = new ShellVisitorNodeBuilder($builder, $this->get(ShellVisitor::class));
|
||||||
|
|
||||||
@ -150,9 +155,11 @@ final class Container
|
|||||||
|
|
||||||
$factory = new ObjectBindingBuilderFactory(
|
$factory = new ObjectBindingBuilderFactory(
|
||||||
$factory,
|
$factory,
|
||||||
$this->get(FunctionDefinitionRepository::class),
|
|
||||||
$this->get(ObjectBuilderFilterer::class),
|
$this->get(ObjectBuilderFilterer::class),
|
||||||
$settings->objectBinding,
|
new FunctionsContainer(
|
||||||
|
$this->get(FunctionDefinitionRepository::class),
|
||||||
|
$settings->objectBinding
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return new AttributeObjectBuilderFactory($factory);
|
return new AttributeObjectBuilderFactory($factory);
|
||||||
|
@ -5,6 +5,8 @@ declare(strict_types=1);
|
|||||||
namespace CuyZ\Valinor\Library;
|
namespace CuyZ\Valinor\Library;
|
||||||
|
|
||||||
use CuyZ\Valinor\Mapper\Tree\Node;
|
use CuyZ\Valinor\Mapper\Tree\Node;
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use DateTimeInterface;
|
||||||
|
|
||||||
use function sys_get_temp_dir;
|
use function sys_get_temp_dir;
|
||||||
|
|
||||||
@ -30,5 +32,6 @@ final class Settings
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->cacheDir = sys_get_temp_dir();
|
$this->cacheDir = sys_get_temp_dir();
|
||||||
|
$this->interfaceMapping[DateTimeInterface::class] = static fn () => DateTimeImmutable::class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace CuyZ\Valinor\Mapper\Object\Factory;
|
namespace CuyZ\Valinor\Mapper\Object\Factory;
|
||||||
|
|
||||||
use CuyZ\Valinor\Definition\ClassDefinition;
|
use CuyZ\Valinor\Definition\ClassDefinition;
|
||||||
use CuyZ\Valinor\Definition\FunctionDefinition;
|
use CuyZ\Valinor\Definition\FunctionsContainer;
|
||||||
use CuyZ\Valinor\Definition\Repository\FunctionDefinitionRepository;
|
|
||||||
use CuyZ\Valinor\Mapper\Object\CallbackObjectBuilder;
|
use CuyZ\Valinor\Mapper\Object\CallbackObjectBuilder;
|
||||||
use CuyZ\Valinor\Mapper\Object\ObjectBuilder;
|
use CuyZ\Valinor\Mapper\Object\ObjectBuilder;
|
||||||
use CuyZ\Valinor\Mapper\Object\ObjectBuilderFilterer;
|
use CuyZ\Valinor\Mapper\Object\ObjectBuilderFilterer;
|
||||||
@ -16,38 +15,27 @@ final class ObjectBindingBuilderFactory implements ObjectBuilderFactory
|
|||||||
{
|
{
|
||||||
private ObjectBuilderFactory $delegate;
|
private ObjectBuilderFactory $delegate;
|
||||||
|
|
||||||
private FunctionDefinitionRepository $functionDefinitionRepository;
|
|
||||||
|
|
||||||
private ObjectBuilderFilterer $objectBuilderFilterer;
|
private ObjectBuilderFilterer $objectBuilderFilterer;
|
||||||
|
|
||||||
/** @var list<callable> */
|
private FunctionsContainer $functions;
|
||||||
private array $callbacks;
|
|
||||||
|
|
||||||
/** @var list<FunctionDefinition> */
|
|
||||||
private array $functions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param list<callable> $callbacks
|
|
||||||
*/
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ObjectBuilderFactory $delegate,
|
ObjectBuilderFactory $delegate,
|
||||||
FunctionDefinitionRepository $functionDefinitionRepository,
|
|
||||||
ObjectBuilderFilterer $objectBuilderFilterer,
|
ObjectBuilderFilterer $objectBuilderFilterer,
|
||||||
array $callbacks
|
FunctionsContainer $functions
|
||||||
) {
|
) {
|
||||||
$this->delegate = $delegate;
|
$this->delegate = $delegate;
|
||||||
$this->functionDefinitionRepository = $functionDefinitionRepository;
|
|
||||||
$this->objectBuilderFilterer = $objectBuilderFilterer;
|
$this->objectBuilderFilterer = $objectBuilderFilterer;
|
||||||
$this->callbacks = $callbacks;
|
$this->functions = $functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function for(ClassDefinition $class, $source): ObjectBuilder
|
public function for(ClassDefinition $class, $source): ObjectBuilder
|
||||||
{
|
{
|
||||||
$builders = [];
|
$builders = [];
|
||||||
|
|
||||||
foreach ($this->functions() as $key => $function) {
|
foreach ($this->functions as $function) {
|
||||||
if ($function->returnType()->matches($class->type())) {
|
if ($function->returnType()->matches($class->type())) {
|
||||||
$builders[] = new CallbackObjectBuilder($function, $this->callbacks[$key]);
|
$builders[] = new CallbackObjectBuilder($function, $this->functions->callback($function));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,20 +45,4 @@ final class ObjectBindingBuilderFactory implements ObjectBuilderFactory
|
|||||||
|
|
||||||
return $this->objectBuilderFilterer->filter($source, ...$builders);
|
return $this->objectBuilderFilterer->filter($source, ...$builders);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return FunctionDefinition[]
|
|
||||||
*/
|
|
||||||
private function functions(): array
|
|
||||||
{
|
|
||||||
if (! isset($this->functions)) {
|
|
||||||
$this->functions = [];
|
|
||||||
|
|
||||||
foreach ($this->callbacks as $key => $callback) {
|
|
||||||
$this->functions[$key] = $this->functionDefinitionRepository->for($callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->functions;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ declare(strict_types=1);
|
|||||||
namespace CuyZ\Valinor\Mapper\Tree\Builder;
|
namespace CuyZ\Valinor\Mapper\Tree\Builder;
|
||||||
|
|
||||||
use CuyZ\Valinor\Definition\FunctionDefinition;
|
use CuyZ\Valinor\Definition\FunctionDefinition;
|
||||||
|
use CuyZ\Valinor\Definition\FunctionsContainer;
|
||||||
use CuyZ\Valinor\Definition\Parameters;
|
use CuyZ\Valinor\Definition\Parameters;
|
||||||
use CuyZ\Valinor\Definition\Repository\FunctionDefinitionRepository;
|
|
||||||
use CuyZ\Valinor\Mapper\Object\Exception\InvalidSourceForInterface;
|
use CuyZ\Valinor\Mapper\Object\Exception\InvalidSourceForInterface;
|
||||||
use CuyZ\Valinor\Mapper\Tree\Exception\InvalidInterfaceResolverReturnType;
|
use CuyZ\Valinor\Mapper\Tree\Exception\InvalidInterfaceResolverReturnType;
|
||||||
use CuyZ\Valinor\Mapper\Tree\Exception\InvalidTypeResolvedForInterface;
|
use CuyZ\Valinor\Mapper\Tree\Exception\InvalidTypeResolvedForInterface;
|
||||||
@ -18,8 +18,6 @@ use CuyZ\Valinor\Type\Parser\TypeParser;
|
|||||||
use CuyZ\Valinor\Type\Resolver\Exception\CannotResolveTypeFromInterface;
|
use CuyZ\Valinor\Type\Resolver\Exception\CannotResolveTypeFromInterface;
|
||||||
use CuyZ\Valinor\Type\Types\ClassType;
|
use CuyZ\Valinor\Type\Types\ClassType;
|
||||||
use CuyZ\Valinor\Type\Types\InterfaceType;
|
use CuyZ\Valinor\Type\Types\InterfaceType;
|
||||||
use DateTimeImmutable;
|
|
||||||
use DateTimeInterface;
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
@ -27,31 +25,15 @@ final class InterfaceNodeBuilder implements NodeBuilder
|
|||||||
{
|
{
|
||||||
private NodeBuilder $delegate;
|
private NodeBuilder $delegate;
|
||||||
|
|
||||||
|
private FunctionsContainer $functions;
|
||||||
|
|
||||||
private TypeParser $typeParser;
|
private TypeParser $typeParser;
|
||||||
|
|
||||||
private FunctionDefinitionRepository $functionDefinitionRepository;
|
public function __construct(NodeBuilder $delegate, FunctionsContainer $functions, TypeParser $typeParser)
|
||||||
|
{
|
||||||
/** @var array<interface-string, callable> */
|
|
||||||
private array $callbacks;
|
|
||||||
|
|
||||||
/** @var array<interface-string, FunctionDefinition> */
|
|
||||||
private array $functions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array<interface-string, callable> $interfaceMapping
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
NodeBuilder $delegate,
|
|
||||||
FunctionDefinitionRepository $functionDefinitionRepository,
|
|
||||||
TypeParser $typeParser,
|
|
||||||
array $interfaceMapping
|
|
||||||
) {
|
|
||||||
$this->delegate = $delegate;
|
$this->delegate = $delegate;
|
||||||
$this->functionDefinitionRepository = $functionDefinitionRepository;
|
$this->functions = $functions;
|
||||||
$this->typeParser = $typeParser;
|
$this->typeParser = $typeParser;
|
||||||
|
|
||||||
$this->callbacks = $interfaceMapping;
|
|
||||||
$this->callbacks[DateTimeInterface::class] ??= static fn () => DateTimeImmutable::class;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function build(Shell $shell, RootNodeBuilder $rootBuilder): Node
|
public function build(Shell $shell, RootNodeBuilder $rootBuilder): Node
|
||||||
@ -64,14 +46,14 @@ final class InterfaceNodeBuilder implements NodeBuilder
|
|||||||
|
|
||||||
$interfaceName = $type->className();
|
$interfaceName = $type->className();
|
||||||
|
|
||||||
if (! isset($this->callbacks[$interfaceName])) {
|
if (! $this->functions->has($interfaceName)) {
|
||||||
throw new CannotResolveTypeFromInterface($interfaceName);
|
throw new CannotResolveTypeFromInterface($interfaceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @infection-ignore-all */
|
$function = $this->functions->get($interfaceName);
|
||||||
$this->functions[$interfaceName] ??= $this->functionDefinitionRepository->for($this->callbacks[$interfaceName]);
|
$callback = $this->functions->callback($function);
|
||||||
|
|
||||||
$children = $this->children($shell, $this->functions[$interfaceName], $rootBuilder);
|
$children = $this->children($shell, $function, $rootBuilder);
|
||||||
$arguments = [];
|
$arguments = [];
|
||||||
|
|
||||||
foreach ($children as $child) {
|
foreach ($children as $child) {
|
||||||
@ -83,7 +65,7 @@ final class InterfaceNodeBuilder implements NodeBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$signature = ($this->callbacks[$interfaceName])(...$arguments);
|
$signature = $callback(...$arguments);
|
||||||
} catch (Exception $exception) {
|
} catch (Exception $exception) {
|
||||||
throw ThrowableMessage::from($exception);
|
throw ThrowableMessage::from($exception);
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace CuyZ\Valinor\Mapper\Tree\Builder;
|
namespace CuyZ\Valinor\Mapper\Tree\Builder;
|
||||||
|
|
||||||
use CuyZ\Valinor\Definition\FunctionDefinition;
|
use CuyZ\Valinor\Definition\FunctionsContainer;
|
||||||
use CuyZ\Valinor\Definition\Repository\FunctionDefinitionRepository;
|
|
||||||
use CuyZ\Valinor\Mapper\Tree\Node;
|
use CuyZ\Valinor\Mapper\Tree\Node;
|
||||||
use CuyZ\Valinor\Mapper\Tree\Shell;
|
use CuyZ\Valinor\Mapper\Tree\Shell;
|
||||||
|
|
||||||
@ -14,25 +13,12 @@ final class ValueAlteringNodeBuilder implements NodeBuilder
|
|||||||
{
|
{
|
||||||
private NodeBuilder $delegate;
|
private NodeBuilder $delegate;
|
||||||
|
|
||||||
private FunctionDefinitionRepository $functionDefinitionRepository;
|
private FunctionsContainer $functions;
|
||||||
|
|
||||||
/** @var list<callable> */
|
public function __construct(NodeBuilder $delegate, FunctionsContainer $functions)
|
||||||
private array $callbacks;
|
{
|
||||||
|
|
||||||
/** @var list<FunctionDefinition> */
|
|
||||||
private array $functions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param list<callable> $callbacks
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
NodeBuilder $delegate,
|
|
||||||
FunctionDefinitionRepository $functionDefinitionRepository,
|
|
||||||
array $callbacks
|
|
||||||
) {
|
|
||||||
$this->delegate = $delegate;
|
$this->delegate = $delegate;
|
||||||
$this->functionDefinitionRepository = $functionDefinitionRepository;
|
$this->functions = $functions;
|
||||||
$this->callbacks = $callbacks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function build(Shell $shell, RootNodeBuilder $rootBuilder): Node
|
public function build(Shell $shell, RootNodeBuilder $rootBuilder): Node
|
||||||
@ -46,7 +32,7 @@ final class ValueAlteringNodeBuilder implements NodeBuilder
|
|||||||
$value = $node->value();
|
$value = $node->value();
|
||||||
$type = $node->type();
|
$type = $node->type();
|
||||||
|
|
||||||
foreach ($this->functions() as $key => $function) {
|
foreach ($this->functions as $function) {
|
||||||
$parameters = $function->parameters();
|
$parameters = $function->parameters();
|
||||||
|
|
||||||
if (count($parameters) === 0) {
|
if (count($parameters) === 0) {
|
||||||
@ -54,27 +40,11 @@ final class ValueAlteringNodeBuilder implements NodeBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($parameters->at(0)->type()->matches($type)) {
|
if ($parameters->at(0)->type()->matches($type)) {
|
||||||
$value = ($this->callbacks[$key])($value);
|
$value = ($this->functions->callback($function))($value);
|
||||||
$node = $node->withValue($value);
|
$node = $node->withValue($value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $node;
|
return $node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return FunctionDefinition[]
|
|
||||||
*/
|
|
||||||
private function functions(): array
|
|
||||||
{
|
|
||||||
if (! isset($this->functions)) {
|
|
||||||
$this->functions = [];
|
|
||||||
|
|
||||||
foreach ($this->callbacks as $key => $callback) {
|
|
||||||
$this->functions[$key] = $this->functionDefinitionRepository->for($callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->functions;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
34
tests/Fake/Definition/FakeFunctionDefinition.php
Normal file
34
tests/Fake/Definition/FakeFunctionDefinition.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace CuyZ\Valinor\Tests\Fake\Definition;
|
||||||
|
|
||||||
|
use CuyZ\Valinor\Definition\EmptyAttributes;
|
||||||
|
use CuyZ\Valinor\Definition\FunctionDefinition;
|
||||||
|
use CuyZ\Valinor\Definition\ParameterDefinition;
|
||||||
|
use CuyZ\Valinor\Definition\Parameters;
|
||||||
|
use CuyZ\Valinor\Type\Types\NativeStringType;
|
||||||
|
|
||||||
|
final class FakeFunctionDefinition
|
||||||
|
{
|
||||||
|
public static function new(): FunctionDefinition
|
||||||
|
{
|
||||||
|
return new FunctionDefinition(
|
||||||
|
'foo',
|
||||||
|
'foo:42-1337',
|
||||||
|
new Parameters(
|
||||||
|
new ParameterDefinition(
|
||||||
|
'bar',
|
||||||
|
'foo::bar',
|
||||||
|
NativeStringType::get(),
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
'foo',
|
||||||
|
EmptyAttributes::get()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
NativeStringType::get()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -4,32 +4,14 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace CuyZ\Valinor\Tests\Fake\Definition\Repository;
|
namespace CuyZ\Valinor\Tests\Fake\Definition\Repository;
|
||||||
|
|
||||||
use CuyZ\Valinor\Definition\EmptyAttributes;
|
|
||||||
use CuyZ\Valinor\Definition\FunctionDefinition;
|
use CuyZ\Valinor\Definition\FunctionDefinition;
|
||||||
use CuyZ\Valinor\Definition\ParameterDefinition;
|
|
||||||
use CuyZ\Valinor\Definition\Parameters;
|
|
||||||
use CuyZ\Valinor\Definition\Repository\FunctionDefinitionRepository;
|
use CuyZ\Valinor\Definition\Repository\FunctionDefinitionRepository;
|
||||||
use CuyZ\Valinor\Type\Types\NativeStringType;
|
use CuyZ\Valinor\Tests\Fake\Definition\FakeFunctionDefinition;
|
||||||
|
|
||||||
final class FakeFunctionDefinitionRepository implements FunctionDefinitionRepository
|
final class FakeFunctionDefinitionRepository implements FunctionDefinitionRepository
|
||||||
{
|
{
|
||||||
public function for(callable $function): FunctionDefinition
|
public function for(callable $function): FunctionDefinition
|
||||||
{
|
{
|
||||||
return new FunctionDefinition(
|
return FakeFunctionDefinition::new();
|
||||||
'foo',
|
|
||||||
'foo:42-1337',
|
|
||||||
new Parameters(
|
|
||||||
new ParameterDefinition(
|
|
||||||
'bar',
|
|
||||||
'foo::bar',
|
|
||||||
NativeStringType::get(),
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
'foo',
|
|
||||||
EmptyAttributes::get()
|
|
||||||
)
|
|
||||||
),
|
|
||||||
NativeStringType::get()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
50
tests/Unit/Definition/FunctionsContainerTest.php
Normal file
50
tests/Unit/Definition/FunctionsContainerTest.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace CuyZ\Valinor\Tests\Unit\Definition;
|
||||||
|
|
||||||
|
use CuyZ\Valinor\Definition\Exception\CallbackNotFound;
|
||||||
|
use CuyZ\Valinor\Definition\Exception\FunctionNotFound;
|
||||||
|
use CuyZ\Valinor\Definition\FunctionsContainer;
|
||||||
|
use CuyZ\Valinor\Tests\Fake\Definition\FakeFunctionDefinition;
|
||||||
|
use CuyZ\Valinor\Tests\Fake\Definition\Repository\FakeFunctionDefinitionRepository;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
use function iterator_to_array;
|
||||||
|
|
||||||
|
final class FunctionsContainerTest extends TestCase
|
||||||
|
{
|
||||||
|
public function test_get_unknown_function_throws_exception(): void
|
||||||
|
{
|
||||||
|
$this->expectException(FunctionNotFound::class);
|
||||||
|
$this->expectExceptionCode(1647523444);
|
||||||
|
$this->expectExceptionMessage('The function `unknown` was not found.');
|
||||||
|
|
||||||
|
(new FunctionsContainer(new FakeFunctionDefinitionRepository(), []))->get('unknown');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_get_unknown_callback_throws_exception(): void
|
||||||
|
{
|
||||||
|
$function = FakeFunctionDefinition::new();
|
||||||
|
|
||||||
|
$this->expectException(CallbackNotFound::class);
|
||||||
|
$this->expectExceptionCode(1647523495);
|
||||||
|
$this->expectExceptionMessage("The callback associated to `{$function->signature()}` could not be found.");
|
||||||
|
|
||||||
|
(new FunctionsContainer(new FakeFunctionDefinitionRepository(), []))->callback($function);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_keys_are_kept_when_iterating(): void
|
||||||
|
{
|
||||||
|
$functions = (new FunctionsContainer(new FakeFunctionDefinitionRepository(), [
|
||||||
|
'foo' => fn () => 'foo',
|
||||||
|
'bar' => fn () => 'bar',
|
||||||
|
]));
|
||||||
|
|
||||||
|
$functions = iterator_to_array($functions);
|
||||||
|
|
||||||
|
self::assertArrayHasKey('foo', $functions);
|
||||||
|
self::assertArrayHasKey('bar', $functions);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user