Skip to content

Commit

Permalink
feat: Context methods now accept $context variable, and pass it to …
Browse files Browse the repository at this point in the history
…exceptions.
  • Loading branch information
priyadi committed Jan 14, 2024
1 parent e25d1cb commit 841cccb
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 35 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 @@
* 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

Expand Down
20 changes: 17 additions & 3 deletions src/MainTransformer/MainTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
}
}

Expand All @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions src/ObjectCache/Exception/CircularReferenceException.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,23 @@

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;
use Symfony\Component\PropertyInfo\Type;

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
);
}
}
5 changes: 3 additions & 2 deletions src/ObjectCache/Exception/NonSimpleTypeException.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
43 changes: 24 additions & 19 deletions src/ObjectCache/ObjectCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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;
Expand All @@ -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);

Expand All @@ -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);

Expand All @@ -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;
Expand All @@ -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);

Expand All @@ -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;
Expand All @@ -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),
Expand All @@ -185,6 +190,6 @@ public function saveTarget(
}

$this->cache->offsetGet($source)->offsetSet($targetTypeString, $target);
$this->removePrecache($source, $targetType);
$this->removePrecache($source, $targetType, $context);
}
}
4 changes: 2 additions & 2 deletions src/Transformer/ObjectToObjectTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion src/Transformer/TraversableToArrayAccessTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion src/Transformer/TraversableToTraversableTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
12 changes: 7 additions & 5 deletions tests/UnitTest/Model/ObjectCacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}
}

0 comments on commit 841cccb

Please sign in to comment.