Skip to content

Commit 12c24d0

Browse files
committed
Enhance denormalizers to handle relations
1 parent 6c2b59e commit 12c24d0

File tree

20 files changed

+461
-161
lines changed

20 files changed

+461
-161
lines changed

config/config/grid/process_import.yaml

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,4 @@ sylius_grid:
2828
actions:
2929
item:
3030
show:
31-
type: show
32-
delete:
33-
type: delete
34-
options:
35-
enabled: "resource.status in ['failed', 'cancelled']"
36-
bulk:
37-
delete:
38-
type: delete
39-
options:
40-
enabled: "resource.status in ['failed', 'cancelled']"
31+
type: show

config/config/sylius_grid.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ sylius_grid:
55
templates:
66
action:
77
export: '@SyliusImportExport\admin\import_export\grid\action\export.html.twig'
8+
import: '@SyliusImportExport\admin\import_export\grid\action\import.html.twig'
89
download: '@SyliusImportExport\admin\import_export\grid\action\download.html.twig'
910
bulk_action:
1011
export: '@SyliusImportExport\admin\import_export\grid\bulk_action\export.html.twig'

config/routes/admin.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ sylius_import_export.admin.resource.export:
66
_sylius:
77
filterable: true
88

9+
sylius_import_export.admin.resource.import:
10+
path: /import/{grid}
11+
methods: [POST]
12+
defaults:
13+
_controller: sylius_import_export.controller.import_action
14+
_sylius:
15+
filterable: true
16+
917
sylius_import_export_admin_process_export:
1018
resource: |
1119
alias: sylius_import_export.process_export

config/services.xml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@
100100
<tag name="controller.service_arguments" />
101101
</service>
102102

103+
<service id="sylius_import_export.controller.import_action" class="Sylius\ImportExport\Controller\ImportAction" public="true">
104+
<argument type="service" id="sylius.resource_registry" />
105+
<argument type="service" id="form.factory" />
106+
<argument type="service" id="sylius.command_bus" />
107+
<argument>%sylius_import_export.import.form_class%</argument>
108+
109+
<tag name="controller.service_arguments" />
110+
</service>
111+
103112
<service id="sylius_import_export.factory.process" class="Sylius\ImportExport\Factory\ProcessFactory">
104113
<argument type="service" id="sylius_import_export.factory.process_export" />
105114
<argument type="service" id="sylius_import_export.factory.process_import" />
@@ -125,5 +134,17 @@
125134
>
126135
<argument type="service" id=".inner" />
127136
</service>
137+
138+
<service id="sylius_import_export.twig.component.import_resource" class="Sylius\ImportExport\Twig\Component\ImportResourceFormComponent">
139+
<argument type="service" id="form.factory" />
140+
<argument>%sylius_import_export.import.form_class%</argument>
141+
142+
<tag
143+
name="twig.component"
144+
key="sylius_import_export:admin:import"
145+
template="@SyliusImportExport\admin\import_export\component\main_import_form.html.twig"
146+
/>
147+
</service>
148+
128149
</services>
129150
</container>

config/services/denormalizer.xml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,20 @@
55
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
66

77
<services>
8-
<service id="sylius_import_export.denormalizer.relation_resolver" class="Sylius\ImportExport\Denormalizer\DoctrineRelationResolver">
8+
<service id="sylius_import_export.denormalizer.entity_relation" class="Sylius\ImportExport\Denormalizer\EntityRelationDenormalizer">
99
<argument type="service" id="doctrine.orm.entity_manager" />
10+
<tag name="serializer.normalizer" priority="64" />
1011
</service>
1112

1213
<service id="sylius_import_export.denormalizer.default_resource" class="Sylius\ImportExport\Denormalizer\DefaultResourceDenormalizer">
1314
<argument type="service" id="serializer" />
14-
<argument type="service" id="sylius_import_export.denormalizer.relation_resolver" />
15-
<argument type="service" id="doctrine.orm.entity_manager" />
1615
</service>
16+
<service id="Sylius\ImportExport\Denormalizer\ResourceDenormalizerInterface" alias="sylius_import_export.denormalizer.default_resource" />
1717

