-
Notifications
You must be signed in to change notification settings - Fork 20
Open
Description
Assuming we have the following code:
class Category
{
/** @var Post[] */
public array $posts = [];
public function __construct(
public string $name
) {
}
}
class Post
{
public function __construct(
public string $name,
public Category $category
) {
}
}
class CategoryDTO
{
/**
* @var PostDTO[]
*/
public array $posts = [];
public function __construct(
public string $name,
) {
}
}
class PostDTO
{
public function __construct(
public string $name,
public CategoryDTO $category,
) {
}
}the generated mapper becomes:
/** @param \AutoMapper\Tests\Fixtures\Category $value */
public function &map($value, array $context = []): mixed
{
if (null === $value) {
return $value;
}
$sourcehash = spl_object_hash($value) . 'AutoMapper\Tests\Fixtures\CategoryDTO';
if (\AutoMapper\MapperContext::shouldHandleCircularReference($context, $sourcehash)) {
return \AutoMapper\MapperContext::handleCircularReference($context, $sourcehash, $value);
}
/** @var \AutoMapper\Tests\Fixtures\CategoryDTO|null $result */
$result = $context['target_to_populate'] ?? null;
if (null === $result) {
$constructargs = [];
if (isset($value->name)) {
$constructargs['name'] = $value->name;
} elseif (\AutoMapper\MapperContext::hasConstructorArgument($context, 'AutoMapper\Tests\Fixtures\CategoryDTO', 'name')) {
$constructargs['name'] = \AutoMapper\MapperContext::getConstructorArgument($context, 'AutoMapper\Tests\Fixtures\CategoryDTO', 'name');
} else {
$constructargs['name'] = throw new \AutoMapper\Exception\MissingConstructorArgumentsException('Cannot create an instance of "AutoMapper\Tests\Fixtures\CategoryDTO" from mapping data because its constructor requires the following parameters to be present : "$name".', 0, null, ['name'], 'AutoMapper\Tests\Fixtures\CategoryDTO');
}
$result = new \AutoMapper\Tests\Fixtures\CategoryDTO(...$constructargs);
}
else {
$context = \AutoMapper\MapperContext::withReference($context, $sourcehash, $result);
$context = \AutoMapper\MapperContext::withIncrementedDepth($context);
if (\AutoMapper\MapperContext::isAllowedAttribute($context, 'name', function () use ($value) {
return !isset($value->name) and null === $value->name;
}, !array_key_exists('name', (array) $value)) && (!array_key_exists('groups', $context) || !$context['groups'])) {
$result->name = $value->name;
}
}
if (\AutoMapper\MapperContext::isAllowedAttribute($context, 'posts', function () use ($value) {
return !isset($value->posts) and null === $value->posts;
}, !array_key_exists('posts', (array) $value)) && (!array_key_exists('groups', $context) || !$context['groups'])) {
$values = $context['deep_target_to_populate'] ?? false ? isset($result->posts) ? $result->posts : [] : [];
foreach ($value->posts ?? [] as $key => $value_1) {
$values[] =& $this->mappers['Mapper_AutoMapper\Tests\Fixtures\Post_AutoMapper\Tests\Fixtures\PostDTO']->map($value_1, \AutoMapper\MapperContext::withNewContext($context, 'posts'));
}
$result->posts = $values;
}
return $result;
}As we can see, the context is only updated when we specify a target to fill. Otherwise it will cause an infinite loop. I would expect the mapper to handle this case as well.
Metadata
Metadata
Assignees
Labels
No labels