Skip to content

Commit 0bffe45

Browse files
committed
[Feature] Test PageImporter and adapt way of saving
1 parent c96f95c commit 0bffe45

File tree

5 files changed

+192
-14
lines changed

5 files changed

+192
-14
lines changed

README.md

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,33 @@
22

33
## Installation
44

5-
1. **Require the bundle**
6-
7-
```shell
8-
composer require teamneusta/pimcore-import-export-bundle
9-
```
5+
1. **Require the bundle**
6+
7+
```shell
8+
composer require teamneusta/pimcore-import-export-bundle
9+
```
1010

1111
2. **Enable the bundle**
12-
13-
Add the Bundle to your `config/bundles.php`:
14-
12+
13+
Add the Bundle to your `config/bundles.php`:
14+
1515
```php
1616
Neusta\Pimcore\ImportExportBundle\NeustaPimcoreImportExportBundle::class => ['all' => true],
1717
```
1818

1919
## Usage
2020

21-
After enabling the bundle you should see a new menu item in the context menu of Pimcore Admin Backend - Section Documents:
21+
After enabling the bundle you should see a new menu item in the context menu of Pimcore Admin Backend - Section
22+
Documents:
2223

2324
![context_menu_import_export.png](docs/images/context_menu_import_export.png)
2425

2526
(german translation)
2627

2728
### Page Export
29+
2830
The selected page will be exported into YAML format:
31+
2932
```yaml
3033
page:
3134
id: 123
@@ -43,7 +46,7 @@ page:
4346
main:
4447
type: areablock
4548
name: main
46-
data: [{ key: '1', type: text-editor, hidden: false }]
49+
data: [ { key: '1', type: text-editor, hidden: false } ]
4750
...
4851
```
4952

