Skip to content

Commit

Permalink
Move some TypeUtil methods to TypeResolver for optimization opportuni…
Browse files Browse the repository at this point in the history
…ties
  • Loading branch information
priyadi committed Jan 11, 2024
1 parent 5b14931 commit a95f1e7
Show file tree
Hide file tree
Showing 12 changed files with 132 additions and 95 deletions.
9 changes: 5 additions & 4 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
use Rekalogika\Mapper\Transformer\StringToBackedEnumTransformer;
use Rekalogika\Mapper\Transformer\TraversableToArrayAccessTransformer;
use Rekalogika\Mapper\Transformer\TraversableToTraversableTransformer;
use Rekalogika\Mapper\TypeStringHelper;
use Rekalogika\Mapper\TypeResolver\TypeResolver;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\PropertyInfo\PropertyInfoCacheExtractor;
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
Expand Down Expand Up @@ -120,6 +120,7 @@
'$propertyInitializableExtractor' => service('rekalogika.mapper.property_info'),
'$propertyAccessExtractor' => service('rekalogika.mapper.property_info'),
'$propertyAccessor' => service('property_accessor'),
'$typeResolver' => service('rekalogika.mapper.type_resolver'),
])
->tag('rekalogika.mapper.transformer', ['priority' => -950]);

Expand All @@ -139,13 +140,13 @@
# other services

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

$services
->set('rekalogika.mapper.main_transformer', MainTransformer::class)
->args([
'$transformersLocator' => tagged_locator('rekalogika.mapper.transformer'),
'$typeStringHelper' => service('rekalogika.mapper.type_string_helper'),
'$typeResolver' => service('rekalogika.mapper.type_resolver'),
'$mappingFactory' => service('rekalogika.mapper.mapping_factory'),
]);

Expand All @@ -167,7 +168,7 @@
->set('rekalogika.mapper.command.try', TryCommand::class)
->args([
service('rekalogika.mapper.main_transformer'),
service('rekalogika.mapper.type_string_helper'),
service('rekalogika.mapper.type_resolver'),
])
->tag('console.command');
};
8 changes: 4 additions & 4 deletions src/Command/TryCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace Rekalogika\Mapper\Command;

