diff --git a/CHANGELOG.md b/CHANGELOG.md index de642639..e9541c04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ * fix: Service definition for `TryPropertyCommand`. * feat: All exceptions now accept `$context` variable for more useful error messages. +* feat: Context methods now accept `$context` variable, and pass it to + exceptions. ## 0.5.8 diff --git a/src/MainTransformer/MainTransformer.php b/src/MainTransformer/MainTransformer.php index 3ef1b558..f326192d 100644 --- a/src/MainTransformer/MainTransformer.php +++ b/src/MainTransformer/MainTransformer.php @@ -147,9 +147,17 @@ public function transform( if ($targetTypeForTransformer !== null) { try { - return $objectCache->getTarget($source, $targetTypeForTransformer); + return $objectCache->getTarget( + $source, + $targetTypeForTransformer, + $context + ); } catch (CachedTargetObjectNotFoundException) { - $objectCache->preCache($source, $targetTypeForTransformer); + $objectCache->preCache( + $source, + $targetTypeForTransformer, + $context + ); } } @@ -171,7 +179,13 @@ public function transform( // if the target type is not null, cache it if ($targetTypeForTransformer !== null) { - $objectCache->saveTarget($source, $targetTypeForTransformer, $result, true); + $objectCache->saveTarget( + $source, + $targetTypeForTransformer, + $result, + $context, + true, + ); } return $result; diff --git a/src/ObjectCache/Exception/CircularReferenceException.php b/src/ObjectCache/Exception/CircularReferenceException.php index 49d923a7..ed1123ce 100644 --- a/src/ObjectCache/Exception/CircularReferenceException.php +++ b/src/ObjectCache/Exception/CircularReferenceException.php @@ -13,6 +13,7 @@ namespace Rekalogika\Mapper\ObjectCache\Exception; +use Rekalogika\Mapper\Context\Context; use Rekalogika\Mapper\Exception\ExceptionInterface; use Rekalogika\Mapper\Exception\RuntimeException; use Rekalogika\Mapper\Util\TypeUtil; @@ -20,14 +21,15 @@ class CircularReferenceException extends RuntimeException implements ExceptionInterface { - public function __construct(mixed $source, Type $targetType) + public function __construct(mixed $source, Type $targetType, Context $context = null) { parent::__construct( sprintf( 'Circular reference detected when trying to get the object of type "%s" transformed to "%s"', \get_debug_type($source), TypeUtil::getDebugType($targetType) - ) + ), + context: $context ); } } diff --git a/src/ObjectCache/Exception/NonSimpleTypeException.php b/src/ObjectCache/Exception/NonSimpleTypeException.php index 47040c81..39ac44a5 100644 --- a/src/ObjectCache/Exception/NonSimpleTypeException.php +++ b/src/ObjectCache/Exception/NonSimpleTypeException.php @@ -13,14 +13,15 @@ namespace Rekalogika\Mapper\ObjectCache\Exception; +use Rekalogika\Mapper\Context\Context; use Rekalogika\Mapper\Exception\UnexpectedValueException; use Rekalogika\Mapper\Util\TypeUtil; use Symfony\Component\PropertyInfo\Type; class NonSimpleTypeException extends UnexpectedValueException { - public function __construct(Type $type) + public function __construct(Type $type, ?Context $context = null) { - parent::__construct(sprintf('Expected a simple type, got non-simple type "%s".', TypeUtil::getDebugType($type))); + parent::__construct(sprintf('Expected a simple type, got non-simple type "%s".', TypeUtil::getDebugType($type)), context: $context); } } diff --git a/src/ObjectCache/ObjectCache.php b/src/ObjectCache/ObjectCache.php index 5d614ca8..19957f78 100644 --- a/src/ObjectCache/ObjectCache.php +++ b/src/ObjectCache/ObjectCache.php @@ -13,6 +13,7 @@ namespace Rekalogika\Mapper\ObjectCache; +use Rekalogika\Mapper\Context\Context; use Rekalogika\Mapper\Exception\LogicException; use Rekalogika\Mapper\ObjectCache\Exception\CachedTargetObjectNotFoundException; use Rekalogika\Mapper\ObjectCache\Exception\CircularReferenceException; @@ -46,10 +47,10 @@ private function isBlacklisted(mixed $source): bool return $source instanceof \DateTimeInterface; } - private function assertSimpleType(Type $type): void + private function assertSimpleType(Type $type, Context $context): void { if (!$this->typeResolver->isSimpleType($type)) { - throw new NonSimpleTypeException($type); + throw new NonSimpleTypeException($type, context: $context); } } @@ -63,7 +64,7 @@ private function assertSimpleType(Type $type): void * @param Type $targetType * @return void */ - public function preCache(mixed $source, Type $targetType): void + public function preCache(mixed $source, Type $targetType, Context $context): void { if (!is_object($source)) { return; @@ -73,7 +74,7 @@ public function preCache(mixed $source, Type $targetType): void return; } - $this->assertSimpleType($targetType); + $this->assertSimpleType($targetType, $context); $targetTypeString = $this->typeResolver->getTypeString($targetType); @@ -86,26 +87,26 @@ public function preCache(mixed $source, Type $targetType): void $this->preCache->offsetGet($source)->offsetSet($targetTypeString, true); } - private function isPreCached(mixed $source, Type $targetType): bool + private function isPreCached(mixed $source, Type $targetType, Context $context): bool { if (!is_object($source)) { return false; } - $this->assertSimpleType($targetType); + $this->assertSimpleType($targetType, $context); $targetTypeString = $this->typeResolver->getTypeString($targetType); return isset($this->preCache[$source][$targetTypeString]); } - private function removePrecache(mixed $source, Type $targetType): void + private function removePrecache(mixed $source, Type $targetType, Context $context): void { if (!is_object($source)) { return; } - $this->assertSimpleType($targetType); + $this->assertSimpleType($targetType, $context); $targetTypeString = $this->typeResolver->getTypeString($targetType); @@ -114,7 +115,7 @@ private function removePrecache(mixed $source, Type $targetType): void } } - public function containsTarget(mixed $source, Type $targetType): bool + public function containsTarget(mixed $source, Type $targetType, Context $context): bool { if (!is_object($source)) { return false; @@ -124,28 +125,28 @@ public function containsTarget(mixed $source, Type $targetType): bool return false; } - $this->assertSimpleType($targetType); + $this->assertSimpleType($targetType, $context); $targetTypeString = $this->typeResolver->getTypeString($targetType); return isset($this->cache[$source][$targetTypeString]); } - public function getTarget(mixed $source, Type $targetType): mixed + public function getTarget(mixed $source, Type $targetType, Context $context): mixed { - if ($this->isPreCached($source, $targetType)) { - throw new CircularReferenceException($source, $targetType); + if ($this->isPreCached($source, $targetType, $context)) { + throw new CircularReferenceException($source, $targetType, context: $context); } if ($this->isBlacklisted($source)) { - throw new CachedTargetObjectNotFoundException(); + throw new CachedTargetObjectNotFoundException(context: $context); } if (!is_object($source)) { - throw new CachedTargetObjectNotFoundException(); + throw new CachedTargetObjectNotFoundException(context: $context); } - $this->assertSimpleType($targetType); + $this->assertSimpleType($targetType, $context); $targetTypeString = $this->typeResolver->getTypeString($targetType); @@ -158,7 +159,8 @@ public function saveTarget( mixed $source, Type $targetType, mixed $target, - bool $addIfAlreadyExists = false + Context $context, + bool $addIfAlreadyExists = false, ): void { if (!is_object($source) || !is_object($target)) { return; @@ -170,7 +172,10 @@ public function saveTarget( $targetTypeString = $this->typeResolver->getTypeString($targetType); - if ($addIfAlreadyExists === false && $this->containsTarget($source, $targetType)) { + if ( + $addIfAlreadyExists === false + && $this->containsTarget($source, $targetType, $context) + ) { throw new LogicException(sprintf( 'Target object for source object "%s" and target type "%s" already exists', get_class($source), @@ -185,6 +190,6 @@ public function saveTarget( } $this->cache->offsetGet($source)->offsetSet($targetTypeString, $target); - $this->removePrecache($source, $targetType); + $this->removePrecache($source, $targetType, $context); } } diff --git a/src/Transformer/ObjectToObjectTransformer.php b/src/Transformer/ObjectToObjectTransformer.php index 25333eb4..651d5523 100644 --- a/src/Transformer/ObjectToObjectTransformer.php +++ b/src/Transformer/ObjectToObjectTransformer.php @@ -102,8 +102,8 @@ public function transform( // save object to cache - $objectCache = $context->get(ObjectCache::class); - $objectCache->saveTarget($source, $targetType, $target); + $context(ObjectCache::class) + ->saveTarget($source, $targetType, $target, $context); // list properties diff --git a/src/Transformer/TraversableToArrayAccessTransformer.php b/src/Transformer/TraversableToArrayAccessTransformer.php index 48b49ad4..29f0d6a4 100644 --- a/src/Transformer/TraversableToArrayAccessTransformer.php +++ b/src/Transformer/TraversableToArrayAccessTransformer.php @@ -66,7 +66,8 @@ public function transform( $target = $this->instantiateArrayAccessOrArray($targetType, $context); } - $objectCache->saveTarget($source, $targetType, $target); + $context(ObjectCache::class) + ->saveTarget($source, $targetType, $target, $context); // Prepare variables for the output loop diff --git a/src/Transformer/TraversableToTraversableTransformer.php b/src/Transformer/TraversableToTraversableTransformer.php index 3fdc73b4..c073bac6 100644 --- a/src/Transformer/TraversableToTraversableTransformer.php +++ b/src/Transformer/TraversableToTraversableTransformer.php @@ -156,7 +156,8 @@ public function transform( $target = new TraversableCountableWrapper($target, count($source)); } - $objectCache->saveTarget($source, $targetType, $target); + $context(ObjectCache::class) + ->saveTarget($source, $targetType, $target, $context); return $target; } diff --git a/tests/UnitTest/Model/ObjectCacheTest.php b/tests/UnitTest/Model/ObjectCacheTest.php index a625da08..d8817ccc 100644 --- a/tests/UnitTest/Model/ObjectCacheTest.php +++ b/tests/UnitTest/Model/ObjectCacheTest.php @@ -14,6 +14,7 @@ namespace Rekalogika\Mapper\Tests\UnitTest\Model; use PHPUnit\Framework\TestCase; +use Rekalogika\Mapper\Context\Context; use Rekalogika\Mapper\ObjectCache\Exception\CachedTargetObjectNotFoundException; use Rekalogika\Mapper\ObjectCache\ObjectCache; use Rekalogika\Mapper\TypeResolver\TypeResolver; @@ -26,16 +27,17 @@ public function testObjectCache(): void $typeResolver = new TypeResolver(); $objectCache = new ObjectCache($typeResolver); $source = new \stdClass(); + $context = Context::create(); - $this->assertFalse($objectCache->containsTarget($source, TypeFactory::int())); + $this->assertFalse($objectCache->containsTarget($source, TypeFactory::int(), $context)); $target = new \stdClass(); - $objectCache->saveTarget($source, TypeFactory::int(), $target); + $objectCache->saveTarget($source, TypeFactory::int(), $target, $context); - $this->assertTrue($objectCache->containsTarget($source, TypeFactory::int())); - $this->assertSame($target, $objectCache->getTarget($source, TypeFactory::int())); + $this->assertTrue($objectCache->containsTarget($source, TypeFactory::int(), $context)); + $this->assertSame($target, $objectCache->getTarget($source, TypeFactory::int(), $context)); $this->expectException(CachedTargetObjectNotFoundException::class); - $objectCache->getTarget($source, TypeFactory::float()); + $objectCache->getTarget($source, TypeFactory::float(), $context); } }