Open brendanjerwin opened 7 months ago
Hi @brendanjerwin, this is a good question. It is not part of the library right now.
Do you want every property to have an explicit operation defined, or is it also considered valid if mapping is possible with the default operation (i.e. mapping properties with the same name)? If the former, you could hack it in yourself using a bit of reflection:
<?php
require 'vendor/autoload.php';
use AutoMapperPlus\Configuration\AutoMapperConfig;
use AutoMapperPlus\AutoMapper;
use AutoMapperPlus\MappingOperation\Operation;
use AutoMapperPlus\Configuration\MappingInterface;
use AutoMapperPlus\MappingOperation\DefaultMappingOperation;
class CustomConfig extends AutoMapperConfig
{
private $configuredMappings = [];
public function registerMapping(
string $sourceClassName,
string $destinationClassName
): MappingInterface {
$this->configuredMappings[] = [$sourceClassName, $destinationClassName];
return parent::registerMapping($sourceClassName, $destinationClassName);
}
public function assertValid(): void {
foreach ($this->configuredMappings as [$sourceClassName, $destinationClassName]) {
$mapping = $this->getMappingFor($sourceClassName, $destinationClassName);
$sourceObject = (new \ReflectionClass($sourceClassName))->newInstance();
$destinationObject = (new \ReflectionClass($destinationClassName))->newInstance();
$properties = $mapping->getTargetProperties($destinationObject, $sourceObject);
foreach ($properties as $property) {
$operation = $mapping->getMappingOperationFor($property);
if ($operation instanceof DefaultMappingOperation) {
throw new \Exception("${destinationClassName}::${property} has no explicit mapping operation defined");
}
}
}
}
}
class ClassA
{
public $prop1 = 'property 1';
public $prop2 = 'property 2';
}
class ClassB
{
public $prop1;
public $prop2;
}
$config = new CustomConfig();
$config
->registerMapping(ClassA::class, ClassB::class)
->forMember('prop1', Operation::setTo('hardcoded prop'));
$mapper = new AutoMapper($config);
$config->assertValid();
The latter can also be done with some additions to the code above. I call it hacking, since the public API of the library doesn't expose which mappings are actually registered.
If fleshed out a bit, it could be a good feature to actually implement in the library.
A feature of the dotnet AutoMapper is
AssertConfigurationIsValid()
which will barf if a new property was added that was not able to be automagically mapped.I'm trying to find a way to assert the same here. A unit test that will fail if there is a destination or source property that doesn't have an operation.
How might I go about this? Am I missing something obvious already?