Skip to content

Commit 76a6806

Browse files
committed
WIP
1 parent b3bde9a commit 76a6806

10 files changed

+280
-1
lines changed

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
"symfony/dependency-injection": "^6.4 || ^7.3",
2121
"symfony/framework-bundle": "^6.4 || ^7.3",
2222
"symfony/messenger": "^6.4 || ^7.3",
23+
"symfony/property-access": "^6.4 || ^7.3",
24+
"symfony/serializer": "^6.4 || ^7.3",
2325
"symfony/ux-live-component": "^2.12",
2426
"symfony/uid": "^6.4 || ^7.3"
2527
},

config/services.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@
5555

5656
<service id="sylius_import_export.messenger.command_handler.import" class="Sylius\ImportExport\Messenger\Handler\ImportCommandHandler">
5757
<argument type="service" id="sylius_import_export.repository.process_import" />
58+
<argument type="service" id="sylius_import_export.denormalizer.registry" />
59+
<argument type="service" id="doctrine.orm.entity_manager" />
5860

5961
<tag name="messenger.message_handler" bus="sylius.command_bus" />
6062
</service>

config/services/denormalizer.xml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
6+
7+
<services>
8+
<service id="sylius_import_export.denormalizer.relation_resolver" class="Sylius\ImportExport\Denormalizer\DoctrineRelationResolver">
9+
<argument type="service" id="doctrine.orm.entity_manager" />
10+
</service>
11+
12+
<service id="sylius_import_export.denormalizer.default_resource" class="Sylius\ImportExport\Denormalizer\DefaultResourceDenormalizer">
13+
<argument type="service" id="serializer" />
14+
<argument type="service" id="property_accessor" />
15+
<argument type="service" id="sylius_import_export.denormalizer.relation_resolver" />
16+
<argument type="service" id="doctrine.orm.entity_manager" />
17+
</service>
18+
19+
<service id="sylius_import_export.denormalizer.registry" class="Sylius\ImportExport\Denormalizer\DenormalizerRegistry">
20+
<argument type="service" id="sylius_import_export.denormalizer.default_resource" />
21+
<argument type="tagged_iterator" tag="sylius_import_export.resource_denormalizer" />
22+
</service>
23+
24+
<service id="Sylius\ImportExport\Denormalizer\DenormalizerRegistryInterface" alias="sylius_import_export.denormalizer.registry" />
25+
<service id="Sylius\ImportExport\Denormalizer\RelationResolverInterface" alias="sylius_import_export.denormalizer.relation_resolver" />
26+
</services>
27+
</container>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\ImportExport\Denormalizer;
15+
16+
use Doctrine\ORM\EntityManagerInterface;
17+
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
18+
use Symfony\Component\Serializer\SerializerInterface;
19+
20+
class DefaultResourceDenormalizer implements ResourceDenormalizerInterface
21+
{
22+
public function __construct(
23+
private SerializerInterface $serializer,
24+
private PropertyAccessorInterface $propertyAccessor,
25+
private RelationResolverInterface $relationResolver,
26+
private EntityManagerInterface $entityManager,
27+
) {
28+
}
29+
30+
public function denormalize(array $data, string $resourceClass): object
31+
{
32+
$metadata = $this->entityManager->getClassMetadata($resourceClass);
33+
$processedData = [];
34+
35+
foreach ($data as $field => $value) {
36+
if (null === $value || '' === $value) {
37+
continue;
38+
}
39+
40+
if ($metadata->hasAssociation($field)) {
41+
$associationMapping = $metadata->getAssociationMapping($field);
42+
$targetEntity = $associationMapping['targetEntity'];
43+
44+
if ($metadata->isCollectionValuedAssociation($field)) {
45+
$identifiers = is_array($value) ? $value : explode(',', (string) $value);
46+
$processedData[$field] = $this->relationResolver->resolveCollection(
47+
$targetEntity,
48+
array_filter(array_map('trim', $identifiers))
49+
);
50+
} else {
51+
$processedData[$field] = $this->relationResolver->resolveEntity($targetEntity, $value);
52+
}
53+
} else {
54+
$processedData[$field] = $value;
55+
}
56+
}
57+
58+
return $this->serializer->denormalize($processedData, $resourceClass);
59+
}
60+
61+
public function supports(string $resourceClass): bool
62+
{
63+
return true; // Default denormalizer supports all resources
64+
}
65+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\ImportExport\Denormalizer;
15+
16+
class DenormalizerRegistry implements DenormalizerRegistryInterface
17+
{
18+
/** @var ResourceDenormalizerInterface[] */
19+
private array $denormalizers = [];
20+
21+
private ResourceDenormalizerInterface $defaultDenormalizer;
22+
23+
/**
24+
* @param iterable<ResourceDenormalizerInterface> $denormalizers
25+
*/
26+
public function __construct(ResourceDenormalizerInterface $defaultDenormalizer, iterable $denormalizers = [])
27+
{
28+
$this->defaultDenormalizer = $defaultDenormalizer;
29+
30+
foreach ($denormalizers as $denormalizer) {
31+
$this->register($denormalizer);
32+
}
33+
}
34+
35+
public function register(ResourceDenormalizerInterface $denormalizer): void
36+
{
37+
$this->denormalizers[] = $denormalizer;
38+
}
39+
40+
public function get(string $resourceClass): ResourceDenormalizerInterface
41+
{
42+
foreach ($this->denormalizers as $denormalizer) {
43+
if ($denormalizer->supports($resourceClass)) {
44+
return $denormalizer;
45+
}
46+
}
47+
48+
return $this->defaultDenormalizer;
49+
}
50+
51+
public function has(string $resourceClass): bool
52+
{
53+
foreach ($this->denormalizers as $denormalizer) {
54+
if ($denormalizer->supports($resourceClass)) {
55+
return true;
56+
}
57+
}
58+
59+
return true; // Default denormalizer always available
60+
}
61+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\ImportExport\Denormalizer;
15+
16+
interface DenormalizerRegistryInterface
17+
{
18+
public function get(string $resourceClass): ResourceDenormalizerInterface;
19+
20+
public function has(string $resourceClass): bool;
21+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\ImportExport\Denormalizer;
15+
16+
use Doctrine\ORM\EntityManagerInterface;
17+
18+
class DoctrineRelationResolver implements RelationResolverInterface
19+
{
20+
public function __construct(
21+
private EntityManagerInterface $entityManager,
22+
) {
23+
}
24+
25+
public function resolveEntity(string $entityClass, mixed $identifier, string $identifierField = 'id'): ?object
26+
{
27+
if (null === $identifier || '' === $identifier) {
28+
return null;
29+
}
30+
31+
$repository = $this->entityManager->getRepository($entityClass);
32+
33+
if ('id' === $identifierField) {
34+
return $repository->find($identifier);
35+
}
36+
37+
return $repository->findOneBy([$identifierField => $identifier]);
38+
}
39+
40+
public function resolveCollection(string $entityClass, array $identifiers, string $identifierField = 'id'): array
41+
{
42+
if (empty($identifiers)) {
43+
return [];
44+
}
45+
46+
$repository = $this->entityManager->getRepository($entityClass);
47+
48+
return $repository->findBy([$identifierField => $identifiers]);
49+
}
50+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\ImportExport\Denormalizer;
15+
16+
interface RelationResolverInterface
17+
{
18+
public function resolveEntity(string $entityClass, mixed $identifier, string $identifierField = 'id'): ?object;
19+
20+
public function resolveCollection(string $entityClass, array $identifiers, string $identifierField = 'id'): array;
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\ImportExport\Denormalizer;
15+
16+
interface ResourceDenormalizerInterface
17+
{
18+
public function denormalize(array $data, string $resourceClass): object;
19+
20+
public function supports(string $resourceClass): bool;
21+
}

src/Messenger/Handler/ImportCommandHandler.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
namespace Sylius\ImportExport\Messenger\Handler;
1515

16+
use Doctrine\ORM\EntityManagerInterface;
17+
use Sylius\ImportExport\Denormalizer\DenormalizerRegistryInterface;
1618
use Sylius\ImportExport\Entity\ImportProcessInterface;
1719
use Sylius\ImportExport\Exception\ImportFailedException;
1820
use Sylius\ImportExport\Messenger\Command\ImportCommand;
@@ -23,6 +25,8 @@ class ImportCommandHandler
2325
/** @param RepositoryInterface<ImportProcessInterface> $processRepository */
2426
public function __construct(
2527
protected RepositoryInterface $processRepository,
28+
protected DenormalizerRegistryInterface $denormalizerRegistry,
29+
protected EntityManagerInterface $entityManager,
2630
) {
2731
}
2832

@@ -35,13 +39,18 @@ public function __invoke(ImportCommand $command): void
3539

3640
try {
3741
$importedCount = 0;
42+
$resourceClass = $process->getResource();
43+
$denormalizer = $this->denormalizerRegistry->get($resourceClass);
3844

3945
foreach ($command->batchData as $recordData) {
40-
// TODO: Process the record
46+
$entity = $denormalizer->denormalize($recordData, $resourceClass);
47+
$this->entityManager->persist($entity);
4148

4249
++$importedCount;
4350
}
4451

52+
$this->entityManager->flush();
53+
4554
$process->setBatchesCount($process->getBatchesCount() - 1);
4655
$process->setImportedCount($process->getImportedCount() + $importedCount);
4756

0 commit comments

Comments
 (0)