Skip to content

Commit dbb7b42

Browse files
committed
feat(doctrine): register doctrine provider
1 parent e6a6d60 commit dbb7b42

File tree

7 files changed

+65
-10
lines changed

7 files changed

+65
-10
lines changed

src/AutoMapper.php

Lines changed: 10 additions & 0 deletions
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;
@@ -148,6 +150,7 @@ public static function create(
148150
EventDispatcherInterface $eventDispatcher = new EventDispatcher(),
149151
iterable $providers = [],
150152
bool $removeDefaultProperties = false,
153+
?EntityManagerInterface $entityManager = null,
151154
): AutoMapperInterface {
152155
if (\count($transformerFactories) > 0) {
153156
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__);
@@ -176,6 +179,12 @@ public static function create(
176179
$classDiscriminatorFromClassMetadata = new ClassDiscriminatorFromClassMetadata($classMetadataFactory);
177180
}
178181

182+
$providers = iterator_to_array($providers);
183+
184+
if (null !== $entityManager) {
185+
$providers[] = new DoctrineProvider($entityManager);
186+
}
187+
179188
$customTransformerRegistry = new PropertyTransformerRegistry($propertyTransformers);
180189
$metadataRegistry = new MetadataRegistry($configuration);
181190
$providerRegistry = new ProviderRegistry($providers);
@@ -192,6 +201,7 @@ public static function create(
192201
$expressionLanguage,
193202
$eventDispatcher,
194203
$removeDefaultProperties,
204+
$entityManager,
195205
);
196206

197207
$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;
@@ -354,6 +356,7 @@ public static function create(
354356
ExpressionLanguage $expressionLanguage = new ExpressionLanguage(),
355357
EventDispatcherInterface $eventDispatcher = new EventDispatcher(),
356358
bool $removeDefaultProperties = false,
359+
?EntityManagerInterface $entityManager = null,
357360
): self {
358361
// Create property info extractors
359362
$flags = ReflectionExtractor::ALLOW_PUBLIC;
@@ -375,6 +378,10 @@ public static function create(
375378
$eventDispatcher->addListener(PropertyMetadataEvent::class, new AdvancedNameConverterListener($nameConverter));
376379
}
377380

381+
if (null !== $entityManager) {
382+
$eventDispatcher->addListener(GenerateMapperEvent::class, new DoctrineProviderListener($entityManager));
383+
}
384+
378385
$eventDispatcher->addListener(PropertyMetadataEvent::class, new MapToContextListener($reflectionExtractor));
379386
$eventDispatcher->addListener(GenerateMapperEvent::class, new MapToListener($customTransformerRegistry, $expressionLanguage));
380387
$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;
@@ -29,6 +30,7 @@ public static function buildAutoMapper(
2930
?ExpressionLanguageProvider $expressionLanguageProvider = null,
3031
EventDispatcherInterface $eventDispatcher = new EventDispatcher(),
3132
bool $removeDefaultProperties = false,
33+
?EntityManagerInterface $entityManager = null,
3234
): AutoMapper {
3335
$skipCacheRemove = $_SERVER['SKIP_CACHE_REMOVE'] ?? false;
3436

@@ -54,6 +56,7 @@ classPrefix: $classPrefix,
5456
eventDispatcher: $eventDispatcher,
5557
providers: $providers,
5658
removeDefaultProperties: $removeDefaultProperties,
59+
entityManager: $entityManager,
5760
);
5861
}
5962
}

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)