Skip to content

Commit

Permalink
Merge pull request #89 from jolicode/feat/various-features
Browse files Browse the repository at this point in the history
Add normalizer format in context, allow skipping group checking, remove registry interface from normalizer
  • Loading branch information
joelwurtz committed Mar 22, 2024
2 parents 9f19cfe + b171133 commit de0e0fa
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 14 deletions.
5 changes: 4 additions & 1 deletion src/AutoMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
use AutoMapper\Transformer\PropertyTransformer\PropertyTransformerRegistry;
use AutoMapper\Transformer\TransformerFactoryInterface;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
Expand Down Expand Up @@ -125,6 +127,7 @@ public static function create(
array $transformerFactories = [],
iterable $propertyTransformers = [],
ExpressionLanguageProvider $expressionLanguageProvider = null,
EventDispatcherInterface $eventDispatcher = new EventDispatcher(),
): self {
if (class_exists(AttributeLoader::class)) {
$loaderClass = new AttributeLoader();
Expand All @@ -149,7 +152,7 @@ public static function create(
}

$customTransformerRegistry = new PropertyTransformerRegistry($propertyTransformers);
$metadataRegistry = MetadataRegistry::create($configuration, $customTransformerRegistry, $transformerFactories, $classMetadataFactory, $nameConverter, $expressionLanguage);
$metadataRegistry = MetadataRegistry::create($configuration, $customTransformerRegistry, $transformerFactories, $classMetadataFactory, $nameConverter, $expressionLanguage, $eventDispatcher);

$mapperGenerator = new MapperGenerator(
new ClassDiscriminatorResolver($classDiscriminatorFromClassMetadata),
Expand Down
1 change: 1 addition & 0 deletions src/Event/PropertyMetadataEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function __construct(
public ?bool $ignored = null,
public ?string $if = null,
public ?array $groups = null,
public ?bool $disableGroupsCheck = null,
) {
}
}
12 changes: 8 additions & 4 deletions src/Generator/PropertyConditionsGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,14 @@ public function generate(GeneratorMetadata $metadata, PropertyMetadata $property
$conditions[] = $this->propertyExistsForStdClass($metadata, $propertyMetadata);
$conditions[] = $this->propertyExistsForArray($metadata, $propertyMetadata);
$conditions[] = $this->isAllowedAttribute($metadata, $propertyMetadata);
$conditions[] = $this->groupsCheck($metadata->variableRegistry, $propertyMetadata->groups); // Property groups
$conditions[] = $this->groupsCheck($metadata->variableRegistry, $propertyMetadata->source->groups); // Source groups
$conditions[] = $this->groupsCheck($metadata->variableRegistry, $propertyMetadata->target->groups); // Target groups
$conditions[] = $this->noGroupsCheck($metadata, $propertyMetadata);

if (!$propertyMetadata->disableGroupsCheck) {
$conditions[] = $this->groupsCheck($metadata->variableRegistry, $propertyMetadata->groups); // Property groups
$conditions[] = $this->groupsCheck($metadata->variableRegistry, $propertyMetadata->source->groups); // Source groups
$conditions[] = $this->groupsCheck($metadata->variableRegistry, $propertyMetadata->target->groups); // Target groups
$conditions[] = $this->noGroupsCheck($metadata, $propertyMetadata);
}

$conditions[] = $this->maxDepthCheck($metadata, $propertyMetadata);
$conditions[] = $this->customCondition($metadata, $propertyMetadata);

Expand Down
1 change: 1 addition & 0 deletions src/MapperContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class MapperContext
public const DATETIME_FORMAT = 'datetime_format';
public const DATETIME_FORCE_TIMEZONE = 'datetime_force_timezone';
public const MAP_TO_ACCESSOR_PARAMETER = 'map_to_accessor_parameter';
public const NORMALIZER_FORMAT = 'normalizer_format';

private array $context = [
self::DEPTH => 0,
Expand Down
3 changes: 2 additions & 1 deletion src/Metadata/MetadataRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ private function createGeneratorMetadata(MapperMetadata $mapperMetadata): Genera
$propertyMappedEvent->maxDepth,
$propertyMappedEvent->if,
$propertyMappedEvent->groups,
$propertyMappedEvent->disableGroupsCheck,
);
}

Expand All @@ -237,6 +238,7 @@ public static function create(
ClassMetadataFactory $classMetadataFactory = null,
AdvancedNameConverterInterface $nameConverter = null,
ExpressionLanguage $expressionLanguage = new ExpressionLanguage(),
EventDispatcherInterface $eventDispatcher = new EventDispatcher(),
): self {
// Create property info extractors
$flags = ReflectionExtractor::ALLOW_PUBLIC;
Expand All @@ -247,7 +249,6 @@ public static function create(

$reflectionExtractor = new ReflectionExtractor(accessFlags: $flags);
$phpStanExtractor = new PhpStanExtractor();
$eventDispatcher = new EventDispatcher();

if (null !== $nameConverter) {
$eventDispatcher->addListener(PropertyMetadataEvent::class, new AdvancedNameConverterListener($nameConverter));
Expand Down
1 change: 1 addition & 0 deletions src/Metadata/PropertyMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public function __construct(
public ?int $maxDepth = null,
public ?string $if = null,
public ?array $groups = null,
public ?bool $disableGroupsCheck = null,
) {
}
}
13 changes: 8 additions & 5 deletions src/Normalizer/AutoMapperNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace AutoMapper\Normalizer;

use AutoMapper\AutoMapperInterface;
use AutoMapper\AutoMapperRegistryInterface;
use AutoMapper\MapperContext;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
Expand All @@ -30,13 +29,13 @@
];

public function __construct(
private AutoMapperInterface&AutoMapperRegistryInterface $autoMapper,
private AutoMapperInterface $autoMapper,
) {
}

public function normalize(mixed $object, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
{
return $this->autoMapper->map($object, 'array', $this->createAutoMapperContext($context));
return $this->autoMapper->map($object, 'array', $this->createAutoMapperContext($format, $context));
}

/**
Expand All @@ -48,7 +47,7 @@ public function normalize(mixed $object, string $format = null, array $context =
*/
public function denormalize(mixed $data, string $type, string $format = null, array $context = []): mixed
{
return $this->autoMapper->map($data, $type, $this->createAutoMapperContext($context));
return $this->autoMapper->map($data, $type, $this->createAutoMapperContext($format, $context));
}

public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool
Expand All @@ -74,7 +73,7 @@ public function getSupportedTypes(?string $format): array
return ['object' => true];
}

private function createAutoMapperContext(array $serializerContext = []): array
private function createAutoMapperContext(string $format = null, array $serializerContext = []): array
{
$context = [];

Expand Down Expand Up @@ -103,6 +102,10 @@ private function createAutoMapperContext(array $serializerContext = []): array
}
}

if ($format !== null) {
$context[MapperContext::NORMALIZER_FORMAT] = $format;
}

return $context + $serializerContext;
}
}
4 changes: 4 additions & 0 deletions tests/AutoMapperBaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use AutoMapper\Configuration;
use AutoMapper\Symfony\ExpressionLanguageProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Filesystem\Filesystem;