use Rekalogika\Mapper\MainTransformer;
use Rekalogika\Mapper\TypeStringHelper;
use Rekalogika\Mapper\TypeResolver\TypeResolverInterface;
use Rekalogika\Mapper\Util\TypeFactory;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
Expand All @@ -30,7 +30,7 @@ class TryCommand extends Command
{
public function __construct(
private MainTransformer $mainTransformer,
private TypeStringHelper $typeStringHelper
private TypeResolverInterface $typeResolver
) {
parent::__construct();
}
Expand All @@ -55,7 +55,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
/** @var string */
$sourceTypeString = $input->getArgument('source');
$sourceType = TypeFactory::fromString($sourceTypeString);
$sourceTypeStrings = $this->typeStringHelper
$sourceTypeStrings = $this->typeResolver
->getApplicableTypeStrings($sourceType);

$rows[] = ['Source type', $sourceTypeString];
Expand All @@ -72,7 +72,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
/** @var string */
$targetTypeString = $input->getArgument('target');
$targetType = TypeFactory::fromString($targetTypeString);
$targetTypeStrings = $this->typeStringHelper
$targetTypeStrings = $this->typeResolver
->getApplicableTypeStrings($targetType);

$rows[] = new TableSeparator();
Expand Down
11 changes: 6 additions & 5 deletions src/MainTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Rekalogika\Mapper\Mapping\MappingFactoryInterface;
use Rekalogika\Mapper\Model\MixedType;
use Rekalogika\Mapper\Model\ObjectCache;
use Rekalogika\Mapper\TypeResolver\TypeResolverInterface;
use Rekalogika\Mapper\Util\TypeUtil;
use Symfony\Component\PropertyInfo\Type;

Expand All @@ -32,7 +33,7 @@ class MainTransformer implements MainTransformerInterface

public function __construct(
private ContainerInterface $transformersLocator,
private TypeStringHelper $typeStringHelper,
private TypeResolverInterface $typeResolver,
private MappingFactoryInterface $mappingFactory
) {
}
Expand Down Expand Up @@ -69,7 +70,7 @@ public function transform(
if ($target === null) {
throw new LogicException('Either $target or $targetType must be provided');
}
$targetType = TypeUtil::guessTypeFromVariable($target);
$targetType = $this->typeResolver->guessTypeFromVariable($target);
}

// get object cache
Expand All @@ -85,7 +86,7 @@ public function transform(
// init vars

$targetType = TypeUtil::getSimpleTypes($targetType);
$sourceType = TypeUtil::guessTypeFromVariable($source);
$sourceType = $this->typeResolver->guessTypeFromVariable($source);

foreach ($targetType as $singleTargetType) {
$transformers = $this->getTransformers($sourceType, $singleTargetType);
Expand Down Expand Up @@ -131,10 +132,10 @@ public function getTransformerMapping(
Type|MixedType $sourceType,
Type|MixedType $targetType,
): array {
$sourceTypeStrings = $this->typeStringHelper
$sourceTypeStrings = $this->typeResolver
->getApplicableTypeStrings($sourceType);

$targetTypeStrings = $this->typeStringHelper
$targetTypeStrings = $this->typeResolver
->getApplicableTypeStrings($targetType);

return $this->mappingFactory->getMapping()
Expand Down
6 changes: 3 additions & 3 deletions src/Mapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class_exists($target)
} elseif (is_object($target)) {
/** @var object $target */
$targetClass = $target::class;
$targetType = TypeUtil::guessTypeFromVariable($target);
$targetType = null;
} else {
$targetClass = null;
$targetType = TypeFactory::fromBuiltIn($target);
Expand Down Expand Up @@ -83,7 +83,7 @@ class_exists($target)
}
}

if ($targetKeyType !== null || $targetValueType !== null) {
if ($targetType !== null && ($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".', TypeUtil::getTypeString($targetType), get_debug_type($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)));
}
}
19 changes: 11 additions & 8 deletions src/MapperFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
use Rekalogika\Mapper\Transformer\StringToBackedEnumTransformer;
use Rekalogika\Mapper\Transformer\TraversableToArrayAccessTransformer;
use Rekalogika\Mapper\Transformer\TraversableToTraversableTransformer;
use Rekalogika\Mapper\TypeResolver\TypeResolver;
use Rekalogika\Mapper\TypeResolver\TypeResolverInterface;
use Symfony\Component\Console\Application;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessor;
Expand Down Expand Up @@ -71,7 +73,7 @@ class MapperFactory
private ?TraversableToTraversableTransformer $traversableToTraversableTransformer = null;

private ?PropertyTypeExtractorInterface $propertyTypeExtractor = null;
private ?TypeStringHelper $typeStringHelper = null;
private ?TypeResolverInterface $typeResolver = null;
private ?MainTransformer $mainTransformer = null;
private ?MapperInterface $mapper = null;
private ?MappingFactoryInterface $mappingFactory = null;
Expand Down Expand Up @@ -230,7 +232,8 @@ protected function getObjectToObjectTransformer(): TransformerInterface
$this->getPropertyTypeExtractor(),
$this->getPropertyInitializableExtractor(),
$this->getPropertyAccessExtractor(),
$this->getPropertyAccessor()
$this->getPropertyAccessor(),
$this->getTypeResolver(),
);
}

Expand Down Expand Up @@ -317,13 +320,13 @@ protected function getTraversableToTraversableTransformer(): TransformerInterfac
// other services
//

protected function getTypeStringHelper(): TypeStringHelper
protected function getTypeResolver(): TypeResolverInterface
{
if (null === $this->typeStringHelper) {
$this->typeStringHelper = new TypeStringHelper();
if (null === $this->typeResolver) {
$this->typeResolver = new TypeResolver();
}

return $this->typeStringHelper;
return $this->typeResolver;
}

/**
Expand Down Expand Up @@ -365,7 +368,7 @@ protected function getMainTransformer(): MainTransformer
if (null === $this->mainTransformer) {
$this->mainTransformer = new MainTransformer(
$this->getTransformersLocator(),
$this->getTypeStringHelper(),
$this->getTypeResolver(),
$this->getMappingFactory(),
);
}
Expand Down Expand Up @@ -404,7 +407,7 @@ protected function getTryCommand(): TryCommand
if (null === $this->tryCommand) {
$this->tryCommand = new TryCommand(
$this->getMainTransformer(),
$this->getTypeStringHelper()
$this->getTypeResolver()
);
}

Expand Down
5 changes: 3 additions & 2 deletions src/Transformer/ObjectToObjectTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
use Rekalogika\Mapper\Exception\InvalidArgumentException;
use Rekalogika\Mapper\MainTransformer;
use Rekalogika\Mapper\Model\ObjectCache;
use Rekalogika\Mapper\TypeResolver\TypeResolverInterface;
use Rekalogika\Mapper\Util\TypeCheck;
use Rekalogika\Mapper\Util\TypeFactory;
use Rekalogika\Mapper\Util\TypeUtil;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface;
Expand All @@ -41,6 +41,7 @@ public function __construct(
private PropertyInitializableExtractorInterface $propertyInitializableExtractor,
private PropertyAccessExtractorInterface $propertyAccessExtractor,
private PropertyAccessorInterface $propertyAccessor,
private TypeResolverInterface $typeResolver,
) {
}

Expand Down Expand Up @@ -74,7 +75,7 @@ public function transform(
throw new InvalidArgumentException(sprintf('The source must be an object, "%s" given.', get_debug_type($source)));
}

$sourceType = TypeUtil::guessTypeFromVariable($source);
$sourceType = $this->typeResolver->guessTypeFromVariable($source);

$targetClass = $targetType->getClassName();

Expand Down
83 changes: 83 additions & 0 deletions src/TypeResolver/TypeResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?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\TypeResolver;

use Rekalogika\Mapper\Exception\InvalidArgumentException;
use Rekalogika\Mapper\Model\MixedType;
use Rekalogika\Mapper\Util\TypeFactory;
use Rekalogika\Mapper\Util\TypeUtil;
use Symfony\Component\PropertyInfo\Type;

class TypeResolver implements TypeResolverInterface
{
public static function guessTypeFromVariable(mixed $variable): Type
{
if (is_object($variable)) {
return TypeFactory::objectOfClass($variable::class);
}

if (is_null($variable)) {
return TypeFactory::null();
}

if (is_array($variable)) {
return TypeFactory::array();
}

if (is_bool($variable)) {
return TypeFactory::bool();
}

if (is_int($variable)) {
return TypeFactory::int();
}

if (is_float($variable)) {
return TypeFactory::float();
}

if (is_string($variable)) {
return TypeFactory::string();
}

if (is_resource($variable)) {
return TypeFactory::resource();
}

throw new InvalidArgumentException(sprintf(
'Cannot determine type of variable "%s"',
get_debug_type($variable),
));
}

public function getApplicableTypeStrings(array|Type|MixedType $type): array
{
if ($type instanceof MixedType) {
$type = ['mixed'];
return $type;
}

if ($type instanceof Type) {
$type = [$type];
}

$typeStrings = [];

foreach ($type as $type) {
$typeStrings = array_merge($typeStrings, TypeUtil::getAllTypeStrings($type, true));
}

return $typeStrings;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@
* that was distributed with this source code.
*/

namespace Rekalogika\Mapper;
namespace Rekalogika\Mapper\TypeResolver;

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

class TypeStringHelper
interface TypeResolverInterface
{
/**
* Guesses the type of the given variable.
*/
public static function guessTypeFromVariable(mixed $variable): Type;

/**
* Example: If the variable type is
* 'IteratorAggregate<int,IteratorAggregate<int,string>>', then this method
Expand All @@ -32,23 +36,5 @@ class TypeStringHelper
* @param array<int,Type>|Type|MixedType $type
* @return array<int,string>
*/
public function getApplicableTypeStrings(array|Type|MixedType $type): array
{
if ($type instanceof MixedType) {
$type = ['mixed'];
return $type;
}

if ($type instanceof Type) {
$type = [$type];
}

$typeStrings = [];

foreach ($type as $type) {
$typeStrings = array_merge($typeStrings, TypeUtil::getAllTypeStrings($type, true));
}

return $typeStrings;
}
public function getApplicableTypeStrings(array|Type|MixedType $type): array;
}
Loading

0 comments on commit a95f1e7

Please sign in to comment.