1818
<service id="sylius_import_export.denormalizer.registry" class="Sylius\ImportExport\Denormalizer\DenormalizerRegistry">
1919
<argument type="service" id="sylius_import_export.denormalizer.default_resource" />
2020
<argument type="tagged_iterator" tag="sylius_import_export.resource_denormalizer" />
2121
</service>
22-
2322
<service id="Sylius\ImportExport\Denormalizer\DenormalizerRegistryInterface" alias="sylius_import_export.denormalizer.registry" />
24-
<service id="Sylius\ImportExport\Denormalizer\RelationResolverInterface" alias="sylius_import_export.denormalizer.relation_resolver" />
2523
</services>
26-
</container>
24+
</container>

config/services/form.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
>
88
<parameters>
99
<parameter key="sylius_import_export.export.form_class">Sylius\ImportExport\Form\Type\ExportResourceType</parameter>
10+
<parameter key="sylius_import_export.import.form_class">Sylius\ImportExport\Form\Type\ImportResourceType</parameter>
1011
</parameters>
1112

1213
<services>
@@ -19,5 +20,11 @@
1920

2021
<tag name="form.type" />
2122
</service>
23+
24+
<service id="sylius_import_export.form.type.import" class="Sylius\ImportExport\Form\Type\ImportResourceType">
25+
<argument>%kernel.project_dir%</argument>
26+
27+
<tag name="form.type" />
28+
</service>
2229
</services>
2330
</container>

config/services/grid.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,13 @@
2727

2828
<tag name="kernel.event_listener" event="sylius.grid.common" method="addExportActions" />
2929
</service>
30+
31+
<service id="sylius_import_export.grid.listener.admin.import_action" class="Sylius\ImportExport\Grid\Listener\ImportActionAdminGridListener">
32+
<argument type="service" id="request_stack" />
33+
<argument type="service" id="sylius.section_resolver.uri_based" on-invalid="null" />
34+
<argument type="service" id="sylius_import_export.grid.checker.exportable" />
35+
36+
<tag name="kernel.event_listener" event="sylius.grid.common" method="addImportActions" />
37+
</service>
3038
</services>
3139
</container>

src/Controller/ImportAction.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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\Controller;
15+
16+
use Sylius\ImportExport\Messenger\Command\CreateImportProcess;
17+
use Sylius\Resource\Metadata\RegistryInterface;
18+
use Symfony\Component\Form\FormFactoryInterface;
19+
use Symfony\Component\HttpFoundation\RedirectResponse;
20+
use Symfony\Component\HttpFoundation\Request;
21+
use Symfony\Component\HttpFoundation\Response;
22+
use Symfony\Component\HttpFoundation\Session\Session;
23+
use Symfony\Component\Messenger\MessageBusInterface;
24+
25+
final class ImportAction
26+
{
27+
public function __construct(
28+
private RegistryInterface $metadataRegistry,
29+
private FormFactoryInterface $formFactory,
30+
private MessageBusInterface $commandBus,
31+
private string $importForm,
32+
) {
33+
}
34+
35+
public function __invoke(Request $request, string $grid): Response
36+
{
37+
$request->attributes->set('_sylius', array_merge($request->attributes->get('_sylius', []), ['grid' => $grid]));
38+
39+
$form = $this->formFactory->create($this->importForm);
40+
$form->handleRequest($request);
41+
42+
if (!$form->isSubmitted() || !$form->isValid()) {
43+
/** @var Session $session */
44+
$session = $request->getSession();
45+
$session->getFlashBag()->add('error', 'sylius_import_export.import_form_invalid');
46+
47+
return new RedirectResponse($request->headers->get('referer') ?? '/');
48+
}
49+
50+
$data = $form->getData();
51+
$format = $data['format'];
52+
$filePath = $data['filePath'];
53+
$resourceClass = $data['resourceClass'];
54+
55+
// Get metadata to find the resource alias
56+
$metadata = $this->metadataRegistry->getByClass($resourceClass);
57+
58+
try {
59+
$this->commandBus->dispatch(new CreateImportProcess(
60+
resource: $resourceClass, // Pass the actual class, not the alias
61+
format: $format,
62+
filePath: $filePath,
63+
parameters: [], // Empty for now
64+
));
65+
66+
/** @var Session $session */
67+
$session = $request->getSession();
68+
$session->getFlashBag()->add('success', 'sylius_import_export.import_started');
69+
} catch (\Throwable $e) {
70+
/** @var Session $session */
71+
$session = $request->getSession();
72+
$session->getFlashBag()->add('error', 'sylius_import_export.import_failed: ' . $e->getMessage());
73+
}
74+
75+
return new RedirectResponse($request->headers->get('referer') ?? '/');
76+
}
77+
}

