Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ Install the package with:
composer require netgen/ibexa-import-export
```

### Register the routes

The bundle ships with its own routing file but does not auto-import it. Add it
to your application's routing configuration (typically `config/routes.yaml` or
an Ibexa Admin UI routes file):

```yaml
ibexa.import_export:
resource: '@NetgenIbexaImportExportBundle/Resources/config/routing.yaml'
```

After clearing the cache the module routes become available and the
**Import/Export** menu item appears under **Admin**.

Licensed under [GPLv2](LICENSE)

Import/Export module
Expand Down
96 changes: 54 additions & 42 deletions bundle/Controller/Ajax/Preview.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Yaml;

use function array_key_exists;
Expand Down Expand Up @@ -42,62 +43,57 @@ public function __invoke(Request $request): Response
{
$this->denyAccessUnlessGranted('ibexa:import_export:access');

/** @var \Symfony\Component\HttpFoundation\File\UploadedFile $file */
/** @var \Symfony\Component\HttpFoundation\File\UploadedFile|null $file */
$file = $request->files->get('file');
$originalFilename = $file->getClientOriginalName();
$errors = [];
$skippedContent = [];
$skippedContentFields = [];

$fileExtension = pathinfo($originalFilename, PATHINFO_EXTENSION);
if ($file === null) {
return new Response(
$this->render('@NetgenIbexaImportExport/preview.html.twig', [
'import_structure' => null,
'import_mode' => null,
'errors' => ['No file uploaded.'],
'skipped_content' => $skippedContent,
'skipped_content_fields' => $skippedContentFields,
])->getContent(),
Response::HTTP_BAD_REQUEST,
);
}

$originalFilename = $file->getClientOriginalName();
$fileExtension = pathinfo($originalFilename, PATHINFO_EXTENSION);
$isYaml = in_array(mb_strtolower($fileExtension), ['yml', 'yaml'], true);

if ($isYaml === false) {
$errors[] = 'Uploaded file is not a valid yaml file!';
} else {
$yamlParsed = Yaml::parseFile($file->getRealPath());

if (count($yamlParsed) > 1) {
$importStructure = 'Subtree';
} else {
$importStructure = 'Singular content';
}
$importMode = $yamlParsed[0]['mode'];

if ($importMode === 'create' && $importStructure === 'Subtree') {
$rootRemoteId = $yamlParsed[0]['remote_id'] ?? null;
$rootName = $yamlParsed[0]['exported_content_name'] ?? null;

if (is_string($rootRemoteId) && $rootRemoteId !== '') {
try {
$this->repository->sudo(
fn () => $this->contentService->loadContentByRemoteId($rootRemoteId),
);

$errors[] = sprintf(
'Subtree import cannot be executed because the root content %s(remote id: %s) already exists.',
$rootName,
$rootRemoteId,
);
} catch (NotFoundException) {
// Do nothing
}
}
try {
$yamlParsed = Yaml::parseFile($file->getRealPath());
} catch (ParseException) {
$yamlParsed = null;
}

if (count($errors) > 0) {
if (!is_array($yamlParsed) || $yamlParsed === [] || !isset($yamlParsed[0]['mode'])) {
$response = $this->render('@NetgenIbexaImportExport/preview.html.twig', [
'import_structure' => $importStructure,
'import_mode' => $importMode,
'errors' => $errors,
'import_structure' => null,
'import_mode' => null,
'errors' => ['The uploaded file is not a valid migration YAML.'],
'skipped_content' => $skippedContent,
'skipped_content_fields' => $skippedContentFields,
]);

return new Response($response->getContent(), Response::HTTP_BAD_REQUEST);
}

if (count($yamlParsed) > 1) {
$importStructure = 'Subtree';
} else {
$importStructure = 'Singular content';
}
$importMode = $yamlParsed[0]['mode'];

foreach ($yamlParsed as $content) {
$contentRemoteId = $importMode === 'update' ? $content['match']['content_remote_id'] : $content['remote_id'];

Expand Down Expand Up @@ -152,6 +148,7 @@ public function __invoke(Request $request): Response
|| $importMode === 'update' && !array_key_exists($contentRemoteId, $skippedContent)
) {
$attributes = $content['attributes'];
$isMultiLanguage = !array_key_exists('lang', $content);
foreach ($attributes as $field => $value) {
$fieldTypeIdentifier = $contentType->getFieldDefinition($field)->fieldTypeIdentifier;

Expand All @@ -165,14 +162,29 @@ public function __invoke(Request $request): Response
continue;
}

$skipsField = $fieldHandler->skipsField($value);
if (is_string($skipsField)) {
$skippedContentFields[$contentRemoteId]['fields'][$fieldTypeIdentifier . '-' . $field][] = $skipsField;
$skippedContentFields[$contentRemoteId]['name'] = $content['exported_content_name'];
} elseif (is_array($skipsField) && count($skipsField) > 0) {
foreach ($skipsField as $skippedField) {
$skippedContentFields[$contentRemoteId]['fields'][$fieldTypeIdentifier . '-' . $field][] = $skippedField;
if ($isMultiLanguage && is_array($value)) {
foreach ($value as $langCode => $langValue) {
$skipsField = $fieldHandler->skipsField($langValue);
if (is_string($skipsField)) {
$skippedContentFields[$contentRemoteId]['fields'][$fieldTypeIdentifier . '-' . $field][] = $skipsField . ' (' . $langCode . ')';
$skippedContentFields[$contentRemoteId]['name'] = $content['exported_content_name'];
} elseif (is_array($skipsField) && count($skipsField) > 0) {
foreach ($skipsField as $skippedField) {
$skippedContentFields[$contentRemoteId]['fields'][$fieldTypeIdentifier . '-' . $field][] = $skippedField . ' (' . $langCode . ')';
$skippedContentFields[$contentRemoteId]['name'] = $content['exported_content_name'];
}
}
}
} else {
$skipsField = $fieldHandler->skipsField($value);
if (is_string($skipsField)) {
$skippedContentFields[$contentRemoteId]['fields'][$fieldTypeIdentifier . '-' . $field][] = $skipsField;
$skippedContentFields[$contentRemoteId]['name'] = $content['exported_content_name'];
} elseif (is_array($skipsField) && count($skipsField) > 0) {
foreach ($skipsField as $skippedField) {
$skippedContentFields[$contentRemoteId]['fields'][$fieldTypeIdentifier . '-' . $field][] = $skippedField;
$skippedContentFields[$contentRemoteId]['name'] = $content['exported_content_name'];
}
}
}
}
Expand Down
Loading
Loading