Skip to content

Commit

Permalink
TypeUtil refactor; add ObjectCacheFactory
Browse files Browse the repository at this point in the history
  • Loading branch information
priyadi committed Jan 11, 2024
1 parent a95f1e7 commit d7c32df
Show file tree
Hide file tree
Showing 26 changed files with 245 additions and 54 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## 0.5.3

* Use `MappingFactoryInterface` everywhere instead of `MappingFactory`
* Move some `TypeUtil` methods to `TypeResolver` for optimization opportunities
* use `ObjectCacheFactory` to generate `ObjectCache` instances

## 0.5.2

Expand Down
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@
"symfony/http-kernel": "^6.4 || ^7.0",
"symfony/phpunit-bridge": "^6.4 || ^7.0",
"symfony/var-dumper": "^6.4 || ^7.0",
"vimeo/psalm": "^5.18"
"vimeo/psalm": "^5.18",
"dave-liddament/php-language-extensions": "^0.6.0",
"dave-liddament/phpstan-php-language-extensions": "^0.5.0"
},
"autoload": {
"psr-4": {
Expand Down
18 changes: 17 additions & 1 deletion config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Rekalogika\Mapper\MapperInterface;
use Rekalogika\Mapper\Mapping\MappingFactory;
use Rekalogika\Mapper\Mapping\MappingFactoryInterface;
use Rekalogika\Mapper\ObjectCache\ObjectCacheFactory;
use Rekalogika\Mapper\Transformer\ArrayToObjectTransformer;
use Rekalogika\Mapper\Transformer\DateTimeTransformer;
use Rekalogika\Mapper\Transformer\NullTransformer;
Expand Down Expand Up @@ -96,10 +97,16 @@

$services
->set('rekalogika.mapper.transformer.traversable_to_arrayaccess', TraversableToArrayAccessTransformer::class)
->args([
'$objectCacheFactory' => service('rekalogika.mapper.object_cache_factory'),
])
->tag('rekalogika.mapper.transformer', ['priority' => -750]);

$services
->set('rekalogika.mapper.transformer.traversable_to_traversable', TraversableToTraversableTransformer::class)
->args([
'$objectCacheFactory' => service('rekalogika.mapper.object_cache_factory'),
])
->tag('rekalogika.mapper.transformer', ['priority' => -800]);

$services
Expand All @@ -121,6 +128,7 @@
'$propertyAccessExtractor' => service('rekalogika.mapper.property_info'),
'$propertyAccessor' => service('property_accessor'),
'$typeResolver' => service('rekalogika.mapper.type_resolver'),
'$objectCacheFactory' => service('rekalogika.mapper.object_cache_factory'),
])
->tag('rekalogika.mapper.transformer', ['priority' => -950]);

Expand All @@ -132,13 +140,20 @@

$services
->set('rekalogika.mapper.mapping_factory', MappingFactory::class)
->args([tagged_iterator('rekalogika.mapper.transformer', 'key')]);
->args([
tagged_iterator('rekalogika.mapper.transformer', 'key'),
service('rekalogika.mapper.type_resolver')
]);

$services
->alias(MappingFactoryInterface::class, 'rekalogika.mapper.mapping_factory');

# other services

$services
->set('rekalogika.mapper.object_cache_factory', ObjectCacheFactory::class)
->args([service('rekalogika.mapper.type_resolver')]);

$services
->set('rekalogika.mapper.type_resolver', TypeResolver::class);

Expand All @@ -148,6 +163,7 @@
'$transformersLocator' => tagged_locator('rekalogika.mapper.transformer'),
'$typeResolver' => service('rekalogika.mapper.type_resolver'),
'$mappingFactory' => service('rekalogika.mapper.mapping_factory'),
'$objectCacheFactory' => service('rekalogika.mapper.object_cache_factory'),
]);