src/Denormalizer/DefaultResourceDenormalizer.php

Lines changed: 13 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,61 +13,30 @@
1313

1414
namespace Sylius\ImportExport\Denormalizer;
1515

16-
use Doctrine\ORM\EntityManagerInterface;
16+
use Sylius\ImportExport\Serializer\ExportAwareItemNormalizer;
17+
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
18+
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
1719
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
18-
use Webmozart\Assert\Assert;
1920

2021
final readonly class DefaultResourceDenormalizer implements ResourceDenormalizerInterface
2122
{
2223
public function __construct(
2324
private DenormalizerInterface $denormalizer,
24-
private RelationResolverInterface $relationResolver,
25-
private EntityManagerInterface $entityManager,
2625
) {
2726
}
2827

2928
public function denormalize(array $data, string $resourceClass): object
3029
{
31-
$metadata = $this->entityManager->getClassMetadata($resourceClass);
32-
$processedData = [];
33-
34-
foreach ($data as $field => $value) {
35-
if (null === $value || '' === $value) {
36-
continue;
37-
}
38-
39-
if ($metadata->hasAssociation($field)) {
40-
$associationMapping = $metadata->getAssociationMapping($field);
41-
$targetEntity = $associationMapping['targetEntity'];
42-
Assert::string($targetEntity);
43-
44-
if ($metadata->isCollectionValuedAssociation($field)) {
45-
if (is_array($value) && !empty($value)) {
46-
$processedData[$field] = $this->relationResolver->resolveCollection($targetEntity, $value);
47-
} else {
48-
$processedData[$field] = [];
49-
}
50-
} else {
51-
if (is_array($value) && !empty($value)) {
52-
$processedData[$field] = $this->relationResolver->resolveEntity($targetEntity, $value);
53-
}
54-
}
55-
} elseif (is_array($value)) {
56-
$processedData[$field] = $this->processNestedArray($value);
57-
} else {
58-
$processedData[$field] = $value;
59-
}
60-
}
61-
62-
$result = $this->denormalizer->denormalize($processedData, $resourceClass);
63-
Assert::object($result);
64-
65-
return $result;
66-
}
67-
68-
private function processNestedArray(array $data): array
69-
{
70-
return $data;
30+
return $this->denormalizer->denormalize(
31+
$data,
32+
$resourceClass,
33+
null,
34+
[
35+
ExportAwareItemNormalizer::EXPORT_CONTEXT_KEY => true,
36+
DateTimeNormalizer::FORMAT_KEY => 'Y-m-d H:i:s',
37+
AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE => true,
38+
],
39+
);
7140
}
7241

7342
public function supports(string $resourceClass): bool

src/Denormalizer/DoctrineRelationResolver.php

Lines changed: 0 additions & 78 deletions
This file was deleted.

0 commit comments

Comments
 (0)