Skip to content

Commit 5a34949

Browse files
committed
Add import file uploader
1 parent 9ac99e2 commit 5a34949

File tree

11 files changed

+135
-24
lines changed

11 files changed

+135
-24
lines changed

config/config/grid/process_import.yaml

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

config/services.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
<argument type="service" id="sylius_import_export.repository.process_import" />
5858
<argument type="service" id="sylius_import_export.denormalizer.registry" />
5959
<argument type="service" id="doctrine.orm.entity_manager" />
60+
<argument type="service" id="sylius.resource_registry" />
6061

6162
<tag name="messenger.message_handler" bus="sylius.command_bus" />
6263
</service>
@@ -100,10 +101,16 @@
100101
<tag name="controller.service_arguments" />
101102
</service>
102103

104+
<service id="sylius_import_export.uploader.import_file" class="Sylius\ImportExport\Uploader\ImportFileUploader">
105+
<argument>%sylius_import_export.import_files_directory%</argument>
106+
</service>
107+
103108
<service id="sylius_import_export.controller.import_action" class="Sylius\ImportExport\Controller\ImportAction" public="true">
104109
<argument type="service" id="form.factory" />
105110
<argument type="service" id="sylius.command_bus" />
106111
<argument>%sylius_import_export.import.form_class%</argument>
112+
<argument type="service" id="sylius_import_export.uploader.import_file" />
113+
<argument type="service" id="sylius.resource_registry" />
107114

108115
<tag name="controller.service_arguments" />
109116
</service>

config/services/form.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@
2222
</service>
2323

2424
<service id="sylius_import_export.form.type.import" class="Sylius\ImportExport\Form\Type\ImportResourceType">
25-
<argument>%kernel.project_dir%</argument>
26-
25+
<argument>%sylius_import_export.import.file_max_size%</argument>
26+
<argument>%sylius_import_export.import.allowed_mime_types%</argument>
27+
2728
<tag name="form.type" />
2829
</service>
2930
</services>

src/Controller/ImportAction.php

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
namespace Sylius\ImportExport\Controller;
1515

1616
use Sylius\ImportExport\Messenger\Command\CreateImportProcess;
17+
use Sylius\ImportExport\Uploader\ImportFileUploader;
18+
use Sylius\Resource\Metadata\RegistryInterface;
1719
use Symfony\Component\Form\FormFactoryInterface;
20+
use Symfony\Component\HttpFoundation\File\UploadedFile;
1821
use Symfony\Component\HttpFoundation\RedirectResponse;
1922
use Symfony\Component\HttpFoundation\Request;
2023
use Symfony\Component\HttpFoundation\Response;
@@ -27,6 +30,8 @@ public function __construct(
2730
private FormFactoryInterface $formFactory,
2831
private MessageBusInterface $commandBus,
2932
private string $importForm,
33+
private ImportFileUploader $importFileUploader,
34+
private RegistryInterface $metadataRegistry,
3035
) {
3136
}
3237

@@ -39,27 +44,43 @@ public function __invoke(Request $request, string $grid): Response
3944
$form->handleRequest($request);
4045

4146
if (!$form->isSubmitted() || !$form->isValid()) {
42-
$session->getFlashBag()->add('error', 'sylius_import_export.import_form_invalid');
47+
if ($form->isSubmitted()) {
48+
$errors = [];
49+
foreach ($form->getErrors(true) as $error) {
50+
$errors[] = $error->getMessage();
51+
}
52+
$errorMessage = !empty($errors) ? implode(', ', $errors) : 'sylius_import_export.import_form_invalid';
53+
$session->getFlashBag()->add('error', $errorMessage);
54+
} else {
55+
$session->getFlashBag()->add('error', 'sylius_import_export.import_form_invalid');
56+
}
4357

4458
return new RedirectResponse($request->headers->get('referer') ?? '/');
4559
}
4660

4761
$data = $form->getData();
48-
$format = $data['format'];
49-
$filePath = $data['filePath'];
5062
$resourceClass = $data['resourceClass'];
5163

64+
/** @var UploadedFile $file */
65+
$file = $data['file'];
66+
5267
try {
68+
$format = $this->importFileUploader->getFormatFromMimeType($file->getMimeType());
69+
$filePath = $this->importFileUploader->upload($file);
70+
71+
$metadata = $this->metadataRegistry->getByClass($resourceClass);
72+
$resourceAlias = $metadata->getAlias();
73+
5374
$this->commandBus->dispatch(new CreateImportProcess(
54-
resource: $resourceClass,
75+
resource: $resourceAlias,
5576
format: $format,
5677
filePath: $filePath,
5778
parameters: [],
5879
));
5980

6081
$session->getFlashBag()->add('success', 'sylius_import_export.import_started');
61-
} catch (\Throwable) {
62-
$session->getFlashBag()->add('error', 'sylius_import_export.import_failed');
82+
} catch (\Throwable $e) {
83+
$session->getFlashBag()->add('error', 'sylius_import_export.upload_failed');
6384
}
6485

6586
return new RedirectResponse($request->headers->get('referer') ?? '/');

src/DependencyInjection/SyliusImportExportExtension.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,9 @@ private function processExportConfig(ContainerBuilder $container, array &$config
4747
$container->setParameter('sylius_import_export.export.default_provider', $defaultProvider);
4848
$container->setParameter('sylius_import_export.export.resources', $config['export']['resources']);
4949
$container->setParameter('sylius_import_export.export_files_directory', '%kernel.project_dir%/var/export');
50+
$container->setParameter('sylius_import_export.import_files_directory', '%kernel.project_dir%/var/import');
51+
52+
$container->setParameter('sylius_import_export.import.file_max_size', '50M');
53+
$container->setParameter('sylius_import_export.import.allowed_mime_types', ['application/json']);
5054
}
5155
}

