mirror of
https://github.com/danog/Valinor.git
synced 2024-11-26 20:24:40 +01:00
feat: allow injecting a cache implementation that is used by the mapper
The cache implementation that was previously injected in the mapper builder must now be manually injected. This gives better control on when the cache should be enabled, especially depending on which environment the application is running. The library provides a cache implementation out of the box, which saves cache entries into the file system. It is also possible to use any PSR-16 compliant implementation, as long as it is capable of caching the entries handled by the library. ```php $cache = new \CuyZ\Valinor\Cache\FileSystemCache('path/to/cache-dir'); (new \CuyZ\Valinor\MapperBuilder()) ->withCache($cache) ->mapper() ->map(SomeClass::class, [/* … */]); ```
This commit is contained in:
parent
1b242d4ce7
commit
69ad3f4777
22
README.md
22
README.md
@ -888,6 +888,28 @@ final class SomeClass
|
||||
}
|
||||
```
|
||||
|
||||
## Performance & caching
|
||||
|
||||
This library needs to parse a lot of information in order to handle all provided
|
||||
features. Therefore, it is strongly advised to activate the cache to reduce
|
||||
heavy workload between runtimes, especially when the application runs in a
|
||||
production environment.
|
||||
|
||||
The library provides a cache implementation out of the box, which saves
|
||||
cache entries into the file system.
|
||||
|
||||
> **Note** It is also possible to use any PSR-16 compliant implementation, as
|
||||
> long as it is capable of caching the entries handled by the library.
|
||||
|
||||
```php
|
||||
$cache = new \CuyZ\Valinor\Cache\FileSystemCache('path/to/cache-directory');
|
||||
|
||||
(new \CuyZ\Valinor\MapperBuilder())
|
||||
->withCache($cache)
|
||||
->mapper()
|
||||
->map(SomeClass::class, [/* … */]);
|
||||
```
|
||||
|
||||
## Static analysis
|
||||
|
||||
To help static analysis of a codebase using this library, an extension for
|
||||
|
@ -25,6 +25,9 @@ parameters:
|
||||
- message: '#Template type T of method CuyZ\\Valinor\\Mapper\\TreeMapper::map\(\) is not referenced in a parameter#'
|
||||
path: src/Mapper/TreeMapper.php
|
||||
|
||||
- message: '#Method CuyZ\\Valinor\\MapperBuilder::withCache\(\) has parameter \$cache with generic interface Psr\\SimpleCache\\\CacheInterface but does not specify its types: EntryType#'
|
||||
path: src/MapperBuilder.php
|
||||
|
||||
stubFiles:
|
||||
- qa/PHPStan/Stubs/Psr/SimpleCache/CacheInterface.stub
|
||||
tmpDir: var/cache/phpstan
|
||||
|
@ -11,8 +11,8 @@ interface CacheInterface
|
||||
{
|
||||
/**
|
||||
* @param string $key
|
||||
* @param EntryType $default
|
||||
* @return EntryType
|
||||
* @param EntryType|null $default
|
||||
* @return EntryType|null
|
||||
*/
|
||||
public function get(string $key, $default = null);
|
||||
|
||||
@ -26,7 +26,7 @@ interface CacheInterface
|
||||
/**
|
||||
* @param iterable<string> $keys
|
||||
* @param EntryType $default
|
||||
* @return iterable<string, EntryType>
|
||||
* @return iterable<string, EntryType|null>
|
||||
*/
|
||||
public function getMultiple(iterable $keys, $default = null): iterable;
|
||||
|
||||
|
@ -83,7 +83,7 @@ final class ChainCache implements CacheInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Traversable<string, EntryType>
|
||||
* @return Traversable<string, EntryType|null>
|
||||
*/
|
||||
public function getMultiple($keys, $default = null): Traversable
|
||||
{
|
||||
|
@ -128,7 +128,7 @@ final class CompiledPhpFileCache implements CacheInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Traversable<string, EntryType>
|
||||
* @return Traversable<string, EntryType|null>
|
||||
*/
|
||||
public function getMultiple($keys, $default = null): Traversable
|
||||
{
|
||||
|
124
src/Cache/FileSystemCache.php
Normal file
124
src/Cache/FileSystemCache.php
Normal file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CuyZ\Valinor\Cache;
|
||||
|
||||
use CuyZ\Valinor\Cache\Compiled\CompiledPhpFileCache;
|
||||
use CuyZ\Valinor\Definition\ClassDefinition;
|
||||
use CuyZ\Valinor\Definition\FunctionDefinition;
|
||||
use CuyZ\Valinor\Definition\Repository\Cache\Compiler\ClassDefinitionCompiler;
|
||||
use CuyZ\Valinor\Definition\Repository\Cache\Compiler\FunctionDefinitionCompiler;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use Traversable;
|
||||
|
||||
use function current;
|
||||
use function get_class;
|
||||
use function next;
|
||||
use function sys_get_temp_dir;
|
||||
|
||||
/**
|
||||
* @api
|
||||
*
|
||||
* @implements CacheInterface<ClassDefinition|FunctionDefinition>
|
||||
*/
|
||||
final class FileSystemCache implements CacheInterface
|
||||
{
|
||||
/** @var array<string, CacheInterface<ClassDefinition|FunctionDefinition>> */
|
||||
private array $delegates;
|
||||
|
||||
public function __construct(string $cacheDir = null)
|
||||
{
|
||||
$cacheDir ??= sys_get_temp_dir();
|
||||
|
||||
// @infection-ignore-all
|
||||
$this->delegates = [
|
||||
ClassDefinition::class => new CompiledPhpFileCache($cacheDir . DIRECTORY_SEPARATOR . 'classes', new ClassDefinitionCompiler()),
|
||||
FunctionDefinition::class => new CompiledPhpFileCache($cacheDir . DIRECTORY_SEPARATOR . 'functions', new FunctionDefinitionCompiler()),
|
||||
];
|
||||
}
|
||||
|
||||
public function has($key): bool
|
||||
{
|
||||
foreach ($this->delegates as $delegate) {
|
||||
if ($delegate->has($key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
while ($delegate = current($this->delegates)) {
|
||||
if ($delegate->has($key)) {
|
||||
return $delegate->get($key, $default);
|
||||
}
|
||||
|
||||
// @infection-ignore-all
|
||||
next($this->delegates);
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
public function set($key, $value, $ttl = null): bool
|
||||
{
|
||||
return $this->delegates[get_class($value)]->set($key, $value, $ttl);
|
||||
}
|
||||
|
||||
public function delete($key): bool
|
||||
{
|
||||
$deleted = true;
|
||||
|
||||
foreach ($this->delegates as $delegate) {
|
||||
$deleted = $delegate->delete($key) && $deleted;
|
||||
}
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
public function clear(): bool
|
||||
{
|
||||
$cleared = true;
|
||||
|
||||
foreach ($this->delegates as $delegate) {
|
||||
$cleared = $delegate->clear() && $cleared;
|
||||
}
|
||||
|
||||
return $cleared;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Traversable<string, ClassDefinition|FunctionDefinition|null>
|
||||
*/
|
||||
public function getMultiple($keys, $default = null): Traversable
|
||||
{
|
||||
foreach ($keys as $key) {
|
||||
yield $key => $this->get($key, $default);
|
||||
}
|
||||
}
|
||||
|
||||
public function setMultiple($values, $ttl = null): bool
|
||||
{
|
||||
$set = true;
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$set = $this->set($key, $value, $ttl) && $set;
|
||||
}
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
public function deleteMultiple($keys): bool
|
||||
{
|
||||
$deleted = true;
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$deleted = $this->delete($key) && $deleted;
|
||||
}
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
}
|
@ -57,7 +57,7 @@ final class VersionedCache implements CacheInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Traversable<string, EntryType>
|
||||
* @return Traversable<string, EntryType|null>
|
||||
*/
|
||||
public function getMultiple($keys, $default = null): Traversable
|
||||
{
|
||||
|
@ -31,7 +31,11 @@ final class CacheClassDefinitionRepository implements ClassDefinitionRepository
|
||||
$key = "class-definition-$type";
|
||||
|
||||
if ($this->cache->has($key)) {
|
||||
return $this->cache->get($key);
|
||||
$entry = $this->cache->get($key);
|
||||
|
||||
if ($entry) {
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
|
||||
$class = $this->delegate->for($type);
|
||||
|
@ -32,7 +32,11 @@ final class CacheFunctionDefinitionRepository implements FunctionDefinitionRepos
|
||||
$key = "function-definition-{$reflection->getFileName()}-{$reflection->getStartLine()}-{$reflection->getEndLine()}";
|
||||
|
||||
if ($this->cache->has($key)) {
|
||||
return $this->cache->get($key);
|
||||
$entry = $this->cache->get($key);
|
||||
|
||||
if ($entry) {
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
|
||||
$definition = $this->delegate->for($function);
|
||||
|
@ -5,17 +5,12 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Library;
|
||||
|
||||
use CuyZ\Valinor\Cache\ChainCache;
|
||||
use CuyZ\Valinor\Cache\Compiled\CompiledPhpFileCache;
|
||||
use CuyZ\Valinor\Cache\RuntimeCache;
|
||||
use CuyZ\Valinor\Cache\VersionedCache;
|
||||
use CuyZ\Valinor\Definition\ClassDefinition;
|
||||
use CuyZ\Valinor\Definition\FunctionDefinition;
|
||||
use CuyZ\Valinor\Definition\FunctionsContainer;
|
||||
use CuyZ\Valinor\Definition\Repository\AttributesRepository;
|
||||
use CuyZ\Valinor\Definition\Repository\Cache\CacheClassDefinitionRepository;
|
||||
use CuyZ\Valinor\Definition\Repository\Cache\CacheFunctionDefinitionRepository;
|
||||
use CuyZ\Valinor\Definition\Repository\Cache\Compiler\ClassDefinitionCompiler;
|
||||
use CuyZ\Valinor\Definition\Repository\Cache\Compiler\FunctionDefinitionCompiler;
|
||||
use CuyZ\Valinor\Definition\Repository\ClassDefinitionRepository;
|
||||
use CuyZ\Valinor\Definition\Repository\FunctionDefinitionRepository;
|
||||
use CuyZ\Valinor\Definition\Repository\Reflection\CombinedAttributesRepository;
|
||||
@ -162,31 +157,21 @@ final class Container
|
||||
|
||||
ObjectBuilderFilterer::class => fn () => new ObjectBuilderFilterer(),
|
||||
|
||||
ClassDefinitionRepository::class => function () use ($settings) {
|
||||
$repository = new ReflectionClassDefinitionRepository(
|
||||
ClassDefinitionRepository::class => fn () => new CacheClassDefinitionRepository(
|
||||
new ReflectionClassDefinitionRepository(
|
||||
$this->get(TypeParserFactory::class),
|
||||
$this->get(AttributesRepository::class),
|
||||
);
|
||||
),
|
||||
$this->get(CacheInterface::class)
|
||||
),
|
||||
|
||||
/** @var CacheInterface<ClassDefinition> $cache */
|
||||
$cache = new CompiledPhpFileCache($settings->cacheDir, new ClassDefinitionCompiler());
|
||||
$cache = $this->wrapCache($cache);
|
||||
|
||||
return new CacheClassDefinitionRepository($repository, $cache);
|
||||
},
|
||||
|
||||
FunctionDefinitionRepository::class => function () use ($settings) {
|
||||
$repository = new ReflectionFunctionDefinitionRepository(
|
||||
FunctionDefinitionRepository::class => fn () => new CacheFunctionDefinitionRepository(
|
||||
new ReflectionFunctionDefinitionRepository(
|
||||
$this->get(TypeParserFactory::class),
|
||||
$this->get(AttributesRepository::class),
|
||||
);
|
||||
|
||||
/** @var CacheInterface<FunctionDefinition> $cache */
|
||||
$cache = new CompiledPhpFileCache($settings->cacheDir, new FunctionDefinitionCompiler());
|
||||
$cache = $this->wrapCache($cache);
|
||||
|
||||
return new CacheFunctionDefinitionRepository($repository, $cache);
|
||||
},
|
||||
),
|
||||
$this->get(CacheInterface::class)
|
||||
),
|
||||
|
||||
AttributesRepository::class => function () use ($settings) {
|
||||
if (! $settings->enableLegacyDoctrineAnnotations) {
|
||||
@ -215,6 +200,16 @@ final class Container
|
||||
},
|
||||
|
||||
TemplateParser::class => fn () => new BasicTemplateParser(),
|
||||
|
||||
CacheInterface::class => function () use ($settings) {
|
||||
$cache = new RuntimeCache();
|
||||
|
||||
if (isset($settings->cache)) {
|
||||
$cache = new ChainCache($cache, $settings->cache);
|
||||
}
|
||||
|
||||
return new VersionedCache($cache);
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@ -232,20 +227,4 @@ final class Container
|
||||
{
|
||||
return $this->services[$name] ??= call_user_func($this->factories[$name]); // @phpstan-ignore-line
|
||||
}
|
||||
|
||||
/**
|
||||
* @template EntryType
|
||||
*
|
||||
* @param CacheInterface<EntryType> $cache
|
||||
* @return CacheInterface<EntryType>
|
||||
*/
|
||||
private function wrapCache(CacheInterface $cache): CacheInterface
|
||||
{
|
||||
/** @var RuntimeCache<EntryType> $runtimeCache */
|
||||
$runtimeCache = new RuntimeCache();
|
||||
|
||||
return new VersionedCache(
|
||||
new ChainCache($runtimeCache, $cache)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,7 @@ namespace CuyZ\Valinor\Library;
|
||||
use CuyZ\Valinor\Mapper\Tree\Node;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
|
||||
use function sys_get_temp_dir;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
|
||||
/** @internal */
|
||||
final class Settings
|
||||
@ -28,13 +27,13 @@ final class Settings
|
||||
/** @var array<callable(Node): void> */
|
||||
public array $nodeVisitors = [];
|
||||
|
||||
public string $cacheDir;
|
||||
/** @var CacheInterface<mixed> */
|
||||
public CacheInterface $cache;
|
||||
|
||||
public bool $enableLegacyDoctrineAnnotations = PHP_VERSION_ID < 8_00_00;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->cacheDir = sys_get_temp_dir();
|
||||
$this->interfaceMapping[DateTimeInterface::class] = static fn () => DateTimeImmutable::class;
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace CuyZ\Valinor;
|
||||
|
||||
use CuyZ\Valinor\Cache\FileSystemCache;
|
||||
use CuyZ\Valinor\Library\Container;
|
||||
use CuyZ\Valinor\Library\Settings;
|
||||
use CuyZ\Valinor\Mapper\Tree\Node;
|
||||
use CuyZ\Valinor\Mapper\TreeMapper;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
|
||||
use function is_callable;
|
||||
|
||||
@ -169,6 +171,36 @@ final class MapperBuilder
|
||||
return $clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject a cache implementation that will be in charge of caching heavy
|
||||
* data used by the mapper.
|
||||
*
|
||||
* An implementation is provided by the library, which writes cache entries
|
||||
* in the file system; it is strongly recommended to use it when the
|
||||
* application runs in production environment.
|
||||
*
|
||||
* It is also possible to use any PSR-16 compliant implementation, as long
|
||||
* as it is capable of caching the entries handled by the library.
|
||||
*
|
||||
* ```php
|
||||
* $cache = new \CuyZ\Valinor\Cache\FileSystemCache('path/to/cache-dir');
|
||||
*
|
||||
* (new \CuyZ\Valinor\MapperBuilder())
|
||||
* ->withCache($cache)
|
||||
* ->mapper()
|
||||
* ->map(SomeClass::class, [
|
||||
* // …
|
||||
* ]);
|
||||
* ```
|
||||
*/
|
||||
public function withCache(CacheInterface $cache): self
|
||||
{
|
||||
$clone = clone $this;
|
||||
$clone->settings->cache = $cache;
|
||||
|
||||
return $clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param callable(T): T $callback
|
||||
@ -191,12 +223,21 @@ final class MapperBuilder
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated instead, use:
|
||||
*
|
||||
* ```php
|
||||
* (new \CuyZ\Valinor\MapperBuilder())
|
||||
* ->withCache(new FileSystemCache('cache-directory'))
|
||||
* ->mapper()
|
||||
* ->map(SomeClass::class, [
|
||||
* // …
|
||||
* ]);
|
||||
* ```
|
||||
*/
|
||||
public function withCacheDir(string $cacheDir): self
|
||||
{
|
||||
$clone = clone $this;
|
||||
$clone->settings->cacheDir = $cacheDir;
|
||||
|
||||
return $clone;
|
||||
return $this->withCache(new FileSystemCache($cacheDir));
|
||||
}
|
||||
|
||||
/**
|
||||
|
37
tests/Integration/Cache/CacheInjectionTest.php
Normal file
37
tests/Integration/Cache/CacheInjectionTest.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CuyZ\Valinor\Tests\Integration\Cache;
|
||||
|
||||
use CuyZ\Valinor\Cache\FileSystemCache;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
|
||||
use function strtoupper;
|
||||
|
||||
final class CacheInjectionTest extends IntegrationTest
|
||||
{
|
||||
public function test_cache_entries_are_written_during_mapping(): void
|
||||
{
|
||||
$files = vfsStream::setup('cache-dir');
|
||||
|
||||
$cache = new FileSystemCache($files->url());
|
||||
|
||||
self::assertFalse($files->hasChildren());
|
||||
|
||||
$object = (new MapperBuilder())
|
||||
->withCache($cache)
|
||||
// The cache should be able to cache function definitions…
|
||||
->alter(fn (string $value): string => strtoupper($value))
|
||||
->mapper()
|
||||
// …as well as class definitions.
|
||||
->map(SimpleObject::class, 'foo');
|
||||
|
||||
self::assertSame('FOO', $object->value);
|
||||
|
||||
self::assertTrue($files->hasChildren());
|
||||
}
|
||||
}
|
@ -6,8 +6,6 @@ namespace CuyZ\Valinor\Tests\Integration;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\Mapper\Tree\Node;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
use function implode;
|
||||
@ -15,17 +13,6 @@ use function iterator_to_array;
|
||||
|
||||
abstract class IntegrationTest extends TestCase
|
||||
{
|
||||
protected MapperBuilder $mapperBuilder;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
vfsStream::setup('cache-dir');
|
||||
|
||||
$this->mapperBuilder = (new MapperBuilder())->withCacheDir(vfsStream::url('cache-dir'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return never-return
|
||||
*/
|
||||
|
@ -6,6 +6,7 @@ namespace CuyZ\Valinor\Tests\Integration\Mapping\Attribute;
|
||||
|
||||
use CuyZ\Valinor\Attribute\Identifier;
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
|
||||
use function get_class;
|
||||
@ -39,7 +40,7 @@ final class IdentifierAttributeMappingTest extends IntegrationTest
|
||||
];
|
||||
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map(get_class($class), $source);
|
||||
$result = (new MapperBuilder())->mapper()->map(get_class($class), $source);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
@ -65,7 +66,7 @@ final class IdentifierAttributeMappingTest extends IntegrationTest
|
||||
'baz' => [],
|
||||
]];
|
||||
|
||||
$result = $this->mapperBuilder->enableLegacyDoctrineAnnotations()->mapper()->map(get_class($class), $source);
|
||||
$result = (new MapperBuilder())->enableLegacyDoctrineAnnotations()->mapper()->map(get_class($class), $source);
|
||||
|
||||
self::assertSame('foo', $result->identifierDoctrineAnnotation['foo']->identifier);
|
||||
self::assertSame('bar', $result->identifierDoctrineAnnotation['bar']->identifier);
|
||||
|
@ -11,6 +11,7 @@ use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\Mapper\Object\Exception\TooManyObjectBuilderFactoryAttributes;
|
||||
use CuyZ\Valinor\Mapper\Object\Factory\ObjectBuilderFactory;
|
||||
use CuyZ\Valinor\Mapper\Object\ObjectBuilder;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Fake\Mapper\Object\FakeObjectBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use RuntimeException;
|
||||
@ -20,7 +21,7 @@ final class ObjectBuilderStrategyMappingTest extends IntegrationTest
|
||||
public function test_object_builder_attribute_is_used(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map(ObjectWithBuilderStrategyAttribute::class, [
|
||||
$result = (new MapperBuilder())->mapper()->map(ObjectWithBuilderStrategyAttribute::class, [
|
||||
'foo' => 'foo',
|
||||
'bar' => 'bar',
|
||||
]);
|
||||
@ -36,7 +37,7 @@ final class ObjectBuilderStrategyMappingTest extends IntegrationTest
|
||||
public function test_named_constructor_throwing_exception_is_caught_by_mapper(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder->mapper()->map(ObjectWithFailingBuilderStrategyAttribute::class, []);
|
||||
(new MapperBuilder())->mapper()->map(ObjectWithFailingBuilderStrategyAttribute::class, []);
|
||||
} catch (MappingError $exception) {
|
||||
$error = $exception->node()->messages()[0];
|
||||
|
||||
@ -53,7 +54,7 @@ final class ObjectBuilderStrategyMappingTest extends IntegrationTest
|
||||
$this->expectExceptionCode(1634044714);
|
||||
$this->expectExceptionMessage("Only one attribute of type `$factoryClass` is allowed, class `$objectClass` contains 2.");
|
||||
|
||||
$this->mapperBuilder->mapper()->map($objectClass, 'foo');
|
||||
(new MapperBuilder())->mapper()->map($objectClass, 'foo');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ use Attribute;
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\Mapper\Tree\Shell;
|
||||
use CuyZ\Valinor\Mapper\Tree\Visitor\ShellVisitor;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
|
||||
@ -16,7 +17,7 @@ final class ShellVisitorMappingTest extends IntegrationTest
|
||||
public function test_shell_visitor_attributes_are_called_during_mapping(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder->enableLegacyDoctrineAnnotations()->mapper()->map(
|
||||
$result = (new MapperBuilder())->enableLegacyDoctrineAnnotations()->mapper()->map(
|
||||
ObjectWithShellVisitorAttributes::class,
|
||||
[
|
||||
'valueA' => 'foo',
|
||||
|
@ -6,6 +6,7 @@ namespace CuyZ\Valinor\Tests\Integration\Mapping;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\Mapper\Object\Exception\CannotInstantiateObject;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use DateTime;
|
||||
use DateTimeImmutable;
|
||||
@ -22,7 +23,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
$object = new stdClass();
|
||||
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->registerConstructor(fn (): stdClass => $object)
|
||||
->mapper()
|
||||
->map(stdClass::class, []);
|
||||
@ -41,7 +42,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
};
|
||||
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->registerConstructor(/** @return stdClass */ fn () => $object)
|
||||
->mapper()
|
||||
->map(get_class($class), []);
|
||||
@ -55,7 +56,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
public function test_registered_named_constructor_is_used(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
// @PHP8.1 first-class callable syntax
|
||||
->registerConstructor([SomeClassWithNamedConstructors::class, 'namedConstructor'])
|
||||
->mapper()
|
||||
@ -80,7 +81,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
};
|
||||
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->registerConstructor($constructor)
|
||||
->mapper()
|
||||
->map(stdClass::class, []);
|
||||
@ -104,7 +105,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
};
|
||||
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
// @PHP8.1 first-class callable syntax
|
||||
->registerConstructor([$constructor, 'build'])
|
||||
->mapper()
|
||||
@ -119,7 +120,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
public function test_native_constructor_is_not_called_if_not_registered_but_other_constructors_are_registered(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
// @PHP8.1 first-class callable syntax
|
||||
->registerConstructor([SomeClassWithSimilarNativeConstructorAndNamedConstructor::class, 'namedConstructor'])
|
||||
->mapper()
|
||||
@ -134,7 +135,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
public function test_registered_native_constructor_is_called_if_registered_and_other_constructors_are_registered(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
// @PHP8.1 first-class callable syntax
|
||||
->registerConstructor(SomeClassWithDifferentNativeConstructorAndNamedConstructor::class)
|
||||
->registerConstructor([SomeClassWithDifferentNativeConstructorAndNamedConstructor::class, 'namedConstructor'])
|
||||
@ -156,7 +157,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
$object = new stdClass();
|
||||
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->registerConstructor(fn (): DateTime => new DateTime())
|
||||
// This constructor is surrounded by other ones to ensure it is
|
||||
// still used correctly.
|
||||
@ -174,7 +175,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
public function test_registered_constructor_with_one_argument_is_used(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->registerConstructor(function (int $int): stdClass {
|
||||
$class = new stdClass();
|
||||
$class->int = $int;
|
||||
@ -193,7 +194,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
public function test_registered_constructor_with_several_arguments_is_used(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->registerConstructor(function (string $string, int $int, float $float = 1337.404): stdClass {
|
||||
$class = new stdClass();
|
||||
$class->string = $string;
|
||||
@ -218,7 +219,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
|
||||
public function test_registered_constructors_for_same_class_are_filtered_correctly(): void
|
||||
{
|
||||
$mapper = $this->mapperBuilder
|
||||
$mapper = (new MapperBuilder())
|
||||
// Basic constructor
|
||||
->registerConstructor(function (string $foo): stdClass {
|
||||
$class = new stdClass();
|
||||
@ -279,7 +280,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
public function test_identical_registered_constructors_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->registerConstructor(
|
||||
fn (): stdClass => new stdClass(),
|
||||
fn (): stdClass => new stdClass(),
|
||||
@ -297,7 +298,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
public function test_source_not_matching_registered_constructors_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->registerConstructor(
|
||||
fn (int $bar, float $baz = 1337.404): stdClass => new stdClass(),
|
||||
fn (string $foo): stdClass => new stdClass(),
|
||||
@ -318,7 +319,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
$this->expectExceptionCode(1646916477);
|
||||
$this->expectExceptionMessage('No available constructor found for class `' . SomeClassWithPrivateNativeConstructor::class . '`');
|
||||
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->mapper()
|
||||
->map(SomeClassWithPrivateNativeConstructor::class, []);
|
||||
}
|
||||
@ -328,7 +329,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
$default = new DateTime('@1356097062');
|
||||
$defaultImmutable = new DateTimeImmutable('@1356097062');
|
||||
|
||||
$mapper = $this->mapperBuilder
|
||||
$mapper = (new MapperBuilder())
|
||||
->registerConstructor(fn (int $timestamp): DateTime => $default)
|
||||
->registerConstructor(fn (int $timestamp): DateTimeImmutable => $defaultImmutable)
|
||||
->mapper();
|
||||
@ -347,7 +348,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
public function test_registered_datetime_constructor_not_matching_source_uses_default_constructor(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->registerConstructor(fn (string $foo, int $bar): DateTimeInterface => new DateTimeImmutable())
|
||||
->mapper()
|
||||
->map(DateTimeInterface::class, 1647781015);
|
||||
@ -361,7 +362,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
public function test_registered_constructor_throwing_exception_fails_mapping_with_message(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->registerConstructor(function (): stdClass {
|
||||
// @PHP8.0 use short closure
|
||||
throw new DomainException('some domain exception');
|
||||
@ -380,7 +381,7 @@ final class ConstructorRegistrationMappingTest extends IntegrationTest
|
||||
$object = new stdClass();
|
||||
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->bind(fn (): stdClass => $object)
|
||||
->mapper()
|
||||
->map(stdClass::class, []);
|
||||
|
@ -8,6 +8,7 @@ use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\Mapper\Tree\Exception\InvalidInterfaceResolverReturnType;
|
||||
use CuyZ\Valinor\Mapper\Tree\Exception\InvalidTypeResolvedForInterface;
|
||||
use CuyZ\Valinor\Mapper\Tree\Exception\ResolvedTypeForInterfaceIsNotAccepted;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Type\Resolver\Exception\CannotResolveTypeFromInterface;
|
||||
use DateTime;
|
||||
@ -20,7 +21,7 @@ final class InterfaceInferringMappingTest extends IntegrationTest
|
||||
public function test_override_date_time_interface_inferring_overrides_correctly(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->infer(DateTimeInterface::class, fn () => DateTime::class)
|
||||
->mapper()
|
||||
->map(DateTimeInterface::class, 1645279176);
|
||||
@ -35,7 +36,7 @@ final class InterfaceInferringMappingTest extends IntegrationTest
|
||||
public function test_infer_interface_with_single_argument_works_properly(): void
|
||||
{
|
||||
try {
|
||||
[$resultA, $resultB] = $this->mapperBuilder
|
||||
[$resultA, $resultB] = (new MapperBuilder())
|
||||
->infer(SomeInterface::class, function (string $type): string {
|
||||
// @PHP8.0 use `match` with short closure
|
||||
switch ($type) {
|
||||
@ -65,7 +66,7 @@ final class InterfaceInferringMappingTest extends IntegrationTest
|
||||
public function test_infer_interface_with_several_arguments_works_properly(): void
|
||||
{
|
||||
try {
|
||||
[$resultA, $resultB] = $this->mapperBuilder
|
||||
[$resultA, $resultB] = (new MapperBuilder())
|
||||
->infer(SomeInterface::class, function (string $type, int $key): string {
|
||||
if ($type === 'classA' && $key === 42) {
|
||||
return SomeClassThatInheritsInterfaceA::class;
|
||||
@ -104,7 +105,7 @@ final class InterfaceInferringMappingTest extends IntegrationTest
|
||||
$this->expectExceptionCode(1618049116);
|
||||
$this->expectExceptionMessage('Impossible to resolve an implementation for the interface `' . SomeInterface::class . '`.');
|
||||
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->mapper()
|
||||
->map(SomeInterface::class, []);
|
||||
}
|
||||
@ -115,7 +116,7 @@ final class InterfaceInferringMappingTest extends IntegrationTest
|
||||
$this->expectExceptionCode(1630091260);
|
||||
$this->expectExceptionMessage('Invalid value 42; it must be the name of a class that implements `DateTimeInterface`.');
|
||||
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->infer(DateTimeInterface::class, fn () => 42)
|
||||
->mapper()
|
||||
->map(DateTimeInterface::class, []);
|
||||
@ -127,7 +128,7 @@ final class InterfaceInferringMappingTest extends IntegrationTest
|
||||
$this->expectExceptionCode(1618049224);
|
||||
$this->expectExceptionMessage('Invalid type `int`; it must be the name of a class that implements `DateTimeInterface`.');
|
||||
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->infer(DateTimeInterface::class, fn () => 'int')
|
||||
->mapper()
|
||||
->map(DateTimeInterface::class, []);
|
||||
@ -139,7 +140,7 @@ final class InterfaceInferringMappingTest extends IntegrationTest
|
||||
$this->expectExceptionCode(1618049487);
|
||||
$this->expectExceptionMessage('The implementation `stdClass` is not accepted by the interface `DateTimeInterface`.');
|
||||
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->infer(DateTimeInterface::class, fn () => stdClass::class)
|
||||
->mapper()
|
||||
->map(DateTimeInterface::class, []);
|
||||
@ -148,7 +149,7 @@ final class InterfaceInferringMappingTest extends IntegrationTest
|
||||
public function test_invalid_source_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->infer(SomeInterface::class, fn (string $type, int $key): string => SomeClassThatInheritsInterfaceA::class)
|
||||
->mapper()
|
||||
->map(SomeInterface::class, 42);
|
||||
@ -163,7 +164,7 @@ final class InterfaceInferringMappingTest extends IntegrationTest
|
||||
public function test_invalid_source_value_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->infer(SomeInterface::class, fn (int $key): string => SomeClassThatInheritsInterfaceA::class)
|
||||
->mapper()
|
||||
->map(SomeInterface::class, 'foo');
|
||||
@ -178,7 +179,7 @@ final class InterfaceInferringMappingTest extends IntegrationTest
|
||||
public function test_exception_thrown_is_caught_and_throws_message_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->infer(DateTimeInterface::class, function () {
|
||||
// @PHP8.0 use short closure
|
||||
throw new DomainException('some error message', 1645303304);
|
||||
|
@ -9,6 +9,7 @@ use CuyZ\Valinor\Mapper\Tree\Message\Formatter\AggregateMessageFormatter;
|
||||
use CuyZ\Valinor\Mapper\Tree\Message\Formatter\LocaleMessageFormatter;
|
||||
use CuyZ\Valinor\Mapper\Tree\Message\Formatter\MessageMapFormatter;
|
||||
use CuyZ\Valinor\Mapper\Tree\Message\Formatter\TranslationMessageFormatter;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
|
||||
final class MessageFormatterTest extends IntegrationTest
|
||||
@ -16,7 +17,7 @@ final class MessageFormatterTest extends IntegrationTest
|
||||
public function test_message_is_formatted_correctly(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder->mapper()->map('int', 'foo');
|
||||
(new MapperBuilder())->mapper()->map('int', 'foo');
|
||||
} catch (MappingError $error) {
|
||||
$formatter = new AggregateMessageFormatter(
|
||||
new LocaleMessageFormatter('fr'),
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping\Object;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject as SimpleObjectAlias;
|
||||
@ -40,7 +41,7 @@ final class ArrayValuesMappingTest extends IntegrationTest
|
||||
|
||||
foreach ([ArrayValues::class, ArrayValuesWithConstructor::class] as $class) {
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map($class, $source);
|
||||
$result = (new MapperBuilder())->mapper()->map($class, $source);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
@ -69,7 +70,7 @@ final class ArrayValuesMappingTest extends IntegrationTest
|
||||
public function test_empty_array_in_non_empty_array_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder->mapper()->map(ArrayValues::class, [
|
||||
(new MapperBuilder())->mapper()->map(ArrayValues::class, [
|
||||
'nonEmptyArraysOfStrings' => [],
|
||||
]);
|
||||
} catch (MappingError $exception) {
|
||||
@ -83,7 +84,7 @@ final class ArrayValuesMappingTest extends IntegrationTest
|
||||
public function test_value_that_cannot_be_casted_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder->mapper()->map(ArrayValues::class, [
|
||||
(new MapperBuilder())->mapper()->map(ArrayValues::class, [
|
||||
'integers' => ['foo'],
|
||||
]);
|
||||
} catch (MappingError $exception) {
|
||||
|
@ -6,6 +6,7 @@ namespace CuyZ\Valinor\Tests\Integration\Mapping\Object;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\Mapper\Object\DateTimeObjectBuilder;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use DateTime;
|
||||
use DateTimeImmutable;
|
||||
@ -36,7 +37,7 @@ final class DateTimeMappingTest extends IntegrationTest
|
||||
$pgsqlDate = (new DateTime('@' . $this->buildRandomTimestamp()))->format('Y-m-d H:i:s.u');
|
||||
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map(AllDateTimeValues::class, [
|
||||
$result = (new MapperBuilder())->mapper()->map(AllDateTimeValues::class, [
|
||||
'dateTimeInterface' => $dateTimeInterface,
|
||||
'dateTimeImmutable' => $dateTimeImmutable,
|
||||
'dateTimeFromTimestamp' => $dateTimeFromTimestamp,
|
||||
@ -67,7 +68,7 @@ final class DateTimeMappingTest extends IntegrationTest
|
||||
public function test_invalid_datetime_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->mapper()
|
||||
->map(SimpleDateTimeValues::class, [
|
||||
'dateTime' => 'invalid datetime',
|
||||
@ -83,7 +84,7 @@ final class DateTimeMappingTest extends IntegrationTest
|
||||
public function test_invalid_datetime_from_array_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->mapper()
|
||||
->map(SimpleDateTimeValues::class, [
|
||||
'dateTime' => [
|
||||
@ -102,7 +103,7 @@ final class DateTimeMappingTest extends IntegrationTest
|
||||
public function test_invalid_array_source_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->mapper()
|
||||
->map(SimpleDateTimeValues::class, [
|
||||
'dateTime' => [
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping\Object;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Fixture\Enum\BackedIntegerEnum;
|
||||
use CuyZ\Valinor\Tests\Fixture\Enum\BackedStringEnum;
|
||||
use CuyZ\Valinor\Tests\Fixture\Enum\PureEnum;
|
||||
@ -29,7 +30,7 @@ final class EnumValuesMappingTest extends IntegrationTest
|
||||
|
||||
foreach ([EnumValues::class, EnumValuesWithConstructor::class] as $class) {
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map($class, $source);
|
||||
$result = (new MapperBuilder())->mapper()->map($class, $source);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping\Object;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject as SimpleObjectAlias;
|
||||
@ -42,7 +43,7 @@ final class GenericValuesMappingTest extends IntegrationTest
|
||||
|
||||
foreach ([GenericValues::class, GenericValuesWithConstructor::class] as $class) {
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map($class, $source);
|
||||
$result = (new MapperBuilder())->mapper()->map($class, $source);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping\Object;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject as SimpleObjectAlias;
|
||||
@ -35,7 +36,7 @@ final class IterableValuesMappingTest extends IntegrationTest
|
||||
|
||||
foreach ([IterableValues::class, IterableValuesWithConstructor::class] as $class) {
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map($class, $source);
|
||||
$result = (new MapperBuilder())->mapper()->map($class, $source);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping\Object;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject as SimpleObjectAlias;
|
||||
@ -45,7 +46,7 @@ final class ListValuesMappingTest extends IntegrationTest
|
||||
|
||||
foreach ([ListValues::class, ListValuesWithConstructor::class] as $class) {
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map($class, $source);
|
||||
$result = (new MapperBuilder())->mapper()->map($class, $source);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
@ -69,7 +70,7 @@ final class ListValuesMappingTest extends IntegrationTest
|
||||
public function test_empty_list_in_non_empty_list_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder->mapper()->map(ListValues::class, [
|
||||
(new MapperBuilder())->mapper()->map(ListValues::class, [
|
||||
'nonEmptyListOfStrings' => [],
|
||||
]);
|
||||
} catch (MappingError $exception) {
|
||||
@ -83,7 +84,7 @@ final class ListValuesMappingTest extends IntegrationTest
|
||||
public function test_value_that_cannot_be_casted_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder->mapper()->map(ListValues::class, [
|
||||
(new MapperBuilder())->mapper()->map(ListValues::class, [
|
||||
'integers' => ['foo'],
|
||||
]);
|
||||
} catch (MappingError $exception) {
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping\Object;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
|
||||
final class LocalTypeAliasMappingTest extends IntegrationTest
|
||||
@ -23,7 +24,7 @@ final class LocalTypeAliasMappingTest extends IntegrationTest
|
||||
|
||||
foreach ([PhpStanLocalAliases::class, PsalmLocalAliases::class] as $class) {
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->mapper()
|
||||
->map($class, $source);
|
||||
|
||||
@ -41,7 +42,7 @@ final class LocalTypeAliasMappingTest extends IntegrationTest
|
||||
{
|
||||
foreach ([PhpStanAliasImport::class, PsalmAliasImport::class] as $class) {
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->mapper()
|
||||
->map($class, [
|
||||
'importedType' => 42,
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping\Object;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
|
||||
|
||||
@ -21,7 +22,7 @@ final class ObjectValuesMappingTest extends IntegrationTest
|
||||
|
||||
foreach ([ObjectValues::class, ObjectValuesWithConstructor::class] as $class) {
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map($class, $source);
|
||||
$result = (new MapperBuilder())->mapper()->map($class, $source);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
@ -36,7 +37,7 @@ final class ObjectValuesMappingTest extends IntegrationTest
|
||||
|
||||
foreach ([ObjectValues::class, ObjectValuesWithConstructor::class] as $class) {
|
||||
try {
|
||||
$this->mapperBuilder->mapper()->map($class, $source);
|
||||
(new MapperBuilder())->mapper()->map($class, $source);
|
||||
} catch (MappingError $exception) {
|
||||
$error = $exception->node()->messages()[0];
|
||||
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping\Object;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
|
||||
use DateTime;
|
||||
@ -41,7 +42,7 @@ final class ScalarValuesMappingTest extends IntegrationTest
|
||||
|
||||
foreach ([ScalarValues::class, ScalarValuesWithConstructor::class] as $class) {
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map($class, $source);
|
||||
$result = (new MapperBuilder())->mapper()->map($class, $source);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
@ -71,7 +72,7 @@ final class ScalarValuesMappingTest extends IntegrationTest
|
||||
public function test_value_that_cannot_be_casted_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder->mapper()->map(SimpleObject::class, [
|
||||
(new MapperBuilder())->mapper()->map(SimpleObject::class, [
|
||||
'value' => new stdClass(),
|
||||
]);
|
||||
} catch (MappingError $exception) {
|
||||
@ -85,7 +86,7 @@ final class ScalarValuesMappingTest extends IntegrationTest
|
||||
public function test_empty_mandatory_value_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder->mapper()->map(SimpleObject::class, [
|
||||
(new MapperBuilder())->mapper()->map(SimpleObject::class, [
|
||||
'value' => null,
|
||||
]);
|
||||
} catch (MappingError $exception) {
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping\Object;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
|
||||
use stdClass;
|
||||
@ -45,7 +46,7 @@ final class ShapedArrayValuesMappingTest extends IntegrationTest
|
||||
|
||||
foreach ([ShapedArrayValues::class, ShapedArrayValuesWithConstructor::class] as $class) {
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map($class, $source);
|
||||
$result = (new MapperBuilder())->mapper()->map($class, $source);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
@ -65,7 +66,7 @@ final class ShapedArrayValuesMappingTest extends IntegrationTest
|
||||
public function test_value_that_cannot_be_casted_throws_exception(): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder->mapper()->map(ShapedArrayValues::class, [
|
||||
(new MapperBuilder())->mapper()->map(ShapedArrayValues::class, [
|
||||
'basicShapedArrayWithStringKeys' => [
|
||||
'foo' => new stdClass(),
|
||||
'bar' => 42,
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping\Object;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\NativeUnionOfObjects;
|
||||
|
||||
@ -16,10 +17,10 @@ final class UnionOfObjectsMappingTest extends IntegrationTest
|
||||
public function test_object_type_is_narrowed_correctly_for_simple_case(): void
|
||||
{
|
||||
try {
|
||||
$resultFoo = $this->mapperBuilder->mapper()->map(NativeUnionOfObjects::class, [
|
||||
$resultFoo = (new MapperBuilder())->mapper()->map(NativeUnionOfObjects::class, [
|
||||
'foo' => 'foo',
|
||||
]);
|
||||
$resultBar = $this->mapperBuilder->mapper()->map(NativeUnionOfObjects::class, [
|
||||
$resultBar = (new MapperBuilder())->mapper()->map(NativeUnionOfObjects::class, [
|
||||
'bar' => 'bar',
|
||||
]);
|
||||
} catch (MappingError $error) {
|
||||
@ -33,7 +34,7 @@ final class UnionOfObjectsMappingTest extends IntegrationTest
|
||||
public function test_object_type_is_narrowed_correctly_for_simple_array_case(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map(UnionOfFooAndBar::class, [
|
||||
$result = (new MapperBuilder())->mapper()->map(UnionOfFooAndBar::class, [
|
||||
'foo' => ['foo' => 'foo'],
|
||||
'bar' => ['bar' => 'bar'],
|
||||
]);
|
||||
@ -48,7 +49,7 @@ final class UnionOfObjectsMappingTest extends IntegrationTest
|
||||
public function test_source_matching_two_unions_maps_the_one_with_most_arguments(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map(UnionOfBarAndFizAndFoo::class, [
|
||||
$result = (new MapperBuilder())->mapper()->map(UnionOfBarAndFizAndFoo::class, [
|
||||
['foo' => 'foo', 'bar' => 'bar', 'fiz' => 'fiz'],
|
||||
]);
|
||||
} catch (MappingError $error) {
|
||||
@ -65,7 +66,7 @@ final class UnionOfObjectsMappingTest extends IntegrationTest
|
||||
public function test_objects_sharing_one_property_are_resolved_correctly(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map(UnionOfFooAndBarAndFoo::class, [
|
||||
$result = (new MapperBuilder())->mapper()->map(UnionOfFooAndBarAndFoo::class, [
|
||||
['foo' => 'foo'],
|
||||
['foo' => 'foo', 'bar' => 'bar'],
|
||||
]);
|
||||
@ -80,7 +81,7 @@ final class UnionOfObjectsMappingTest extends IntegrationTest
|
||||
public function test_one_failing_union_type_does_not_stop_union_inferring(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
// @PHP8.1 first-class callable syntax
|
||||
->registerConstructor(
|
||||
[SomeClassWithTwoIdenticalNamedConstructors::class, 'constructorA'],
|
||||
@ -107,7 +108,7 @@ final class UnionOfObjectsMappingTest extends IntegrationTest
|
||||
public function test_mapping_error_when_cannot_resolve_union(string $className, array $source): void
|
||||
{
|
||||
try {
|
||||
$this->mapperBuilder->mapper()->map($className, $source);
|
||||
(new MapperBuilder())->mapper()->map($className, $source);
|
||||
|
||||
self::fail('No mapping error when one was expected');
|
||||
} catch (MappingError $exception) {
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping\Object;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\NativeUnionValues;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\NativeUnionValuesWithConstructor;
|
||||
@ -39,7 +40,7 @@ final class UnionValuesMappingTest extends IntegrationTest
|
||||
|
||||
foreach ($classes as $class) {
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map($class, $source);
|
||||
$result = (new MapperBuilder())->mapper()->map($class, $source);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping\Other;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
|
||||
final class ArrayOfScalarMappingTest extends IntegrationTest
|
||||
@ -18,7 +19,7 @@ final class ArrayOfScalarMappingTest extends IntegrationTest
|
||||
];
|
||||
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map('string[]', $source);
|
||||
$result = (new MapperBuilder())->mapper()->map('string[]', $source);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping\Other;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
|
||||
final class ShapedArrayMappingTest extends IntegrationTest
|
||||
@ -18,7 +19,7 @@ final class ShapedArrayMappingTest extends IntegrationTest
|
||||
];
|
||||
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map('array{foo: string, bar: int, fiz: float}', $source);
|
||||
$result = (new MapperBuilder())->mapper()->map('array{foo: string, bar: int, fiz: float}', $source);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
@ -38,7 +39,7 @@ final class ShapedArrayMappingTest extends IntegrationTest
|
||||
|
||||
foreach (['array{foo: string, bar: int}', 'array{bar: int, fiz:float}'] as $signature) {
|
||||
try {
|
||||
$result = $this->mapperBuilder->mapper()->map($signature, $source);
|
||||
$result = (new MapperBuilder())->mapper()->map($signature, $source);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\ReadonlyValues;
|
||||
|
||||
@ -16,7 +17,7 @@ final class ReadonlyMappingTest extends IntegrationTest
|
||||
public function test_single_property_and_constructor_parameter_are_mapped_properly(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(ReadonlyValues::class, [
|
||||
$object = (new MapperBuilder())->mapper()->map(ReadonlyValues::class, [
|
||||
'value' => 'foo',
|
||||
]);
|
||||
} catch (MappingError $error) {
|
||||
|
@ -5,13 +5,14 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
|
||||
final class SingleNodeMappingTest extends IntegrationTest
|
||||
{
|
||||
public function test_single_property_and_constructor_parameter_are_mapped_properly(): void
|
||||
{
|
||||
$mapper = $this->mapperBuilder->mapper();
|
||||
$mapper = (new MapperBuilder())->mapper();
|
||||
|
||||
// Note that the key `value` is missing from the source
|
||||
$scalarSource = 'foo';
|
||||
|
@ -6,6 +6,7 @@ namespace CuyZ\Valinor\Tests\Integration\Mapping\Source;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\Mapper\Source\JsonSource;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
|
||||
|
||||
@ -14,7 +15,7 @@ final class JsonSourceMappingTest extends IntegrationTest
|
||||
public function test_json_source_is_mapped_correctly(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SimpleObject::class,
|
||||
new JsonSource('{"value": "foo"}')
|
||||
);
|
||||
|
@ -6,6 +6,7 @@ namespace CuyZ\Valinor\Tests\Integration\Mapping\Source\Modifier;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\Mapper\Source\Modifier\CamelCaseKeys;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
|
||||
final class CamelCaseKeysMappingTest extends IntegrationTest
|
||||
@ -13,7 +14,7 @@ final class CamelCaseKeysMappingTest extends IntegrationTest
|
||||
public function test_underscore_key_is_modified_to_camel_case(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithCamelCaseProperty::class,
|
||||
new CamelCaseKeys(['some_value' => 'foo'])
|
||||
);
|
||||
@ -27,7 +28,7 @@ final class CamelCaseKeysMappingTest extends IntegrationTest
|
||||
public function test_dash_key_is_modified_to_camel_case(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithCamelCaseProperty::class,
|
||||
new CamelCaseKeys(['some-value' => 'foo'])
|
||||
);
|
||||
@ -41,7 +42,7 @@ final class CamelCaseKeysMappingTest extends IntegrationTest
|
||||
public function test_spaced_key_is_modified_to_camel_case(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithCamelCaseProperty::class,
|
||||
new CamelCaseKeys(['some value' => 'foo'])
|
||||
);
|
||||
@ -55,7 +56,7 @@ final class CamelCaseKeysMappingTest extends IntegrationTest
|
||||
public function test_nested_camel_case_keys_are_modified(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithNestedProperty::class,
|
||||
new CamelCaseKeys([
|
||||
'some_nested_value' => ['some_value' => 'foo'],
|
||||
@ -71,7 +72,7 @@ final class CamelCaseKeysMappingTest extends IntegrationTest
|
||||
public function test_existing_camel_case_key_is_not_overridden(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithCamelCaseProperty::class,
|
||||
new CamelCaseKeys([
|
||||
'someValue' => 'bar',
|
||||
@ -88,7 +89,7 @@ final class CamelCaseKeysMappingTest extends IntegrationTest
|
||||
public function test_multiple_camel_case_keys_are_modified(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithCamelCaseProperty::class,
|
||||
new CamelCaseKeys([
|
||||
'some_value' => 'foo',
|
||||
|
@ -6,6 +6,7 @@ namespace CuyZ\Valinor\Tests\Integration\Mapping\Source\Modifier;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\Mapper\Source\Modifier\PathMapping;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
|
||||
final class PathMappingTest extends IntegrationTest
|
||||
@ -35,7 +36,7 @@ final class PathMappingTest extends IntegrationTest
|
||||
}
|
||||
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeRootClass::class,
|
||||
new PathMapping(
|
||||
[
|
||||
|
@ -6,6 +6,7 @@ namespace CuyZ\Valinor\Tests\Integration\Mapping\Source;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\Mapper\Source\Source;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use IteratorAggregate;
|
||||
use Traversable;
|
||||
@ -15,7 +16,7 @@ final class SourceTest extends IntegrationTest
|
||||
public function test_iterable_source(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithSubProperty::class,
|
||||
Source::iterable(new SomeIterableClass())
|
||||
);
|
||||
@ -29,7 +30,7 @@ final class SourceTest extends IntegrationTest
|
||||
public function test_array_source(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithSubProperty::class,
|
||||
Source::array(['someNestedValue' => ['someValue' => 'foo']])
|
||||
);
|
||||
@ -43,7 +44,7 @@ final class SourceTest extends IntegrationTest
|
||||
public function test_json_source(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithSubProperty::class,
|
||||
Source::json('{"someNestedValue": {"someValue": "foo"}}')
|
||||
);
|
||||
@ -60,7 +61,7 @@ final class SourceTest extends IntegrationTest
|
||||
public function test_yaml_source(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithSubProperty::class,
|
||||
Source::yaml("someNestedValue:\n someValue: foo")
|
||||
);
|
||||
@ -74,7 +75,7 @@ final class SourceTest extends IntegrationTest
|
||||
public function test_camel_case_keys(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithSubProperty::class,
|
||||
Source::json('{"some nested value": {"some value": "foo"}}')
|
||||
->camelCaseKeys()
|
||||
@ -89,7 +90,7 @@ final class SourceTest extends IntegrationTest
|
||||
public function test_path_mapping(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithSubProperty::class,
|
||||
Source::json('{"A": {"B": "foo"}}')
|
||||
->map([
|
||||
@ -107,7 +108,7 @@ final class SourceTest extends IntegrationTest
|
||||
public function test_camel_case_keys_then_path_mapping(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithSubProperty::class,
|
||||
Source::json('{"level-one": {"level-two": "foo"}}')
|
||||
->camelCaseKeys()
|
||||
@ -126,7 +127,7 @@ final class SourceTest extends IntegrationTest
|
||||
public function test_path_mapping_then_camel_case_keys(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SomeClassWithSubProperty::class,
|
||||
Source::json('{"level-one": {"level-two": "foo"}}')
|
||||
->map([
|
||||
|
@ -6,6 +6,7 @@ namespace CuyZ\Valinor\Tests\Integration\Mapping\Source;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\Mapper\Source\YamlSource;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
|
||||
|
||||
@ -17,7 +18,7 @@ final class YamlSourceMappingTest extends IntegrationTest
|
||||
public function test_yaml_source_is_mapped_correctly(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(
|
||||
$object = (new MapperBuilder())->mapper()->map(
|
||||
SimpleObject::class,
|
||||
new YamlSource('value: foo')
|
||||
);
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
|
||||
|
||||
@ -16,7 +17,7 @@ final class ValueAlteringMappingTest extends IntegrationTest
|
||||
public function test_alter_string_alters_value(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->alter(fn () => 'bar')
|
||||
->alter(fn (string $value) => strtolower($value))
|
||||
->alter(fn (string $value) => strtoupper($value))
|
||||
@ -34,7 +35,7 @@ final class ValueAlteringMappingTest extends IntegrationTest
|
||||
public function test_value_not_accepted_by_value_altering_callback_is_not_used(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->alter(fn (string $value) => $value)
|
||||
->mapper()
|
||||
->map('string|null', null);
|
||||
@ -48,7 +49,7 @@ final class ValueAlteringMappingTest extends IntegrationTest
|
||||
public function test_alter_function_is_called_when_not_the_first_nor_the_last_one(): void
|
||||
{
|
||||
try {
|
||||
$result = $this->mapperBuilder
|
||||
$result = (new MapperBuilder())
|
||||
->alter(fn (int $value) => 404)
|
||||
->alter(fn (string $value) => $value . '!')
|
||||
->alter(fn (float $value) => 42.1337)
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
|
||||
final class VariadicParameterMappingTest extends IntegrationTest
|
||||
@ -12,7 +13,7 @@ final class VariadicParameterMappingTest extends IntegrationTest
|
||||
public function test_only_variadic_parameters_are_mapped_properly(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(SomeClassWithOnlyVariadicParameters::class, [
|
||||
$object = (new MapperBuilder())->mapper()->map(SomeClassWithOnlyVariadicParameters::class, [
|
||||
'values' => ['foo', 'bar', 'baz'],
|
||||
]);
|
||||
} catch (MappingError $error) {
|
||||
@ -25,7 +26,7 @@ final class VariadicParameterMappingTest extends IntegrationTest
|
||||
public function test_variadic_parameters_are_mapped_properly_when_string_keys_are_given(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(SomeClassWithOnlyVariadicParameters::class, [
|
||||
$object = (new MapperBuilder())->mapper()->map(SomeClassWithOnlyVariadicParameters::class, [
|
||||
'values' => [
|
||||
'foo' => 'foo',
|
||||
'bar' => 'bar',
|
||||
@ -42,7 +43,7 @@ final class VariadicParameterMappingTest extends IntegrationTest
|
||||
public function test_named_constructor_with_only_variadic_parameters_are_mapped_properly(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder
|
||||
$object = (new MapperBuilder())
|
||||
// @PHP8.1 first-class callable syntax
|
||||
->registerConstructor([SomeClassWithNamedConstructorWithOnlyVariadicParameters::class, 'new'])
|
||||
->mapper()
|
||||
@ -59,7 +60,7 @@ final class VariadicParameterMappingTest extends IntegrationTest
|
||||
public function test_non_variadic_and_variadic_parameters_are_mapped_properly(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder->mapper()->map(SomeClassWithNonVariadicAndVariadicParameters::class, [
|
||||
$object = (new MapperBuilder())->mapper()->map(SomeClassWithNonVariadicAndVariadicParameters::class, [
|
||||
'int' => 42,
|
||||
'values' => ['foo', 'bar', 'baz'],
|
||||
]);
|
||||
@ -74,14 +75,14 @@ final class VariadicParameterMappingTest extends IntegrationTest
|
||||
public function test_named_constructor_with_non_variadic_and_variadic_parameters_are_mapped_properly(): void
|
||||
{
|
||||
try {
|
||||
$object = $this->mapperBuilder
|
||||
$object = (new MapperBuilder())
|
||||
// @PHP8.1 first-class callable syntax
|
||||
->registerConstructor([SomeClassWithNamedConstructorWithNonVariadicAndVariadicParameters::class, 'new'])
|
||||
->mapper()
|
||||
->map(SomeClassWithNamedConstructorWithNonVariadicAndVariadicParameters::class, [
|
||||
'int' => 42,
|
||||
'values' => ['foo', 'bar', 'baz'],
|
||||
]);
|
||||
'int' => 42,
|
||||
'values' => ['foo', 'bar', 'baz'],
|
||||
]);
|
||||
} catch (MappingError $error) {
|
||||
$this->mappingFail($error);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ namespace CuyZ\Valinor\Tests\Integration\Mapping;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\Mapper\Tree\Node;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Fake\Mapper\Tree\Message\FakeErrorMessage;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
|
||||
@ -18,7 +19,7 @@ final class VisitorMappingTest extends IntegrationTest
|
||||
$error = new FakeErrorMessage();
|
||||
|
||||
try {
|
||||
$this->mapperBuilder
|
||||
(new MapperBuilder())
|
||||
->visit(function (Node $node) use (&$visits): void {
|
||||
if ($node->isRoot()) {
|
||||
$visits[] = '#1';
|
||||
|
147
tests/Unit/Cache/FileSystemCacheTest.php
Normal file
147
tests/Unit/Cache/FileSystemCacheTest.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CuyZ\Valinor\Tests\Unit\Cache;
|
||||
|
||||
use CuyZ\Valinor\Cache\FileSystemCache;
|
||||
use CuyZ\Valinor\Definition\ClassDefinition;
|
||||
use CuyZ\Valinor\Definition\FunctionDefinition;
|
||||
use CuyZ\Valinor\Tests\Fake\Cache\FakeCache;
|
||||
use CuyZ\Valinor\Tests\Fake\Cache\FakeFailingCache;
|
||||
use CuyZ\Valinor\Tests\Fake\Definition\FakeClassDefinition;
|
||||
use CuyZ\Valinor\Tests\Fake\Definition\FakeFunctionDefinition;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
use org\bovigo\vfs\vfsStreamDirectory;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
use function iterator_to_array;
|
||||
|
||||
final class FileSystemCacheTest extends TestCase
|
||||
{
|
||||
private vfsStreamDirectory $files;
|
||||
|
||||
private FileSystemCache $cache;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->files = vfsStream::setup('cache-dir');
|
||||
$this->cache = new FileSystemCache($this->files->url());
|
||||
|
||||
$this->injectFakeCache();
|
||||
}
|
||||
|
||||
public function test_cache_entries_are_handled_properly(): void
|
||||
{
|
||||
$classDefinition = FakeClassDefinition::new();
|
||||
$functionDefinition = FakeFunctionDefinition::new();
|
||||
|
||||
self::assertFalse($this->cache->has('class-definition'));
|
||||
self::assertFalse($this->cache->has('function-definition'));
|
||||
|
||||
self::assertTrue($this->cache->set('class-definition', $classDefinition));
|
||||
self::assertTrue($this->cache->set('function-definition', $functionDefinition));
|
||||
|
||||
self::assertTrue($this->cache->has('class-definition'));
|
||||
self::assertTrue($this->cache->has('function-definition'));
|
||||
|
||||
/** @var ClassDefinition $cachedClassDefinition */
|
||||
$cachedClassDefinition = $this->cache->get('class-definition');
|
||||
/** @var FunctionDefinition $cachedFunctionDefinition */
|
||||
$cachedFunctionDefinition = $this->cache->get('function-definition');
|
||||
|
||||
self::assertSame($classDefinition->name(), $cachedClassDefinition->name());
|
||||
self::assertSame($functionDefinition->signature(), $cachedFunctionDefinition->signature());
|
||||
|
||||
self::assertTrue($this->cache->delete('class-definition'));
|
||||
self::assertTrue($this->cache->delete('function-definition'));
|
||||
|
||||
self::assertFalse($this->cache->has('class-definition'));
|
||||
self::assertFalse($this->cache->has('function-definition'));
|
||||
}
|
||||
|
||||
public function test_clear_cache_clears_all_caches(): void
|
||||
{
|
||||
$classDefinition = FakeClassDefinition::new();
|
||||
$functionDefinition = FakeFunctionDefinition::new();
|
||||
|
||||
$this->cache->set('class-definition', $classDefinition);
|
||||
$this->cache->set('function-definition', $functionDefinition);
|
||||
|
||||
self::assertTrue($this->cache->has('class-definition'));
|
||||
self::assertTrue($this->cache->has('function-definition'));
|
||||
|
||||
self::assertTrue($this->cache->clear());
|
||||
|
||||
self::assertFalse($this->cache->has('class-definition'));
|
||||
self::assertFalse($this->cache->has('function-definition'));
|
||||
}
|
||||
|
||||
public function test_multiple_cache_entries_are_handled_properly(): void
|
||||
{
|
||||
$classDefinition = FakeClassDefinition::new();
|
||||
$functionDefinition = FakeFunctionDefinition::new();
|
||||
|
||||
self::assertTrue($this->cache->setMultiple([
|
||||
'class-definition' => $classDefinition,
|
||||
'function-definition' => $functionDefinition,
|
||||
]));
|
||||
|
||||
$cached = iterator_to_array($this->cache->getMultiple(['class-definition', 'function-definition']));
|
||||
|
||||
/** @var ClassDefinition $cachedClassDefinition */
|
||||
$cachedClassDefinition = $cached['class-definition'];
|
||||
/** @var FunctionDefinition $cachedFunctionDefinition */
|
||||
$cachedFunctionDefinition = $cached['function-definition'];
|
||||
|
||||
self::assertSame($classDefinition->name(), $cachedClassDefinition->name());
|
||||
self::assertSame($functionDefinition->signature(), $cachedFunctionDefinition->signature());
|
||||
|
||||
self::assertTrue($this->cache->deleteMultiple(['class-definition', 'function-definition']));
|
||||
|
||||
self::assertFalse($this->cache->has('class-definition'));
|
||||
self::assertFalse($this->cache->has('function-definition'));
|
||||
}
|
||||
|
||||
public function test_methods_returns_false_if_delegates_fail(): void
|
||||
{
|
||||
$this->injectFakeCache(true);
|
||||
|
||||
$classDefinition = FakeClassDefinition::new();
|
||||
$functionDefinition = FakeFunctionDefinition::new();
|
||||
|
||||
self::assertTrue($this->cache->set('class-definition', $classDefinition));
|
||||
self::assertFalse($this->cache->set('function-definition', $functionDefinition));
|
||||
|
||||
self::assertFalse($this->cache->delete('class-definition'));
|
||||
self::assertFalse($this->cache->delete('function-definition'));
|
||||
|
||||
self::assertFalse($this->cache->clear());
|
||||
|
||||
self::assertFalse($this->cache->setMultiple([
|
||||
'class-definition' => $classDefinition,
|
||||
'function-definition' => $functionDefinition,
|
||||
]));
|
||||
|
||||
self::assertFalse($this->cache->deleteMultiple(['class-definition', 'function-definition']));
|
||||
}
|
||||
|
||||
public function test_get_non_existing_entry_returns_default_value(): void
|
||||
{
|
||||
$defaultValue = FakeClassDefinition::new();
|
||||
|
||||
self::assertSame($defaultValue, $this->cache->get('non-existing-entry', $defaultValue));
|
||||
}
|
||||
|
||||
private function injectFakeCache(bool $withFailingCache = false): void
|
||||
{
|
||||
(function () use ($withFailingCache) {
|
||||
$this->delegates = [
|
||||
ClassDefinition::class => new FakeCache(),
|
||||
FunctionDefinition::class => $withFailingCache ? new FakeFailingCache() : new FakeCache(),
|
||||
];
|
||||
})->call($this->cache);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user