$services
Expand Down
1 change: 1 addition & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ includes:
- vendor/phpstan/phpstan-deprecation-rules/rules.neon
- vendor/bnf/phpstan-psr-container/extension.neon
- vendor/ekino/phpstan-banned-code/extension.neon
- vendor/dave-liddament/phpstan-php-language-extensions/extension.neon
4 changes: 2 additions & 2 deletions src/Exception/CircularReferenceException.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

namespace Rekalogika\Mapper\Exception;

use Rekalogika\Mapper\Util\TypeCheck;
use Rekalogika\Mapper\Util\TypeUtil;
use Symfony\Component\PropertyInfo\Type;

class CircularReferenceException extends \RuntimeException implements ExceptionInterface
Expand All @@ -24,7 +24,7 @@ public function __construct(mixed $source, Type $targetType)
sprintf(
'Circular reference detected when trying to get the object of type "%s" transformed to "%s"',
\get_debug_type($source),
TypeCheck::getDebugType($targetType)
TypeUtil::getDebugType($targetType)
)
);
}
Expand Down
25 changes: 25 additions & 0 deletions src/Exception/InvalidTypeInArgumentException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/*
* This file is part of rekalogika/mapper package.
*
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

namespace Rekalogika\Mapper\Exception;

use Rekalogika\Mapper\Util\TypeUtil;
use Symfony\Component\PropertyInfo\Type;

class InvalidTypeInArgumentException extends InvalidArgumentException
{
public function __construct(string $printfMessage, Type $expectedType)
{
parent::__construct(sprintf($printfMessage, TypeUtil::getDebugType($expectedType)));
}
}
31 changes: 31 additions & 0 deletions src/Exception/MapperReturnsUnexpectedValueException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

/*
* This file is part of rekalogika/mapper package.
*
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

namespace Rekalogika\Mapper\Exception;

use Rekalogika\Mapper\Util\TypeUtil;
use Symfony\Component\PropertyInfo\Type;

class MapperReturnsUnexpectedValueException extends UnexpectedValueException
{
public function __construct(Type|null $type, mixed $target)
{
$message = sprintf(
'Mapper returns unexpected value. Expected type "%s", but got "%s"',
$type === null ? 'unknown' : TypeUtil::getTypeString($type),
get_debug_type($target),
);

parent::__construct($message);
}
}
4 changes: 2 additions & 2 deletions src/Exception/MissingMemberKeyTypeException.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@

namespace Rekalogika\Mapper\Exception;

use Rekalogika\Mapper\Util\TypeCheck;
use Rekalogika\Mapper\Util\TypeUtil;
use Symfony\Component\PropertyInfo\Type;

class MissingMemberKeyTypeException extends MissingMemberTypeException
{
public function __construct(Type $sourceType, Type $targetType)
{
parent::__construct(sprintf('Trying to map collection type "%s" to "%s", but the source member key is not the simple array-key type, and the target does not have the type information about the key of its child members. Usually you can fix this by adding a PHPdoc to the property containing the collection type.', TypeCheck::getDebugType($sourceType), TypeCheck::getDebugType($targetType)));
parent::__construct(sprintf('Trying to map collection type "%s" to "%s", but the source member key is not the simple array-key type, and the target does not have the type information about the key of its child members. Usually you can fix this by adding a PHPdoc to the property containing the collection type.', TypeUtil::getDebugType($sourceType), TypeUtil::getDebugType($targetType)));
}
}
4 changes: 2 additions & 2 deletions src/Exception/MissingMemberValueTypeException.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@

namespace Rekalogika\Mapper\Exception;

use Rekalogika\Mapper\Util\TypeCheck;
use Rekalogika\Mapper\Util\TypeUtil;
use Symfony\Component\PropertyInfo\Type;

class MissingMemberValueTypeException extends MissingMemberTypeException
{
public function __construct(Type $sourceType, Type $targetType)
{
parent::__construct(sprintf('Trying to map collection type "%s" to "%s", but the target does not have the type information about the value of its child members. Usually you can fix this by adding a PHPdoc to the property containing the collection type.', TypeCheck::getDebugType($sourceType), TypeCheck::getDebugType($targetType)));
parent::__construct(sprintf('Trying to map collection type "%s" to "%s", but the target does not have the type information about the value of its child members. Usually you can fix this by adding a PHPdoc to the property containing the collection type.', TypeUtil::getDebugType($sourceType), TypeUtil::getDebugType($targetType)));
}
}
8 changes: 4 additions & 4 deletions src/Exception/UnableToFindSuitableTransformerException.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

namespace Rekalogika\Mapper\Exception;

use Rekalogika\Mapper\Util\TypeCheck;
use Rekalogika\Mapper\Util\TypeUtil;
use Symfony\Component\PropertyInfo\Type;

class UnableToFindSuitableTransformerException extends NotMappableValueException
Expand All @@ -25,11 +25,11 @@ class UnableToFindSuitableTransformerException extends NotMappableValueException
public function __construct(Type $sourceType, Type|array $targetType)
{
if (is_array($targetType)) {
$targetType = implode(', ', array_map(fn (Type $type) => TypeCheck::getDebugType($type), $targetType));
$targetType = implode(', ', array_map(fn (Type $type) => TypeUtil::getDebugType($type), $targetType));
} else {
$targetType = TypeCheck::getDebugType($targetType);
$targetType = TypeUtil::getDebugType($targetType);
}

parent::__construct(sprintf('Unable to map the value "%s" to "%s"', TypeCheck::getDebugType($sourceType), $targetType));
parent::__construct(sprintf('Unable to map the value "%s" to "%s"', TypeUtil::getDebugType($sourceType), $targetType));
}
}
8 changes: 5 additions & 3 deletions src/MainTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
use Rekalogika\Mapper\Mapping\MappingEntry;
use Rekalogika\Mapper\Mapping\MappingFactoryInterface;
use Rekalogika\Mapper\Model\MixedType;
use Rekalogika\Mapper\Model\ObjectCache;
use Rekalogika\Mapper\ObjectCache\ObjectCache;
use Rekalogika\Mapper\ObjectCache\ObjectCacheFactoryInterface;
use Rekalogika\Mapper\TypeResolver\TypeResolverInterface;
use Rekalogika\Mapper\Util\TypeUtil;
use Symfony\Component\PropertyInfo\Type;
Expand All @@ -34,7 +35,8 @@ class MainTransformer implements MainTransformerInterface
public function __construct(
private ContainerInterface $transformersLocator,
private TypeResolverInterface $typeResolver,
private MappingFactoryInterface $mappingFactory
private MappingFactoryInterface $mappingFactory,
private ObjectCacheFactoryInterface $objectCacheFactory,
) {
}

Expand Down Expand Up @@ -76,7 +78,7 @@ public function transform(
// get object cache

if (!isset($context[self::OBJECT_CACHE])) {
$objectCache = new ObjectCache();
$objectCache = $this->objectCacheFactory->createObjectCache();
$context[self::OBJECT_CACHE] = $objectCache;
} else {
/** @var ObjectCache */
Expand Down
8 changes: 4 additions & 4 deletions src/Mapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
namespace Rekalogika\Mapper;

