Skip to content

Commit

Permalink
Consistently pass destination object & class in context
Browse files Browse the repository at this point in the history
  • Loading branch information
mark-gerarts committed Aug 5, 2019
1 parent 0ca74fd commit 88145c3
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 27 deletions.
41 changes: 30 additions & 11 deletions src/AutoMapper.php
Expand Up @@ -20,7 +20,6 @@
class AutoMapper implements AutoMapperInterface
{
public const DESTINATION_CONTEXT = '__destination';

public const DESTINATION_CLASS_CONTEXT = '__destination_class';

/**
Expand Down Expand Up @@ -68,15 +67,21 @@ public function map($source, string $destinationClass, array $context = [])
}
}

$context = array_merge(
[self::DESTINATION_CLASS_CONTEXT => $destinationClass],
$context
);
$mapping = $this->getMapping($sourceClass, $destinationClass);
if ($mapping->providesCustomMapper()) {
return $this->getCustomMapper($mapping)->map($source, $destinationClass);
}

if ($mapping->hasCustomConstructor()) {
$destinationObject = $mapping->getCustomConstructor()($source, $this, array_merge([
self::DESTINATION_CLASS_CONTEXT => $destinationClass
]));
$destinationObject = $mapping->getCustomConstructor()(
$source,
$this,
$context
);
}
elseif (interface_exists($destinationClass)) {
// If we're mapping to an interface a valid custom constructor has
Expand All @@ -89,6 +94,8 @@ public function map($source, string $destinationClass, array $context = [])
$destinationObject = new $destinationClass;
}

$context[self::DESTINATION_CONTEXT] = $destinationObject;

return $this->doMap($source, $destinationObject, $mapping, $context);
}

Expand All @@ -100,7 +107,6 @@ public function mapMultiple(
string $destinationClass,
array $context = []
): array {

if(!is_iterable($sourceCollection)){
throw new InvalidArgumentException(
'The collection provided should be iterable.'
Expand Down Expand Up @@ -132,16 +138,29 @@ public function mapToObject($source, $destination, array $context = [])

$destinationClass = \get_class($destination);

$context = array_merge(
[
self::DESTINATION_CONTEXT => $destination,
self::DESTINATION_CLASS_CONTEXT => $destinationClass
],
$context
);

$mapping = $this->getMapping($sourceClass, $destinationClass);
if ($mapping->providesCustomMapper()) {
return $this->getCustomMapper($mapping)->mapToObject($source, $destination, [
self::DESTINATION_CONTEXT => $destination,
]);
return $this->getCustomMapper($mapping)->mapToObject(
$source,
$destination,
$context
);
}

return $this->doMap($source, $destination, $mapping, array_merge([
self::DESTINATION_CONTEXT => $destination,
], $context));
return $this->doMap(
$source,
$destination,
$mapping,
$context
);
}

/**
Expand Down
17 changes: 1 addition & 16 deletions test/AutoMapperTest.php
Expand Up @@ -123,21 +123,6 @@ public function testMapToAnExistingObjectContext()
;
$mapper = new AutoMapper($this->config);
$mapper->mapToObject($source, $destination);

// Make sure context added only for mapToObject method
$this->config
->getMappingFor(Source::class, Destination::class)
->forMember('name', Operation::mapFrom(function(Source $source, AutoMapperInterface $mapper, array $context) {
$this->assertArrayNotHasKey(AutoMapper::DESTINATION_CONTEXT, $context);

return $source->name;
}))
;
$mapper = new AutoMapper($this->config);

$source = new Source();
$source->name = 'Hello';
$mapper->map($source, Destination::class);
}

public function testSourceDoesntGetOverridden()
Expand Down Expand Up @@ -731,7 +716,7 @@ public function testAnExceptionIsThrownForNoIterableSourceInMultpleMappings()
$mapper = new AutoMapper($this->config);

$sourceCollection = new \stdClass();

$mapper->mapMultiple($sourceCollection, Destination::class);
}
}
33 changes: 33 additions & 0 deletions test/Scenarios/ContextTest.php
Expand Up @@ -129,4 +129,37 @@ public function testMapToMergesTheParentContext()

$this->assertEquals('map-to-value', $result->source->name);
}

public function testDestinationClassIsPassed()
{
$config = new AutoMapperConfig();
$config->registerMapping(Source::class, Destination::class)
->forMember('name', function ($source, $mapper, $context = []) {
$this->assertArrayHasKey(
AutoMapper::DESTINATION_CONTEXT,
$context
);
$this->assertArrayHasKey(
AutoMapper::DESTINATION_CLASS_CONTEXT,
$context
);
$this->assertInstanceOf(
Destination::class,
$context[AutoMapper::DESTINATION_CONTEXT]
);
$this->assertEquals(
Destination::class,
$context[AutoMapper::DESTINATION_CLASS_CONTEXT]
);

return 'some value';
});
$mapper = new AutoMapper($config);
$source = new Source('a name');

$mapper->map(
$source,
Destination::class
);
}
}

0 comments on commit 88145c3

Please sign in to comment.