@@ -53,7 +56,23 @@ In the same way you can re-import your yaml file again by selecting: `Import fro
5356

5457
### Page Import
5558

56-
The import process will create a new page with the given data.
59+
The import process will create pages with the given data.
60+
61+
The following rule applies:
62+
63+
If the parseYaml method of the `PageImporter` is not called with `forcedSave`, the data from the provided YAML will be
64+
adopted, regardless of whether it makes sense or not, and without checking whether the page could be saved that way.
65+
66+
If `forcedSave` is set to `true`, the ID will be retained (Caution – this can overwrite an existing page).
67+
If a `parentId` is specified, the corresponding document will be searched for.
68+
If it exists, it will be set as the parent (Note: This may override the `path` specification).
69+
If the `parentId` does not exist, an attempt will be made to find a parent using the `path` specification.
70+
If such a parent exists, the `parentId` will be set accordingly and saved.
71+
72+
If neither is found, an InvalidArgumentException will be thrown, and the save operation will be aborted.
73+
74+
If multiple pages are imported and a path specification changes py the applied rules, this path specification will be
75+
replaced with the new, correct path specification in all provided page configurations.
5776

5877
## Contribution
5978

src/Documents/Export/PageExporter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public function exportToYaml(iterable $pages): string
7373
'yaml',
7474
[
7575
'yaml_inline' => 4,
76-
'yaml_indent' => 2,
76+
'yaml_indent' => 0,
7777
'yaml_flags' => self::YAML_DUMP_FLAGS,
7878
]
7979
);

src/Documents/Import/PageImportPopulator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ public function populate(object $target, object $source, ?object $ctx = null): v
2222
if (property_exists($source, 'language') && isset($source->language)) {
2323
$target->setProperty('language', 'text', $source->language);
2424
}
25-
$target->setProperty('navigation_title', 'text', $source->title);
26-
$target->setProperty('navigation_name', 'text', $source->key);
25+
$target->setProperty('navigation_title', 'text', $source->navigation_title);
26+
$target->setProperty('navigation_name', 'text', $source->navigation_name);
2727
/** @var array<string, mixed> $editable */
2828
foreach ($source->editables ?? [] as $key => $editable) {
2929
$target->setRawEditable($key, $editable['type'], $editable['data']);

src/Documents/Import/PageImporter.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Neusta\ConverterBundle\Converter\Context\GenericContext;
77
use Neusta\ConverterBundle\Exception\ConverterException;
88
use Neusta\Pimcore\ImportExportBundle\Documents\Export\YamlExportPage;
9+
use Pimcore\Model\Document;
910
use Pimcore\Model\Document\Page;
1011
use Pimcore\Model\Element\DuplicateFullPathException;
1112
use Symfony\Component\Yaml\Yaml;
@@ -41,6 +42,7 @@ public function parseYaml(string $yamlInput, bool $forcedSave = true): array
4142
if (\is_array($configPage[YamlExportPage::PAGE])) {
4243
$page = $this->yamlToPageConverter->convert(new YamlExportPage($configPage[YamlExportPage::PAGE]));
4344
if ($forcedSave) {
45+
$this->checkAndUpdatePage($page, $config[YamlExportPage::PAGES]);
4446
$page->save();
4547
}
4648
}
@@ -67,4 +69,26 @@ public function readYamlFileAndSetParameters(string $filename, array $params = [
6769

6870
return '';
6971
}
72+
73+
/**
74+
* @param array<string, array<string, mixed>> $configPages
75+
*/
76+
private function checkAndUpdatePage(Page $page, array &$configPages): void
77+
{
78+
$oldPath = $page->getPath();
79+
$existingParent = Document::getById($page->getParentId() ?? -1);
80+
if (!$existingParent) {
81+
$existingParent = Document::getByPath($page->getPath() ?? '');
82+
if (!$existingParent) {
83+
throw new \InvalidArgumentException('Neither parentId nor path leads to a valid parent element');
84+
}
85+
$page->setParentId($existingParent->getId());
86+
$newPath = $existingParent->getPath() . $page->getKey() . '/';
87+
foreach ($configPages as $configPage) {
88+
if (\array_key_exists('path', $configPage[YamlExportPage::PAGE]) && \is_string($oldPath)) {
89+
str_replace($oldPath, $newPath, $configPage[YamlExportPage::PAGE]['path']);
90+
}
91+
}
92+
}
93+
}
7094
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Neusta\Pimcore\ImportExportBundle\Tests\Integration\Documents\Export;
4+
5+
use Neusta\Pimcore\ImportExportBundle\Documents\Import\PageImporter;
6+
use Neusta\Pimcore\TestingFramework\Database\ResetDatabase;
7+
use Pimcore\Test\KernelTestCase;
8+
use Spatie\Snapshots\MatchesSnapshots;
9+
10+
class PageImporterTest extends KernelTestCase
11+
{
12+
use MatchesSnapshots;
13+
use ResetDatabase;
14+
15+
private PageImporter $importer;
16+
17+
protected function setUp(): void
18+
{
19+
$this->importer = self::getContainer()->get(PageImporter::class);
20+
}
21+
22+
public function testSinglePageImport_exceptional_case(): void
23+
{
24+
$yaml =
25+
<<<YAML
26+
pages:
27+
-
28+
page:
29+
id: 999
30+
path: /path-does-not-exist/
31+
key: test_document_1
32+
YAML;
33+
34+
$this->expectException(\InvalidArgumentException::class);
35+
$this->expectExceptionMessage('Neither parentId nor path leads to a valid parent element');
36+
$this->importer->parseYaml($yaml);
37+
}
38+
39+
public function testSinglePageExport_regular_case_parent_id(): void
40+
{
41+
$yaml =
42+
<<<YAML
43+
pages:
44+
-
45+
page:
46+
id: 999
47+
parentId: 1
48+
type: email
49+
published: false
50+
path: /path/will/be/overwritten/by/parent_id/
51+
language: fr
52+
navigation_name: 'Mein Dokument'
53+
navigation_title: 'Mein Dokument - Titel'
54+
key: test_document_1
55+
title: 'Titel meines Dokuments'
56+
controller: Irgend/ein/Controller
57+
YAML;
58+
59+
$pages = $this->importer->parseYaml($yaml);
60+
self::assertEquals(999, $pages[0]->getId());
61+
self::assertEquals('/', $pages[0]->getPath());
62+
63+
self::assertEquals('test_document_1', $pages[0]->getKey());
64+
self::assertEquals('Titel meines Dokuments', $pages[0]->getTitle());
65+
self::assertEquals('email', $pages[0]->getType());
66+
self::assertEquals('Irgend/ein/Controller', $pages[0]->getController());
67+
self::assertEquals('fr', $pages[0]->getProperty('language'));
68+
self::assertEquals('Mein Dokument', $pages[0]->getProperty('navigation_name'));
69+
self::assertEquals('Mein Dokument - Titel', $pages[0]->getProperty('navigation_title'));
70+
}
71+
72+
public function testSinglePageExport_regular_case_path(): void
73+
{
74+
$yaml =
75+
<<<YAML
76+
pages:
77+
-
78+
page:
79+
id: 999
80+
parentId: 99999
81+
type: email
82+
published: false
83+
path: /
84+
language: fr
85+
navigation_name: 'Mein Dokument'
86+
navigation_title: 'Mein Dokument - Titel'
87+
key: test_document_1
88+
title: 'Titel meines Dokuments'
89+
controller: Irgend/ein/Controller
90+
YAML;
91+
92+
$pages = $this->importer->parseYaml($yaml);
93+
self::assertEquals(999, $pages[0]->getId());
94+
self::assertEquals('/', $pages[0]->getPath());
95+
self::assertEquals(1, $pages[0]->getParentId());
96+
97+
self::assertEquals('test_document_1', $pages[0]->getKey());
98+
self::assertEquals('Titel meines Dokuments', $pages[0]->getTitle());
99+
self::assertEquals('email', $pages[0]->getType());
100+
self::assertEquals('Irgend/ein/Controller', $pages[0]->getController());
101+
self::assertEquals('fr', $pages[0]->getProperty('language'));
102+
self::assertEquals('Mein Dokument', $pages[0]->getProperty('navigation_name'));
103+
self::assertEquals('Mein Dokument - Titel', $pages[0]->getProperty('navigation_title'));
104+
}
105+
106+
public function testSinglePageImport_tree_case(): void
107+
{
108+
$yaml =
109+
<<<YAML
110+
pages:
111+
-
112+
page:
113+
parentId: 1
114+
id: 999
115+
path: /my_path/
116+
key: test_document_1
117+
-
118+
page:
119+
parentId: 999
120+
id: 1000
121+
path: /my_path/test_document_1/
122+
key: test_document_1_1
123+
-
124+
page:
125+
parentId: 1000
126+
id: 1001
127+
path: /my_path/test_document_1/test_document_1_1/
128+
key: test_document_1_1_1
129+
YAML;
130+
131+
$pages = $this->importer->parseYaml($yaml);
132+
133+
self::assertEquals('/test_document_1/test_document_1_1/', $pages[2]->getPath());
134+
}
135+
}

0 commit comments

Comments
 (0)