use Rekalogika\Mapper\Contracts\MainTransformerInterface;
use Rekalogika\Mapper\Exception\MapperReturnsUnexpectedValueException;
use Rekalogika\Mapper\Exception\UnexpectedValueException;
use Rekalogika\Mapper\Model\MixedType;
use Rekalogika\Mapper\Util\TypeFactory;
use Rekalogika\Mapper\Util\TypeUtil;
use Symfony\Component\PropertyInfo\Type;

final class Mapper implements MapperInterface
Expand Down Expand Up @@ -52,7 +52,7 @@ class_exists($target)
} elseif (is_object($target)) {
/** @var object $target */
$targetClass = $target::class;
$targetType = null;
$targetType = TypeFactory::objectOfClass($targetClass);
} else {
$targetClass = null;
$targetType = TypeFactory::fromBuiltIn($target);
Expand Down Expand Up @@ -83,7 +83,7 @@ class_exists($target)
}
}

if ($targetType !== null && ($targetKeyType !== null || $targetValueType !== null)) {
if ($targetKeyType !== null || $targetValueType !== null) {
$targetType = new Type(
builtinType: $targetType->getBuiltinType(),
nullable: $targetType->isNullable(),
Expand Down Expand Up @@ -129,6 +129,6 @@ class: $targetType->getClassName(),
return $target;
}

throw new UnexpectedValueException(sprintf('The transformer did not return the variable of expected type, expecting "%s", returned "%s".', $targetType !== null ? TypeUtil::getTypeString($targetType) : 'unknown', get_debug_type($target)));
throw new MapperReturnsUnexpectedValueException($targetType, $target);
}
}
27 changes: 24 additions & 3 deletions src/MapperFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
use Rekalogika\Mapper\Mapping\MappingFactory;
use Rekalogika\Mapper\Mapping\MappingFactoryInterface;
use Rekalogika\Mapper\Model\ServiceLocator;
use Rekalogika\Mapper\ObjectCache\ObjectCacheFactory;
use Rekalogika\Mapper\ObjectCache\ObjectCacheFactoryInterface;
use Rekalogika\Mapper\Transformer\ArrayToObjectTransformer;
use Rekalogika\Mapper\Transformer\DateTimeTransformer;
use Rekalogika\Mapper\Transformer\NullTransformer;
Expand Down Expand Up @@ -77,6 +79,7 @@ class MapperFactory
private ?MainTransformer $mainTransformer = null;
private ?MapperInterface $mapper = null;
private ?MappingFactoryInterface $mappingFactory = null;
private ?ObjectCacheFactoryInterface $objectCacheFactory = null;

