Skip to content

Commit c5c4fc5

Browse files
committed
feat(doctrine): register doctrine provider
1 parent d8f2358 commit c5c4fc5

File tree

7 files changed

+66
-11
lines changed

7 files changed

+66
-11
lines changed

src/AutoMapper.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212
use AutoMapper\Loader\FileLoader;
1313
use AutoMapper\Metadata\MetadataFactory;
1414
use AutoMapper\Metadata\MetadataRegistry;
15+
use AutoMapper\Provider\Doctrine\DoctrineProvider;
1516
use AutoMapper\Provider\ProviderInterface;
1617
use AutoMapper\Provider\ProviderRegistry;
1718
use AutoMapper\Symfony\ExpressionLanguageProvider;
1819
use AutoMapper\Transformer\PropertyTransformer\PropertyTransformerInterface;
1920
use AutoMapper\Transformer\PropertyTransformer\PropertyTransformerRegistry;
2021
use AutoMapper\Transformer\TransformerFactoryInterface;
2122
use Doctrine\Common\Annotations\AnnotationReader;
23+
use Doctrine\ORM\EntityManagerInterface;
2224
use Symfony\Component\EventDispatcher\EventDispatcher;
2325
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
2426
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
@@ -147,6 +149,7 @@ public static function create(
147149
?ExpressionLanguageProvider $expressionLanguageProvider = null,
148150
EventDispatcherInterface $eventDispatcher = new EventDispatcher(),
149151
iterable $providers = [],
152+
?EntityManagerInterface $entityManager = null,
150153
): AutoMapperInterface {
151154
if (\count($transformerFactories) > 0) {
152155
trigger_deprecation('jolicode/automapper', '9.0', 'The "$transformerFactories" property will be removed in version 10.0, AST transformer factories must be included within AutoMapper.', __METHOD__);
@@ -175,6 +178,12 @@ public static function create(
175178
$classDiscriminatorFromClassMetadata = new ClassDiscriminatorFromClassMetadata($classMetadataFactory);
176179
}
177180

181+
$providers = iterator_to_array($providers);
182+
183+
if (null !== $entityManager) {
184+
$providers[] = new DoctrineProvider($entityManager);
185+
}
186+
178187
$customTransformerRegistry = new PropertyTransformerRegistry($propertyTransformers);
179188
$metadataRegistry = new MetadataRegistry($configuration);
180189
$providerRegistry = new ProviderRegistry($providers);
@@ -189,7 +198,8 @@ public static function create(
189198
$classMetadataFactory,
190199
$nameConverter,
191200
$expressionLanguage,
192-
$eventDispatcher
201+
$eventDispatcher,
202+
$entityManager,
193203
);
194204

195205
$mapperGenerator = new MapperGenerator(
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace AutoMapper\EventListener\Doctrine;
6+
7+
use AutoMapper\Event\GenerateMapperEvent;
8+
use AutoMapper\Provider\Doctrine\DoctrineProvider;
9+
use Doctrine\ORM\EntityManagerInterface;
10+
11+
final readonly class DoctrineProviderListener
12+
{
13+
public function __construct(
14+
private EntityManagerInterface $entityManager
15+
) {
16+
}
17+
18+
public function __invoke(GenerateMapperEvent $event): void
19+
{
20+
if (!$this->entityManager->getMetadataFactory()->hasMetadataFor($event->mapperMetadata->target)) {
21+
return;
22+
}
23+
24+
$event->provider = DoctrineProvider::class;
25+
}
26+
}

src/Metadata/MetadataFactory.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use AutoMapper\Event\PropertyMetadataEvent;
1010
use AutoMapper\Event\SourcePropertyMetadata as SourcePropertyMetadataEvent;
1111
use AutoMapper\Event\TargetPropertyMetadata as TargetPropertyMetadataEvent;
12+
use AutoMapper\EventListener\Doctrine\DoctrineProviderListener;
1213
use AutoMapper\EventListener\MapFromListener;
1314
use AutoMapper\EventListener\MapperListener;
1415
use AutoMapper\EventListener\MapProviderListener;
@@ -44,6 +45,7 @@
4445
use AutoMapper\Transformer\TransformerFactoryInterface;
4546
use AutoMapper\Transformer\UniqueTypeTransformerFactory;
4647
use AutoMapper\Transformer\VoidTransformer;
48+
use Doctrine\ORM\EntityManagerInterface;
4749
use Symfony\Component\EventDispatcher\EventDispatcher;
4850
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
4951
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
@@ -340,6 +342,7 @@ public static function create(
340342
AdvancedNameConverterInterface|NameConverterInterface|null $nameConverter = null,
341343
ExpressionLanguage $expressionLanguage = new ExpressionLanguage(),
342344
EventDispatcherInterface $eventDispatcher = new EventDispatcher(),
345+
EntityManagerInterface|null $entityManager = null,
343346
): self {
344347
// Create property info extractors
345348
$flags = ReflectionExtractor::ALLOW_PUBLIC;
@@ -361,6 +364,10 @@ public static function create(
361364
$eventDispatcher->addListener(PropertyMetadataEvent::class, new AdvancedNameConverterListener($nameConverter));
362365
}
363366

367+
if (null !== $entityManager) {
368+
$eventDispatcher->addListener(GenerateMapperEvent::class, new DoctrineProviderListener($entityManager));
369+
}
370+
364371
$eventDispatcher->addListener(PropertyMetadataEvent::class, new MapToContextListener($reflectionExtractor));
365372
$eventDispatcher->addListener(GenerateMapperEvent::class, new MapToListener($customTransformerRegistry, $expressionLanguage));
366373
$eventDispatcher->addListener(GenerateMapperEvent::class, new MapFromListener($customTransformerRegistry, $expressionLanguage));
Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,33 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace AutoMapper\Provider\Doctrine;
46

57
use AutoMapper\Provider\ProviderInterface;
68
use Doctrine\ORM\EntityManagerInterface;
79

810
final readonly class DoctrineProvider implements ProviderInterface
911
{
10-
public function __construct(private EntityManagerInterface $entityManager)
11-
{
12+
public function __construct(
13+
private EntityManagerInterface $entityManager
14+
) {
1215
}
1316

1417
public function provide(string $targetType, mixed $source, array $context): object|array|null
1518
{
1619
$metadata = $this->entityManager->getClassMetadata($targetType);
17-
$entity = $metadata->identifier;
20+
// @TODO support multiple identifiers
21+
$identifier = $metadata->identifier;
1822

19-
$this->entityManager->createQueryBuilder()
23+
$result = $this->entityManager->createQueryBuilder()
2024
->select('e')
2125
->from($targetType, 'e')
22-
->where('e.' . $entity . ' = :id')
23-
->setParameter('id', $source)
26+
->where('e.' . $identifier[0] . ' = :id')
27+
->setParameter('id', $source[$identifier[0]])
2428
->getQuery()
2529
->getOneOrNullResult();
2630

31+
return $result;
2732
}
28-
}
33+
}

tests/AutoMapperBuilder.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use AutoMapper\Configuration;
99
use AutoMapper\ConstructorStrategy;
1010
use AutoMapper\Symfony\ExpressionLanguageProvider;
11+
use Doctrine\ORM\EntityManagerInterface;
1112
use Symfony\Component\EventDispatcher\EventDispatcher;
1213
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
1314
use Symfony\Component\Filesystem\Filesystem;
@@ -28,6 +29,7 @@ public static function buildAutoMapper(
2829
string $dateTimeFormat = \DateTimeInterface::RFC3339,
2930
?ExpressionLanguageProvider $expressionLanguageProvider = null,
3031
EventDispatcherInterface $eventDispatcher = new EventDispatcher(),
32+
?EntityManagerInterface $entityManager = null,
3133
): AutoMapper {
3234
$skipCacheRemove = $_SERVER['SKIP_CACHE_REMOVE'] ?? false;
3335

@@ -52,6 +54,7 @@ classPrefix: $classPrefix,
5254
expressionLanguageProvider: $expressionLanguageProvider,
5355
eventDispatcher: $eventDispatcher,
5456
providers: $providers,
57+
entityManager: $entityManager,
5558
);
5659
}
5760
}

tests/Doctrine/DoctrineTest.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace AutoMapper\Tests\Doctrine;
66

7+
use AutoMapper\Tests\AutoMapperBuilder;
78
use AutoMapper\Tests\AutoMapperTestCase;
89
use AutoMapper\Tests\Doctrine\Entity\Book;
910
use Doctrine\DBAL\DriverManager;
@@ -23,9 +24,12 @@ protected function setUp(): void
2324
{
2425
parent::setUp();
2526
$this->buildDatabase();
27+
28+
$this->autoMapper = AutoMapperBuilder::buildAutoMapper(entityManager: $this->entityManager);
2629
}
2730

28-
private function buildDatabase() {
31+
private function buildDatabase()
32+
{
2933
// delete the database file
3034
if (file_exists(__DIR__ . '/db.sqlite')) {
3135
unlink(__DIR__ . '/db.sqlite');
@@ -70,4 +74,4 @@ public function testAutoMapping(): void
7074

7175
$this->assertEquals('John Doe', $book->author);
7276
}
73-
}
77+
}

tests/Doctrine/Entity/Book.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ class Book
2626
public string $author = '';
2727

2828
#[ORM\OneToMany(targetEntity: Review::class, mappedBy: 'book', cascade: ['persist', 'remove'])]
29+
/** @var Collection<int, Review> */
2930
public Collection $reviews;
3031

3132
public function __construct()
3233
{
3334
$this->reviews = new ArrayCollection();
34-
3535
}
3636
}

0 commit comments

Comments
 (0)