Skip to content

Commit aaf8d72

Browse files
committed
feat: import export bundle
1 parent b5f6712 commit aaf8d72

File tree

77 files changed

+2944
-272
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+2944
-272
lines changed

components/ImportExportBundle/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
],
2020
"require": {
2121
"php": "^7.3 || ^8.0",
22+
"craue/formflow-bundle": "^3.0"
2223
},
2324
"autoload": {
2425
"psr-4": {

components/ImportExportBundle/src/bundle/AlmaviaCXIbexaImportExportBundle.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,21 @@
44

55
namespace AlmaviaCX\Bundle\IbexaImportExportBundle;
66

7+
use AlmaviaCX\Bundle\IbexaImportExportBundle\DependencyInjection\Security\Provider\PolicyProvider;
8+
use Symfony\Component\DependencyInjection\ContainerBuilder;
79
use Symfony\Component\HttpKernel\Bundle\Bundle;
810

911
class AlmaviaCXIbexaImportExportBundle extends Bundle
1012
{
13+
/**
14+
* Builds the bundle.
15+
*
16+
* It is only ever called once when the cache is empty.
17+
*/
18+
public function build(ContainerBuilder $container): void
19+
{
20+
parent::build($container);
21+
$ibexaExtension = $container->getExtension('ibexa');
22+
$ibexaExtension->addPolicyProvider(new PolicyProvider());
23+
}
1124
}
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace AlmaviaCX\Bundle\IbexaImportExportBundle\Controller\Admin;
6+
7+
use AlmaviaCX\Bundle\IbexaImportExport\Job\Form\JobCreateFlow;
8+
use AlmaviaCX\Bundle\IbexaImportExport\Job\Job;
9+
use AlmaviaCX\Bundle\IbexaImportExport\Job\JobService;
10+
use AlmaviaCX\Bundle\IbexaImportExport\Writer\WriterRegistry;
11+
use Ibexa\Contracts\AdminUi\Controller\Controller;
12+
use Ibexa\Contracts\AdminUi\Notification\TranslatableNotificationHandlerInterface;
13+
use Ibexa\Contracts\Core\Repository\PermissionResolver;
14+
use Ibexa\Core\Base\Exceptions\NotFoundException;
15+
use Ibexa\Core\MVC\Symfony\Security\Authorization\Attribute;
16+
use Pagerfanta\Adapter\CallbackAdapter;
17+
use Pagerfanta\Pagerfanta;
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\VarExporter\Instantiator;
23+
use Twig\Environment;
24+
use Twig\Error\LoaderError;
25+
26+
class JobController extends Controller
27+
{
28+
protected FormFactoryInterface $formFactory;
29+
protected TranslatableNotificationHandlerInterface $notificationHandler;
30+
protected JobService $jobService;
31+
protected JobCreateFlow $jobCreateFlow;
32+
protected PermissionResolver $permissionResolver;
33+
protected Environment $twig;
34+
protected WriterRegistry $writerRegistry;
35+
36+
public function __construct(
37+
FormFactoryInterface $formFactory,
38+
TranslatableNotificationHandlerInterface $notificationHandler,
39+
JobService $jobService,
40+
JobCreateFlow $jobCreateFlow,
41+
PermissionResolver $permissionResolver,
42+
Environment $twig,
43+
WriterRegistry $writerRegistry
44+
) {
45+
$this->formFactory = $formFactory;
46+
$this->notificationHandler = $notificationHandler;
47+
$this->jobService = $jobService;
48+
$this->jobCreateFlow = $jobCreateFlow;
49+
$this->permissionResolver = $permissionResolver;
50+
$this->twig = $twig;
51+
$this->writerRegistry = $writerRegistry;
52+
}
53+
54+
public function listAction(Request $request): Response
55+
{
56+
$page = $request->query->get('page') ?? 1;
57+
58+
$pagerfanta = new Pagerfanta(
59+
new CallbackAdapter(
60+
function (): int {
61+
return $this->jobService->countJobs();
62+
},
63+
function (int $offset, int $length): array {
64+
return $this->jobService->loadJobs($length, $offset);
65+
}
66+
)
67+
);
68+
69+
$pagerfanta->setMaxPerPage(10);
70+
$pagerfanta->setCurrentPage(min($page, $pagerfanta->getNbPages()));
71+
72+
return $this->render('@ibexadesign/import_export/job/list.html.twig', [
73+
'pager' => $pagerfanta,
74+
'can_create' => $this->isGranted(new Attribute('import_export', 'job.create')),
75+
]);
76+
}
77+
78+
public function createAction(Request $request): Response
79+
{
80+
$job = Instantiator::instantiate(Job::class);
81+
$this->jobCreateFlow->bind($job);
82+
83+
$form = $this->jobCreateFlow->createForm();
84+
if ($this->jobCreateFlow->isValid($form)) {
85+
$this->jobCreateFlow->saveCurrentStepData($form);
86+
if ($this->jobCreateFlow->nextStep()) {
87+
// form for the next step
88+
$form = $this->jobCreateFlow->createForm();
89+
} else {
90+
$this->jobCreateFlow->reset();
91+
try {
92+
$job->setCreatorId($this->permissionResolver->getCurrentUserReference()->getUserId());
93+
$this->jobService->createJob($job);
94+
$this->notificationHandler->success(
95+
/* @Desc("Job '%label%' created.") */
96+
'job.create.success',
97+
['%label%' => $job->getLabel()],
98+
'importexport'
99+
);
100+
101+
return new RedirectResponse($this->generateUrl('import_export.job.view', [
102+
'id' => $job->getId(),
103+
]));
104+
} catch (\Exception $exception) {
105+
$this->notificationHandler->error(
106+
/* @Ignore */
107+
$exception->getMessage()
108+
);
109+
}
110+
}
111+
}
112+
113+
return $this->render('@ibexadesign/import_export/job/create.html.twig', [
114+
'form_job_create' => $form->createView(),
115+
'form_job_create_flow' => $this->jobCreateFlow,
116+
]);
117+
}
118+
119+
public function viewAction(Job $job): Response
120+
{
121+
$results = [];
122+
foreach ($job->getWriterResults() as $index => $writerResults) {
123+
try {
124+
$writerIdentifier = $writerResults['writerIdentifier'];
125+
$writer = $this->writerRegistry->get($writerIdentifier);
126+
$template = sprintf('@ibexadesign/import_export/writer/results/%s.html.twig', $writerIdentifier);
127+
$this->twig->load($template);
128+
129+
$results[] = [
130+
'template' => $template,
131+
'parameters' => [
132+
'results' => $writerResults,
133+
'writerIndex' => $index,
134+
'writer' => $writer,
135+
'job' => $job,
136+
],
137+
];
138+
} catch (LoaderError|NotFoundException $e) {
139+
continue;
140+
}
141+
}
142+
143+
return $this->render('@ibexadesign/import_export/job/view.html.twig', [
144+
'job' => $job,
145+
'results' => $results,
146+
]);
147+
}
148+
149+
public function processAction(Job $job): Response
150+
{
151+
$this->jobService->runJob($job);
152+
153+
return new RedirectResponse($this->generateUrl('import_export.job.view', [
154+
'id' => $job->getId(),
155+
]));
156+
}
157+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace AlmaviaCX\Bundle\IbexaImportExportBundle\Controller\Admin;
6+
7+
use AlmaviaCX\Bundle\IbexaImportExport\Job\Job;
8+
use AlmaviaCX\Bundle\IbexaImportExport\Writer\AbstractStreamWriter;
9+
use AlmaviaCX\Bundle\IbexaImportExport\Writer\WriterRegistry;
10+
use Ibexa\Contracts\AdminUi\Controller\Controller;
11+
use Symfony\Component\Filesystem\Filesystem;
12+
use Symfony\Component\HttpFoundation\Response;
13+
14+
class WriterController extends Controller
15+
{
16+
protected Filesystem $filesystem;
17+
protected WriterRegistry $writerRegistry;
18+
19+
public function __construct(Filesystem $filesystem, WriterRegistry $writerRegistry)
20+
{
21+
$this->filesystem = $filesystem;
22+
$this->writerRegistry = $writerRegistry;
23+
}
24+
25+
public function downloadFileAction(Job $job, $writerIndex)
26+
{
27+
// $writer = $this->writerRegistry->get($job->getWriterResults()[$writerIndex]['writerIdentifier']);
28+
// if (!$writer instanceof AbstractStreamWriter) {
29+
// exit();
30+
// }
31+
32+
// $filepath = $job->getWriterResults()[$writerIndex]['filePath'];
33+
34+
return new Response('');
35+
}
36+
}
Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,58 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace AlmaviaCX\Bundle\IbexaImportExportBundle\DependencyInjection;
46

57
use Symfony\Component\Config\FileLocator;
8+
use Symfony\Component\Config\Resource\FileResource;
69
use Symfony\Component\DependencyInjection\ContainerBuilder;
710
use Symfony\Component\DependencyInjection\Extension\Extension;
11+
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
812
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
13+
use Symfony\Component\Yaml\Yaml;
914

10-
class AlmaviaCXIbexaImportExportExtension extends Extension
15+
class AlmaviaCXIbexaImportExportExtension extends Extension implements PrependExtensionInterface
1116
{
12-
public function load( array $configs, ContainerBuilder $container )
17+
public function load(array $configs, ContainerBuilder $container)
1318
{
1419
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
1520
$loader->load('default_settings.yml');
1621
$loader->load('services.yml');
22+
$loader->load('job.yaml');
23+
$loader->load('workflow.yaml');
24+
$loader->load('workflow_reader.yaml');
25+
$loader->load('workflow_step.yaml');
26+
$loader->load('workflow_writer.yaml');
27+
$loader->load('object_accessor.yaml');
28+
$loader->load('content_field_value_transformer.yaml');
1729
}
1830

31+
public function prepend(ContainerBuilder $container)
32+
{
33+
$ibexaOrmConfig = [
34+
'orm' => [
35+
'entity_mappings' => [
36+
'AlmaviaCXIbexaImportExport' => [
37+
'type' => 'annotation',
38+
'dir' => __DIR__.'/../../lib',
39+
'prefix' => 'AlmaviaCX\Bundle\IbexaImportExport',
40+
'is_bundle' => false,
41+
],
42+
],
43+
],
44+
];
45+
$container->prependExtensionConfig('ibexa', $ibexaOrmConfig);
46+
47+
$configs = [
48+
'ibexa.yaml' => 'ibexa',
49+
];
50+
51+
foreach ($configs as $fileName => $extensionName) {
52+
$configFile = __DIR__.'/../Resources/config/prepend/'.$fileName;
53+
$config = Yaml::parse(file_get_contents($configFile));
54+
$container->prependExtensionConfig($extensionName, $config);
55+
$container->addResource(new FileResource($configFile));
56+
}
57+
}
1958
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace AlmaviaCX\Bundle\IbexaImportExportBundle\DependencyInjection\Security\Provider;
6+
7+
use Ibexa\Bundle\Core\DependencyInjection\Security\PolicyProvider\YamlPolicyProvider;
8+
9+
class PolicyProvider extends YamlPolicyProvider
10+
{
11+
public function getFiles(): array
12+
{
13+
return [
14+
__DIR__.'/../../../Resources/config/policies.yaml',
15+
];
16+
}
17+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
services:
2+
importexport.content.field.value.transformer.ezstring:
3+
class: AlmaviaCX\Bundle\IbexaImportExport\Ibexa\Content\Field\ValueTransformer\GenericFieldValueTransformer
4+
arguments:
5+
$propertyName: 'value.text'
6+
tags:
7+
- { name: 'importexport.content.field.value.transformer', type: 'ezstring' }
8+
9+
importexport.content.field.value.transformer.ezrichtext:
10+
class: AlmaviaCX\Bundle\IbexaImportExport\Ibexa\Content\Field\ValueTransformer\RichtextFieldValueTransformer
11+
arguments:
12+
$richTextOutputConverter: '@ibexa.richtext.converter.output.xhtml5'
13+
tags:
14+
- { name: 'importexport.content.field.value.transformer', type: 'ezrichtext' }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
parameters:
2+
# ibexa.orm.entity_mappings:

components/ImportExportBundle/src/bundle/Resources/config/forms.yaml

Whitespace-only changes.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
services:
2+
AlmaviaCX\Bundle\IbexaImportExport\Job\JobRepository:
3+
arguments:
4+
$entityManager: '@ibexa.doctrine.orm.entity_manager'
5+
6+
AlmaviaCX\Bundle\IbexaImportExport\Job\JobService:
7+
arguments:
8+
$jobRepository: '@AlmaviaCX\Bundle\IbexaImportExport\Job\JobRepository'
9+
$jobRunner: '@AlmaviaCX\Bundle\IbexaImportExport\Job\JobRunner'
10+
11+
AlmaviaCX\Bundle\IbexaImportExport\Job\JobRunner:
12+
arguments:
13+
$workflowExecutor: '@AlmaviaCX\Bundle\IbexaImportExport\Workflow\WorkflowExecutor'
14+
$workflowRegistry: '@AlmaviaCX\Bundle\IbexaImportExport\Workflow\WorkflowRegistry'
15+
$eventDispatcher: '@Symfony\Contracts\EventDispatcher\EventDispatcherInterface'
16+
17+
AlmaviaCX\Bundle\IbexaImportExport\Job\Form\Type\JobCreateType:
18+
arguments:
19+
$workflowRegistry: '@AlmaviaCX\Bundle\IbexaImportExport\Workflow\WorkflowRegistry'
20+
tags:
21+
- { name: form.type, alias: AlmaviaCX\Bundle\IbexaImportExport\Job\Form\Type\JobCreateType }
22+
23+
AlmaviaCX\Bundle\IbexaImportExport\Job\Form\JobCreateFlow:
24+
parent: craue.form.flow
25+

0 commit comments

Comments
 (0)