Skip to content

Commit

Permalink
fix(transformer): fix property transformer with adder and remover met…
Browse files Browse the repository at this point in the history
…hods (#116)

Fix #111
  • Loading branch information
joelwurtz committed May 5, 2024
2 parents 77e90f8 + 2e5ee1e commit 48a0415
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 7 deletions.
45 changes: 38 additions & 7 deletions src/Transformer/PropertyTransformer/PropertyTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace AutoMapper\Transformer\PropertyTransformer;

use AutoMapper\Extractor\WriteMutator;
use AutoMapper\Generator\UniqueVariableScope;
use AutoMapper\Metadata\PropertyMetadata;
use AutoMapper\Transformer\AllowNullValueTransformerInterface;
Expand Down Expand Up @@ -48,12 +49,8 @@ public function transform(Expr $input, Expr $target, PropertyMetadata $propertyM
}
}

/*
* When using a custom transformer, we need to call the transform method of the custom transformer which has been injected into the mapper.
*
* $this->transformers['id']($input, $source, $context)
*/
return [new Expr\MethodCall(
$statements = [];
$transformExpr = new Expr\MethodCall(
new Expr\MethodCall(new Expr\PropertyFetch(new Expr\Variable('this'), 'transformerRegistry'), 'getPropertyTransformer', [
new Arg(new Scalar\String_($this->propertyTransformerId)),
]),
Expand All @@ -63,6 +60,40 @@ public function transform(Expr $input, Expr $target, PropertyMetadata $propertyM
new Arg($source),
new Arg($context),
]
), []];
);

/*
* If mutator is type adder and remover, we need to loop over the transformed values and call the adder method for each value.
*
* $values = $this->transformers['id']($input, $source, $context);
* foreach ($values as $value) {
* $target->add($value);
* }
*/
if ($propertyMapping->target->writeMutator && $propertyMapping->target->writeMutator->type === WriteMutator::TYPE_ADDER_AND_REMOVER) {
$mappedValueVar = new Expr\Variable($uniqueVariableScope->getUniqueName('mappedValue'));

$statements[] = new Stmt\Expression(new Expr\Assign(
$mappedValueVar,
$transformExpr
));

$loopValueVar = new Expr\Variable($uniqueVariableScope->getUniqueName('value'));

$statements[] = new Stmt\Foreach_($mappedValueVar, $loopValueVar, [
'stmts' => [
new Stmt\Expression($propertyMapping->target->writeMutator->getExpression($target, $loopValueVar)),
],
]);

return [new Expr\Variable($uniqueVariableScope->getUniqueName('mappedValues')), $statements];
}

/*
* When using a custom transformer, we need to call the transform method of the custom transformer which has been injected into the mapper.
*
* $this->transformers['id']($input, $source, $context)
*/
return [$transformExpr, []];
}
}
16 changes: 16 additions & 0 deletions tests/AutoMapperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
use AutoMapper\Tests\Fixtures\HasDateTimeInterfaceWithMutableInstance;
use AutoMapper\Tests\Fixtures\HasDateTimeInterfaceWithNullValue;
use AutoMapper\Tests\Fixtures\HasDateTimeWithNullValue;
use AutoMapper\Tests\Fixtures\Issue111\Colour;
use AutoMapper\Tests\Fixtures\Issue111\ColourTransformer;
use AutoMapper\Tests\Fixtures\Issue111\FooDto;
use AutoMapper\Tests\Fixtures\ObjectsUnion\Bar;
use AutoMapper\Tests\Fixtures\ObjectsUnion\Foo;
use AutoMapper\Tests\Fixtures\ObjectsUnion\ObjectsUnionProperty;
Expand Down Expand Up @@ -1507,4 +1510,17 @@ public function testProviderEarlyReturn(): void
self::assertSame('bar', $data->foo);
self::assertSame('foo', $data->bar);
}

public function testIssue111(): void
{
$fooDto = new FooDto();
$fooDto->colours = ['red', 'green', 'blue'];

$this->buildAutoMapper(propertyTransformers: [new ColourTransformer()]);

$foo = $this->autoMapper->map($fooDto, Fixtures\Issue111\Foo::class);

self::assertInstanceOf(Fixtures\Issue111\Foo::class, $foo);
self::assertEquals([new Colour('red'), new Colour('green'), new Colour('blue')], $foo->getColours());
}
}
13 changes: 13 additions & 0 deletions tests/Fixtures/Issue111/Colour.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace AutoMapper\Tests\Fixtures\Issue111;

class Colour
{
public function __construct(
public string $name
) {
}
}
21 changes: 21 additions & 0 deletions tests/Fixtures/Issue111/ColourTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace AutoMapper\Tests\Fixtures\Issue111;

use AutoMapper\Transformer\PropertyTransformer\PropertyTransformerInterface;

class ColourTransformer implements PropertyTransformerInterface
{
public function transform(mixed $value, object|array $source, array $context): mixed
{
$colours = [];

foreach ($value as $colour) {
$colours[] = new Colour($colour);
}

return $colours;
}
}
29 changes: 29 additions & 0 deletions tests/Fixtures/Issue111/Foo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace AutoMapper\Tests\Fixtures\Issue111;

class Foo
{
private array $colours = [];

public function getColours(): array
{
return $this->colours;
}

public function addColour(Colour $colour): void
{
$this->colours[] = $colour;
}

public function removeColour(Colour $colour): void
{
$key = array_search($colour, $this->colours, true);

if ($key !== false) {
unset($this->colours[$key]);
}
}
}
13 changes: 13 additions & 0 deletions tests/Fixtures/Issue111/FooDto.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace AutoMapper\Tests\Fixtures\Issue111;

use AutoMapper\Attribute\MapTo;

class FooDto
{
#[MapTo(target: Foo::class, transformer: ColourTransformer::class)]
public array $colours = [];
}

0 comments on commit 48a0415

Please sign in to comment.