Skip to content

Commit

Permalink
Add custom constructor and middleware support to custom mappers
Browse files Browse the repository at this point in the history
  • Loading branch information
Toilal committed Sep 12, 2019
1 parent 8ba45d9 commit e85de1b
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 62 deletions.
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -770,15 +770,12 @@ of custom code. This code would look a lot cleaner if put in its own class.
Another reason to resort to a custom mapper would be [performance](#performance).

It is therefore possible to specify a custom mapper class for a mapping. This
mapper has to implement the `MapperInterface`. For your convenience, a
`CustomMapper` class has been provided that implements this interface.
mapper has to implement the `DestinationMapperInterface`.

```php
<?php

// You can either extend the CustomMapper, or just implement the MapperInterface
// directly.
class EmployeeMapper extends CustomMapper
class EmployeeMapper implements DestinationMapperInterface
{
/**
* @param Employee $source
Expand Down
20 changes: 6 additions & 14 deletions src/AutoMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ public function map($source, string $destinationClass, array $context = [])
$context[self::DESTINATION_CLASS_CONTEXT] = $destinationClass;

$mapping = $this->getMapping($sourceClass, $destinationClass);
if ($mapping->providesCustomMapper()) {
return $this->getCustomMapper($mapping)->map($source, $destinationClass);
}

if ($mapping->hasCustomConstructor()) {
$destinationObject = $mapping->getCustomConstructor()(
$source,
Expand Down Expand Up @@ -167,14 +163,6 @@ public function mapToObject($source, $destination, array $context = [])
$this->push(self::DESTINATION_STACK_CONTEXT, $destination, $context);
try {
$mapping = $this->getMapping($sourceClass, $destinationClass);
if ($mapping->providesCustomMapper()) {
return $this->getCustomMapper($mapping)->mapToObject(
$source,
$destination,
$context
);
}

return $this->doMap(
$source,
$destination,
Expand Down Expand Up @@ -206,8 +194,12 @@ protected function doMap(
{
$mapper = $this;

$this->autoMapperConfig->getDefaultMapperMiddleware()->map($source, $destination, $mapper, $mapping, $context, function () {
});
if ($mapping->providesCustomMapper()) {
$this->getCustomMapper($mapping)->mapToObject($source, $destination, $context);
} else {
$this->autoMapperConfig->getDefaultMapperMiddleware()->map($source, $destination, $mapper, $mapping, $context, function () {
});
}

$map = function () {
// NOOP
Expand Down
33 changes: 33 additions & 0 deletions src/ClassMapperInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace AutoMapperPlus;

use AutoMapperPlus\Exception\UnregisteredMappingException;

/**
* Interface ClassMapperInterface
*
* @package AutoMapperPlus
*/
interface ClassMapperInterface
{
/**
* Maps an object to an instance of class $to, provided a mapping is
* configured.
*
* @param array|object $source
* The source object.
* @param string $targetClass
* The target classname.
* @param array $context
* An arbitrary array of values that will be passed to supporting
* mapping operations (e.g. MapFrom) to alter their behaviour based on
* the context.
* This is not explicitly required on the interface yet to preserve
* backwards compatibility, but will be added in version 2.0.
* @return mixed
* An instance of class $to.
* @throws UnregisteredMappingException
*/
public function map($source, string $targetClass/**, array $context = [] */);
}
12 changes: 6 additions & 6 deletions src/Configuration/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace AutoMapperPlus\Configuration;

use AutoMapperPlus\MapperInterface;
use AutoMapperPlus\DestinationMapperInterface;
use AutoMapperPlus\MappingOperation\DefaultMappingOperation;
use AutoMapperPlus\MappingOperation\MappingOperationInterface;
use AutoMapperPlus\NameConverter\NamingConvention\NamingConventionInterface;
Expand Down Expand Up @@ -61,7 +61,7 @@ class Options
private $defaultMappingOperation;

/**
* @var MapperInterface|null
* @var DestinationMapperInterface|null
*/
private $customMapper;

Expand Down Expand Up @@ -256,17 +256,17 @@ public function shouldConvertName(): bool
}

/**
* @return MapperInterface|null
* @return DestinationMapperInterface|null
*/
public function getCustomMapper(): ?MapperInterface
public function getCustomMapper(): ?DestinationMapperInterface
{
return $this->customMapper;
}

/**
* @param MapperInterface $customMapper
* @param DestinationMapperInterface $customMapper
*/
public function setCustomMapper(MapperInterface $customMapper): void
public function setCustomMapper(DestinationMapperInterface $customMapper): void
{
$this->customMapper = $customMapper;
}
Expand Down
1 change: 1 addition & 0 deletions src/CustomMapper/CustomMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
/**
* Interface CustomMapperInterface
*
* @deprecated Implement DestinationMapperInterface instead
* @package AutoMapperPlus\CustomMapper
*/
abstract class CustomMapper implements MapperInterface
Expand Down
28 changes: 28 additions & 0 deletions src/DestinationMapperInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace AutoMapperPlus;

use AutoMapperPlus\Exception\UnregisteredMappingException;

/**
* Interface ObjectMapperInterface
*
* @package AutoMapperPlus
*/
interface DestinationMapperInterface
{
/**
* Maps properties of object $from to an existing object $to.
*
* @param array|object $source
* The source object.
* @param object $destination
* The target object.
* @param array $context
* See MapperInterface::map()
* @return mixed
* $to, with properties copied from $from.
* @throws UnregisteredMappingException
*/
public function mapToObject($source, $destination/**, array $context = [] */);
}
38 changes: 1 addition & 37 deletions src/MapperInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,11 @@

namespace AutoMapperPlus;

use AutoMapperPlus\Exception\UnregisteredMappingException;

/**
* Interface MapperInterface
*
* @package AutoMapperPlus
*/
interface MapperInterface
interface MapperInterface extends DestinationMapperInterface, ClassMapperInterface
{
/**
* Maps an object to an instance of class $to, provided a mapping is
* configured.
*
* @param array|object $source
* The source object.
* @param string $targetClass
* The target classname.
* @param array $context
* An arbitrary array of values that will be passed to supporting
* mapping operations (e.g. MapFrom) to alter their behaviour based on
* the context.
* This is not explicitly required on the interface yet to preserve
* backwards compatibility, but will be added in version 2.0.
* @return mixed
* An instance of class $to.
* @throws UnregisteredMappingException
*/
public function map($source, string $targetClass/**, array $context = [] */);

/**
* Maps properties of object $from to an existing object $to.
*
* @param array|object $source
* The source object.
* @param object $destination
* The target object.
* @param array $context
* See MapperInterface::map()
* @return mixed
* $to, with properties copied from $from.
* @throws UnregisteredMappingException
*/
public function mapToObject($source, $destination/**, array $context = [] */);
}

0 comments on commit e85de1b

Please sign in to comment.