Skip to main content

Predetermined Mapping Preset

The user can provide a list of predetermined mapping between objects to Mapper. If Mapper encounters an object in the list, that matches the provided target class, it will use the preset value.

Usage

use Rekalogika\Mapper\MapperInterface;
use Rekalogika\Mapper\Transformer\Context\PresetMapping;
use Rekalogika\Mapper\Context\Context;

/** @var MapperInterface $mapper */
/** @var Book $book */
/** @var BookDto $bookDto */

// this means if a Book is being mapped to a BookDto, use the provided $bookDto
// @todo this is wrong
$presetMapping = new PresetMapping([
$book => [
BookDto::class => $bookDto,
]
])

$context = Context::create($presetMapping);

$result = $mapper->map($book, BookDto::class, $context);
assert($bookDto === $result); // true

Populating PresetMapping from an Existing ObjectCache

You can use the ObjectCache from a previous mapping to populate the PresetMapping object.

use Rekalogika\Mapper\ObjectCache\ObjectCacheFactoryInterface;
use Rekalogika\Mapper\Transformer\Context\PresetMapping;
use Rekalogika\Mapper\Context\Context;
use Rekalogika\Mapper\MapperInterface;

/** @var ObjectCacheFactoryInterface $objectCacheFactory */
/** @var MapperInterface $mapper */
/** @var Book $book */
/** @var BookDto $bookDto */

$objectCache = $objectCacheFactory->createObjectCache();
$context = Context::create($objectCache);

$result = $mapper->map($book, BookDto::class, $context);

$presetMapping = PresetMappingFactory::fromObjectCache($objectCache);
// or to get the reversed mapping:
$reversedMapping = PresetMappingFactory::fromObjectCacheReversed($objectCache);

// ...

You can also generate the reversed mapping from the cache. i.e, a mapping from $book to BookDto::class will generate a PresetMapping containing the mapping from the previous result to Book::class.

use Rekalogika\Mapper\Transformer\Context\PresetMappingFactory;

$reversedPresetMapping = PresetMappingFactory::fromObjectCacheReversed($objectCache);

Example Use Case: Remembering Mapper

A mapper that remembers the previous mappings. So you can get the original source object if you have the resulting DTO.

use Rekalogika\Mapper\Context\Context;
use Rekalogika\Mapper\Exception\UnexpectedValueException;
use Rekalogika\Mapper\MapperInterface;
use Rekalogika\Mapper\ObjectCache\ObjectCacheFactoryInterface;
use Rekalogika\Mapper\Transformer\Context\PresetMapping;
use Rekalogika\Mapper\Transformer\Context\PresetMappingFactory;
use Symfony\Contracts\Service\ResetInterface;

class RememberingMapper implements MapperInterface, ResetInterface
{
private PresetMapping $presetMapping;

public function __construct(
private MapperInterface $decorated,
private ObjectCacheFactoryInterface $objectCacheFactory
) {
$this->presetMapping = new PresetMapping();
}

public function reset(): void
{
$this->presetMapping = new PresetMapping();
}

public function map(
object $source,
object|string $target,
?Context $context = null
): object {
$objectCache = $this->objectCacheFactory->createObjectCache();

$context ??= Context::create();
$context = $context->with($objectCache, $this->presetMapping);

$result = $this->decorated->map($source, $target, $context);

$newPresetMapping = PresetMappingFactory::fromObjectCacheReversed($objectCache);
$this->presetMapping->mergeFrom($newPresetMapping);

return $result;
}
}