private ?MappingCommand $mappingCommand = null;
private ?TryCommand $tryCommand = null;
Expand Down Expand Up @@ -234,6 +237,7 @@ protected function getObjectToObjectTransformer(): TransformerInterface
$this->getPropertyAccessExtractor(),
$this->getPropertyAccessor(),
$this->getTypeResolver(),
$this->getObjectCacheFactory(),
);
}

Expand Down Expand Up @@ -301,7 +305,10 @@ protected function getDateTimeTransformer(): TransformerInterface
protected function getTraversableToArrayAccessTransformer(): TransformerInterface
{
if (null === $this->traversableToArrayAccessTransformer) {
$this->traversableToArrayAccessTransformer = new TraversableToArrayAccessTransformer();
$this->traversableToArrayAccessTransformer =
new TraversableToArrayAccessTransformer(
$this->getObjectCacheFactory()
);
}

return $this->traversableToArrayAccessTransformer;
Expand All @@ -310,7 +317,10 @@ protected function getTraversableToArrayAccessTransformer(): TransformerInterfac
protected function getTraversableToTraversableTransformer(): TransformerInterface
{
if (null === $this->traversableToTraversableTransformer) {
$this->traversableToTraversableTransformer = new TraversableToTraversableTransformer();
$this->traversableToTraversableTransformer =
new TraversableToTraversableTransformer(
$this->getObjectCacheFactory()
);
}

return $this->traversableToTraversableTransformer;
Expand Down Expand Up @@ -370,6 +380,7 @@ protected function getMainTransformer(): MainTransformer
$this->getTransformersLocator(),
$this->getTypeResolver(),
$this->getMappingFactory(),
$this->getObjectCacheFactory(),
);
}

Expand All @@ -380,13 +391,23 @@ protected function getMappingFactory(): MappingFactoryInterface
{
if (null === $this->mappingFactory) {
$this->mappingFactory = new MappingFactory(
$this->getTransformersIterator()
$this->getTransformersIterator(),
$this->getTypeResolver(),
);
}

return $this->mappingFactory;
}

protected function getObjectCacheFactory(): ObjectCacheFactoryInterface
{
if (null === $this->objectCacheFactory) {
$this->objectCacheFactory = new ObjectCacheFactory($this->getTypeResolver());
}

return $this->objectCacheFactory;
}

//
// command
//
Expand Down
Loading

0 comments on commit d7c32df

Please sign in to comment.