/**
Expand All @@ -32,6 +34,7 @@ protected function buildAutoMapper(
array $propertyTransformers = [],
string $dateTimeFormat = \DateTimeInterface::RFC3339,
?ExpressionLanguageProvider $expressionLanguageProvider = null,
EventDispatcherInterface $eventDispatcher = new EventDispatcher(),
): AutoMapper {
$fs = new Filesystem();
$fs->remove(__DIR__ . '/cache/');
Expand All @@ -50,6 +53,7 @@ classPrefix: $classPrefix,
transformerFactories: $transformerFactories,
propertyTransformers: $propertyTransformers,
expressionLanguageProvider: $expressionLanguageProvider,
eventDispatcher: $eventDispatcher,
);
}
}
34 changes: 34 additions & 0 deletions tests/AutoMapperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use AutoMapper\AutoMapper;
use AutoMapper\Configuration;
use AutoMapper\Event\PropertyMetadataEvent;
use AutoMapper\Exception\CircularReferenceException;
use AutoMapper\Exception\NoMappingFoundException;
use AutoMapper\Exception\ReadOnlyTargetException;
Expand Down Expand Up @@ -41,6 +42,7 @@
use AutoMapper\Tests\Fixtures\Transformer\MoneyTransformerFactory;
use AutoMapper\Tests\Fixtures\Uninitialized;
use AutoMapper\Tests\Fixtures\UserPromoted;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Serializer\Attribute\Groups;
use Symfony\Component\Serializer\Attribute\Ignore;
Expand Down Expand Up @@ -316,6 +318,38 @@ public function testGroupsToArray(): void
self::assertArrayNotHasKey('id', $fooArray);
}

public function testSkippedGroups(): void
{
if (!class_exists(Groups::class)) {
self::markTestSkipped('Symfony Serializer is required to run this test.');
}

$eventDispatcher = new EventDispatcher();
$eventDispatcher->addListener(PropertyMetadataEvent::class, function (PropertyMetadataEvent $event) {
$event->disableGroupsCheck = true;
});

$this->buildAutoMapper(eventDispatcher: $eventDispatcher, classPrefix: 'SkippedGroups_');

$foo = new Fixtures\Foo();
$foo->setId(10);

$fooArray = $this->autoMapper->map($foo, 'array', [MapperContext::GROUPS => ['group1']]);

self::assertIsArray($fooArray);
self::assertEquals(10, $fooArray['id']);

$fooArray = $this->autoMapper->map($foo, 'array', [MapperContext::GROUPS => []]);

self::assertIsArray($fooArray);
self::assertEquals(10, $fooArray['id']);

$fooArray = $this->autoMapper->map($foo, 'array');

self::assertIsArray($fooArray);
self::assertEquals(10, $fooArray['id']);
}

public function testDeepCloning(): void
{
$nodeA = new Fixtures\Node();
Expand Down
9 changes: 6 additions & 3 deletions tests/Normalizer/AutoMapperNormalizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public function hasMapper(string $source, string $target): bool
}
);

$context = $normalizer->normalize(new Fixtures\User(1, 'Jack', 37), 'array', [
$context = $normalizer->normalize(new Fixtures\User(1, 'Jack', 37), 'json', [
AbstractNormalizer::GROUPS => ['foo'],
AbstractNormalizer::ATTRIBUTES => ['foo'],
AbstractNormalizer::IGNORED_ATTRIBUTES => ['foo'],
Expand All @@ -154,16 +154,19 @@ public function hasMapper(string $source, string $target): bool
MapperContext::CIRCULAR_REFERENCE_LIMIT => 1,
MapperContext::CIRCULAR_REFERENCE_HANDLER => 'circular-reference-handler',
MapperContext::DATETIME_FORMAT => 'Y-m-d',
MapperContext::NORMALIZER_FORMAT => 'json',
'custom-context' => 'some custom context',
],
$context
);

$context = $normalizer->normalize(new Fixtures\User(1, 'Jack', 37), 'array', [
$context = $normalizer->normalize(new Fixtures\User(1, 'Jack', 37), 'json', [
AbstractNormalizer::OBJECT_TO_POPULATE => 'bad-object',
]);

self::assertSame([], $context);
self::assertSame([
MapperContext::NORMALIZER_FORMAT => 'json',
], $context);
}

public function testItUsesSerializerDateFormatBasedOnSerializerContext(): void
Expand Down

0 comments on commit de0e0fa

Please sign in to comment.