src/Form/Type/ImportResourceType.php

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,39 @@
1414
namespace Sylius\ImportExport\Form\Type;
1515

1616
use Symfony\Component\Form\AbstractType;
17-
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
17+
use Symfony\Component\Form\Extension\Core\Type\FileType;
1818
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
1919
use Symfony\Component\Form\FormBuilderInterface;
20+
use Symfony\Component\Validator\Constraints\File;
21+
use Symfony\Component\Validator\Constraints\NotBlank;
2022

2123
final class ImportResourceType extends AbstractType
2224
{
2325
public function __construct(
24-
private string $projectDir,
26+
private string $fileMaxSize,
27+
private array $allowedMimeTypes,
2528
) {
2629
}
2730

2831
public function buildForm(FormBuilderInterface $builder, array $options): void
2932
{
3033
$builder
31-
->add('format', ChoiceType::class, [
32-
'label' => 'sylius_import_export.grid.form.format',
33-
'choices' => [
34-
'json' => 'json',
35-
'csv' => 'csv',
34+
->add('file', FileType::class, [
35+
'label' => 'sylius_import_export.grid.form.file',
36+
'required' => true,
37+
'constraints' => [
38+
new NotBlank([
39+
'message' => 'sylius_import_export.validation.import.file.not_blank',
40+
'groups' => ['sylius'],
41+
]),
42+
new File([
43+
'maxSize' => $this->fileMaxSize,
44+
'mimeTypes' => $this->allowedMimeTypes,
45+
'mimeTypesMessage' => 'sylius_import_export.validation.import.file.invalid_type',
46+
'maxSizeMessage' => 'sylius_import_export.validation.import.file.max_size',
47+
'groups' => ['sylius'],
48+
]),
3649
],
37-
'data' => 'json', // Default to JSON for testing
38-
])
39-
->add('filePath', HiddenType::class, [
40-
'data' => $this->projectDir . '/var/exported/export.json', // Hardcoded path
4150
])
4251
->add('resourceClass', HiddenType::class)
4352
;

src/Messenger/Handler/ImportCommandHandler.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Sylius\ImportExport\Exception\ImportFailedException;
2020
use Sylius\ImportExport\Messenger\Command\ImportCommand;
2121
use Sylius\Resource\Doctrine\Persistence\RepositoryInterface;
22+
use Sylius\Resource\Metadata\RegistryInterface;
2223

2324
class ImportCommandHandler
2425
{
@@ -27,6 +28,7 @@ public function __construct(
2728
protected RepositoryInterface $processRepository,
2829
protected DenormalizerRegistryInterface $denormalizerRegistry,
2930
protected EntityManagerInterface $entityManager,
31+
protected RegistryInterface $metadataRegistry,
3032
) {
3133
}
3234

@@ -39,7 +41,8 @@ public function __invoke(ImportCommand $command): void
3941

4042
try {
4143
$importedCount = 0;
42-
$resourceClass = $process->getResource();
44+
$resourceMetadata = $this->metadataRegistry->get($process->getResource());
45+
$resourceClass = $resourceMetadata->getClass('model');
4346
$denormalizer = $this->denormalizerRegistry->get($resourceClass);
4447

4548
foreach ($command->batchData as $recordData) {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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\Uploader;
15+
16+
use Symfony\Component\HttpFoundation\File\UploadedFile;
17+
18+
final readonly class ImportFileUploader
19+
{
20+
public function __construct(
21+
private string $importFilesDirectory,
22+
) {
23+
}
24+
25+
public function upload(UploadedFile $file): string
26+
{
27+
if (!is_dir($this->importFilesDirectory)) {
28+
mkdir($this->importFilesDirectory, 0755, true);
29+
}
30+
31+
$fileName = uniqid() . '_' . $file->getClientOriginalName();
32+
$filePath = $this->importFilesDirectory . '/' . $fileName;
33+
34+
$file->move($this->importFilesDirectory, $fileName);
35+
36+
return $filePath;
37+
}
38+
39+
public function getFormatFromMimeType(?string $mimeType): string
40+
{
41+
return match ($mimeType) {
42+
'application/json' => 'json',
43+
'text/csv', 'text/plain' => 'csv',
44+
default => 'json',
45+
};
46+
}
47+
}

templates/admin/import_export/component/main_import_form.html.twig

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,17 @@
1212
<button class="btn btn-primary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
1313
{{ 'sylius_import_export.ui.import'|trans }}
1414
</button>
15-
<div class="dropdown-menu p-4">
15+
<div class="dropdown-menu p-4" style="min-width: 300px;">
1616
{{ form_start(form, {'action': path('sylius_import_export.admin.resource.import', import_parameters), 'attr': {'novalidate': 'novalidate'}}) }}
1717

1818
<div class="mb-3">
19-
{{ form_row(form.format) }}
19+
{{ form_row(form.file) }}
2020
</div>
2121

2222
<div class="d-flex justify-content-end">
2323
{{ button.primary({'type': 'submit', 'text': 'sylius_import_export.ui.import'|trans}) }}
2424
</div>
2525

26-
{{ form_widget(form.filePath) }}
2726
{{ form_widget(form.resourceClass) }}
2827
{{ form_row(form._token) }}
2928
{{ form_end(form, {'render_rest': false}) }}

translations/flashes.en.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
sylius_import_export:
22
export_started: "Export started and will be processed in the background. You can check the status in the Import/Export processes list."
3+
import_failed: "Import failed"

0 commit comments

Comments
 (0)