Skip to content

Commit

Permalink
Refactor MapperFactory to use property info caching
Browse files Browse the repository at this point in the history
  • Loading branch information
priyadi committed Jan 11, 2024
1 parent 221c7af commit 613c04b
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 33 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* Use `MappingFactoryInterface` everywhere instead of `MappingFactory`
* Move some `TypeUtil` methods to `TypeResolver` for optimization opportunities
* use `ObjectCacheFactory` to generate `ObjectCache` instances
* Update `MapperFactory` to reflect framework usage
* Use property info caching in non-framework usage

## 0.5.2

Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
],
"require": {
"psr/container": "^2.0",
"symfony/cache": "^6.4 || ^7.0",
"symfony/clock": "^6.4 || ^7.0",
"symfony/config": "^6.4 || ^7.0",
"symfony/dependency-injection": "^6.4 || ^7.0",
Expand Down
89 changes: 57 additions & 32 deletions src/MapperFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace Rekalogika\Mapper;

use Psr\Cache\CacheItemPoolInterface;
use Psr\Container\ContainerInterface;
use Rekalogika\Mapper\Command\MappingCommand;
use Rekalogika\Mapper\Command\TryCommand;
Expand All @@ -34,14 +35,17 @@
use Rekalogika\Mapper\Transformer\TraversableToTraversableTransformer;
use Rekalogika\Mapper\TypeResolver\TypeResolver;
use Rekalogika\Mapper\TypeResolver\TypeResolverInterface;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\Console\Application;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessor;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyInfoCacheExtractor;
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
Expand Down Expand Up @@ -74,7 +78,8 @@ class MapperFactory
private ?TraversableToArrayAccessTransformer $traversableToArrayAccessTransformer = null;
private ?TraversableToTraversableTransformer $traversableToTraversableTransformer = null;

private ?PropertyTypeExtractorInterface $propertyTypeExtractor = null;
private CacheItemPoolInterface $propertyInfoExtractorCache;
private null|(PropertyInfoExtractorInterface&PropertyInitializableExtractorInterface) $propertyInfoExtractor = null;
private ?TypeResolverInterface $typeResolver = null;
private ?MainTransformer $mainTransformer = null;
private ?MapperInterface $mapper = null;
Expand All @@ -95,7 +100,9 @@ public function __construct(
private ?PropertyAccessor $propertyAccessor = null,
private ?NormalizerInterface $normalizer = null,
private ?DenormalizerInterface $denormalizer = null,
?CacheItemPoolInterface $propertyInfoExtractorCache = null,
) {
$this->propertyInfoExtractorCache = $propertyInfoExtractorCache ?? new ArrayAdapter();
}

public function getMapper(): MapperInterface
Expand All @@ -108,7 +115,7 @@ public function getMapper(): MapperInterface
}

//
// concrete services
// property info
//

private function getReflectionExtractor(): ReflectionExtractor
Expand All @@ -129,6 +136,53 @@ private function getPhpStanExtractor(): PropertyTypeExtractorInterface
return $this->phpStanExtractor;
}

private function getPropertyInfoExtractor(): PropertyInfoExtractorInterface&PropertyInitializableExtractorInterface
{
if ($this->propertyInfoExtractor === null) {
$propertyInfoExtractor = new PropertyInfoExtractor(
listExtractors: [
$this->getReflectionExtractor(),
],
typeExtractors: [
$this->getPhpStanExtractor(),
$this->getReflectionExtractor(),
],
accessExtractors: [
$this->getReflectionExtractor(),
],
initializableExtractors: [
$this->getReflectionExtractor(),
],
);

$this->propertyInfoExtractor = new PropertyInfoCacheExtractor(
$propertyInfoExtractor,
$this->propertyInfoExtractorCache,
);
}

return $this->propertyInfoExtractor;
}

private function getPropertyInitializableExtractor(): PropertyInitializableExtractorInterface
{
return $this->getPropertyInfoExtractor();
}

private function getPropertyAccessExtractor(): PropertyAccessExtractorInterface
{
return $this->getPropertyInfoExtractor();
}

private function getPropertyListExtractor(): PropertyListExtractorInterface
{
return $this->getPropertyInfoExtractor();
}

//
// concrete services
//

private function getConcretePropertyAccessor(): PropertyAccessorInterface
{
if (null === $this->propertyAccessor) {
Expand Down Expand Up @@ -162,35 +216,6 @@ private function getSerializer(): Serializer
// interfaces
//

private function getPropertyListExtractor(): PropertyListExtractorInterface
{
return $this->getReflectionExtractor();
}

private function getPropertyTypeExtractor(): PropertyTypeExtractorInterface
{
if ($this->propertyTypeExtractor === null) {
$this->propertyTypeExtractor = new PropertyInfoExtractor(
typeExtractors: [
$this->getPhpStanExtractor(),
$this->getReflectionExtractor(),
],
);
}

return $this->propertyTypeExtractor;
}

private function getPropertyInitializableExtractor(): PropertyInitializableExtractorInterface
{
return $this->getReflectionExtractor();
}

private function getPropertyAccessExtractor(): PropertyAccessExtractorInterface
{
return $this->getReflectionExtractor();
}

private function getPropertyAccessor(): PropertyAccessorInterface
{
return $this->getConcretePropertyAccessor();
Expand Down Expand Up @@ -232,7 +257,7 @@ protected function getObjectToObjectTransformer(): TransformerInterface
if (null === $this->objectToObjectTransformer) {
$this->objectToObjectTransformer = new ObjectToObjectTransformer(
$this->getPropertyListExtractor(),
$this->getPropertyTypeExtractor(),
$this->getPropertyInfoExtractor(),
$this->getPropertyInitializableExtractor(),
$this->getPropertyAccessExtractor(),
$this->getPropertyAccessor(),
Expand Down
1 change: 0 additions & 1 deletion src/Util/TypeUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

use DaveLiddament\PhpLanguageExtensions\Friend;
use DaveLiddament\PhpLanguageExtensions\NamespaceVisibility;
use Rekalogika\Mapper\Contracts\TypeMapping;
use Rekalogika\Mapper\Exception\InvalidArgumentException;
use Rekalogika\Mapper\Exception\MapperReturnsUnexpectedValueException;
use Rekalogika\Mapper\Model\MixedType;
Expand Down

0 comments on commit 613c04b

Please sign in to comment.