Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
12852a9
[Feature] enable exporting and importing several pages by ONE yaml file
mike4git Feb 28, 2025
3647382
[Fix] use ['page'] instead of config
mike4git Feb 28, 2025
ac6271e
[Feature] Add integration tests for PageExporter
mike4git Mar 1, 2025
d1754f9
[Feature] Moved import menu to main menu toolbar
mike4git Mar 1, 2025
f0f8f47
[Feature] Test PageImporter and adapt way of saving
mike4git Mar 2, 2025
884f2f1
[Export All] new command for export all pages
mike4git Mar 14, 2025
69e2ff6
[Chore] fix general code styles
lukadschaak Mar 14, 2025
f2f05d1
[Chore] readme: edit how tests must be executed
lukadschaak Mar 14, 2025
1654f74
[Export All][Refactoring] remove duplicated code
mike4git Mar 15, 2025
eaba65f
Update src/Controller/Admin/PageImportController.php
mike4git Mar 15, 2025
248bacb
Update tests/Integration/Documents/Export/PageExporterTest.php
mike4git Mar 15, 2025
8953203
Update tests/Integration/Documents/Export/PageImporterTest.php
mike4git Mar 15, 2025
a4a3de0
Update tests/Integration/Documents/Export/PageImporterTest.php
mike4git Mar 15, 2025
65eabf9
Update translations/admin.de.yaml
mike4git Mar 15, 2025
c9a4b4e
Update translations/admin.en.yaml
mike4git Mar 15, 2025
725fbb9
Update tests/Integration/Documents/Export/PageImporterTest.php
mike4git Mar 15, 2025
8d987ab
Update tests/Integration/Documents/Export/PageImporterTest.php
mike4git Mar 15, 2025
9343665
[Export All][Tests] add expected yaml files
mike4git Mar 15, 2025
158f981
[Export All][Tests] fix it
mike4git Mar 15, 2025
3514a1f
[Export All][Refactoring] (#12)
mike4git Mar 19, 2025
7b6a683
[Export All][Refactoring][New Commands] add test results
mike4git Mar 19, 2025
af03dc1
Update tests/Integration/Documents/Export/PageExporterTest.php
mike4git Mar 19, 2025
c4704c2
[Export All][Refactoring][New Commands] adapt naming import to export
mike4git Mar 19, 2025
fa97083
[Export All][Refactoring][New Commands] fix test
mike4git Mar 19, 2025
c0c6bb2
Update src/Controller/Admin/PageImportController.php
mike4git Mar 19, 2025
a77952e
Update src/Command/ExportPagesCommand.php
mike4git Mar 19, 2025
8844cd1
Update src/Command/ImportPagesCommand.php
mike4git Mar 19, 2025
57e9853
Update src/Command/ImportPagesCommand.php
mike4git Mar 19, 2025
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
183 changes: 172 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,137 @@
## Installation

1. **Require the bundle**

```shell
composer require teamneusta/pimcore-import-export-bundle
```

2. **Enable the bundle**
2. **Enable the bundle**

Add the Bundle to your `config/bundles.php`:

```php
Neusta\Pimcore\ImportExportBundle\NeustaPimcoreImportExportBundle::class => ['all' => true],
```
```php
Neusta\Pimcore\ImportExportBundle\NeustaPimcoreImportExportBundle::class => ['all' => true],
```

## Usage

### Pimcore Admin Backend

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

![context_menu_import_export.png](docs/images/context_menu_import_export.png)
![context_menu_export.png](docs/images/context_menu_export.png)

After that you will be asked for a file name and the export will start:
![filename_dialog.png](docs/images/filename_dialog.png)

(german translation)

For the import you can use the main menu button:

![import_menu.png](docs/images/import_menu.png)

### Symfony Commands

There are two commands: one for exporting all pages, starting from the root document with ID 1, and one for importing pages from a given YAML file.

#### Export Command

##### Command Name
`neusta:pimcore:export:pages:all`

##### Description
Exports all pages into a single YAML file. Optionally, you can specify a comma-separated list of page IDs to export specific pages and their children.

##### Options

- `--output` or `-o` (optional): Specifies the name of the output file. Default is `export_all_pages.yaml`.
- `--ids` (optional): A comma-separated list of page IDs to export. If not provided, the command exports the root page and its children.

##### Usage

1. **Export all pages to the default file:**

```sh
php bin/console neusta:pimcore:export:pages:all
```

2. **Export all pages to a specified file:**

```sh
php bin/console neusta:pimcore:export:pages:all --output=custom_output.yaml
```

3. **Export specific pages and their children:**

```sh
php bin/console neusta:pimcore:export:pages:all --ids=2,3,4
```

4. **Export specific pages and their children to a specified file:**

```sh
php bin/console neusta:pimcore:export:pages:all --ids=2,3,4 --output=custom_output.yaml
```

##### Example

To export pages with IDs 2, 3, and 4 and their children to a file named `selected_pages.yaml`:

```sh
php bin/console neusta:pimcore:export:pages:all --ids=2,3,4 --output=selected_pages.yaml
```

This command will generate a YAML file named `selected_pages.yaml` containing the specified pages and their children. If any of the specified page IDs are not found, an error message will be displayed.
#### Import Command

##### Command Name
`neusta:pimcore:import:pages`

##### Description
Imports pages from a given YAML file. Optionally, you can perform a dry run to see how many pages would be successfully imported without actually saving them.

##### Options

- `--input` or `-i` (required): Specifies the name of the input YAML file.
- `--dry-run` (optional): Perform a dry run without saving the imported pages.

##### Usage

1. **Import pages from a specified file:**

```sh
php bin/console neusta:pimcore:import:pages --input=your_input_file.yaml
```

2. **Perform a dry run to see how many pages would be imported:**

```sh
php bin/console neusta:pimcore:import:pages --input=your_input_file.yaml --dry-run
```

##### Example

To import pages from a file named `pages_to_import.yaml`:

```sh
php bin/console neusta:pimcore:import:pages --input=pages_to_import.yaml
```

To perform a dry run for the same file:

```sh
php bin/console neusta:pimcore:import:pages --input=pages_to_import.yaml --dry-run
```

This command will read the specified YAML file and import the pages. If the `--dry-run` option is used, the pages will not be saved, and you will see how many pages would be successfully imported.

## Concepts

### Page Export

The selected page will be exported into YAML format:

```yaml
page:
id: 123
Expand All @@ -43,17 +151,65 @@ page:
main:
type: areablock
name: main
data: [{ key: '1', type: text-editor, hidden: false }]
data: [ { key: '1', type: text-editor, hidden: false } ]
...
```

In the same way you can re-import your yaml file again by selecting: `Import from YAML` in the context menu.

## Configuration

### Page Import

The import process will create a new page with the given data.
The import process will create pages with the given data.

The following rule applies:

If the parseYaml method of the `PageImporter` is not called with `forcedSave`, the data from the provided YAML will be
adopted, regardless of whether it makes sense or not, and without checking whether the page could be saved that way.

If `forcedSave` is set to `true`, the ID will be retained (Caution – this can overwrite an existing page).
If a `parentId` is specified, the corresponding document will be searched for.
If it exists, it will be set as the parent (Note: This may override the `path` specification).
If the `parentId` does not exist, an attempt will be made to find a parent using the `path` specification.
If such a parent exists, the `parentId` will be set accordingly and saved.

If neither is found, an InvalidArgumentException will be thrown, and the save operation will be aborted.

If multiple pages are imported and a path specification changes py the applied rules, this path specification will be
replaced with the new, correct path specification in all provided page configurations.

### Parameterize your yaml files

You can parameterize your yaml files with placeholders. The placeholders will be replaced by the values you provide in your fixtures.

```yaml
pages:
- page:
id: 2
parentId: 1
# ...further properties
editables:
# ...several editables
'main:1.img:1.image':
type: image
data:
id: %IMAGE_ID%
'main:1.img:1.title':
# ...
```

In the case above an image has been assigned to an `Editable/Image` editable. The image id is a placeholder `%IMAGE_ID%`.

You can use now a `Neusta\Pimcore\ImportExportBundle\Documents\Import\Filter\SearchAndReplaceFilter` instance to replace the placeholder with the actual image id (e.g. 1234).

```php
$yamlContent = (new SearchAndReplaceFilter(['%IMAGE_ID%' => 1234]))->filterAndReplace($yamlContent);
```

If you want to change your yaml in a more complex way you can use the `Neusta\Pimcore\ImportExportBundle\Documents\Import\Filter\YamlFilter` interface to implement your own filter.

With that technique you can export test pages for Fixtures, change values into placeholders (e.g. for assets and data objects) and replace them with the actual values in your tests.

```php

## Contribution

Expand All @@ -74,5 +230,10 @@ We use composer scripts for our main quality tools. They can be executed via the
```shell
bin/composer cs:fix
bin/composer phpstan
bin/composer tests
```

For the tests there is a different script, that includes a database setup.

```shell
bin/run-tests
```
2 changes: 1 addition & 1 deletion compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ services:
timeout: 10s

php:
image: pimcore/pimcore:php8.3-latest
image: pimcore/pimcore:php8.3-debug-latest
volumes:
- ./:/var/www/html/
environment:
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"phpstan/phpstan-symfony": "^1.3.8",
"phpunit/phpunit": "^9.5",
"pimcore/admin-ui-classic-bundle": "^1.6",
"spatie/phpunit-snapshot-assertions": "^4.2",
"teamneusta/pimcore-testing-framework": "^0.12"
},
"autoload": {
Expand Down
59 changes: 59 additions & 0 deletions config/converters_populators.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
services:
_defaults:
autowire: true
autoconfigure: true

###########################################################
# Import Populator (YamlPage -> Page)
###########################################################
Neusta\Pimcore\ImportExportBundle\Documents\Import\Populator\PageImportPopulator: ~

###########################################################
# Export Converter (Document -> YamlPage)
###########################################################
neusta_pimcore_import_export.export_document:
class: Neusta\Pimcore\ImportExportBundle\Documents\Export\Converter\DocumentTypeStrategyConverter
arguments:
$typeToConverterMap:
Pimcore\Model\Document\Page: '@neusta_pimcore_import_export.export_page'
Pimcore\Model\Document\Snippet: '@neusta_pimcore_import_export.export_page_snippet'
Pimcore\Model\Document\Folder: '@neusta_pimcore_import_export.export_folder'


###########################################################
# Export Populator (Page -> YamlPage)
###########################################################
neusta_pimcore_import_export.page.editables.populator:
class: Neusta\ConverterBundle\Populator\ArrayConvertingPopulator
arguments:
$converter: '@neusta_pimcore_import_export.editable_converter'
$sourceArrayPropertyName: 'editables'
$targetPropertyName: 'editables'

neusta_pimcore_import_export.page.property.language.populator:
class: Neusta\Pimcore\ImportExportBundle\PimcoreConverter\Populator\PropertyBasedMappingPopulator
arguments:
$propertyKey: 'language'
$targetProperty: 'language'
$skipNull: true

neusta_pimcore_import_export.page.property.navigation_title.populator:
class: Neusta\Pimcore\ImportExportBundle\PimcoreConverter\Populator\PropertyBasedMappingPopulator
arguments:
$propertyKey: 'navigation_title'
$targetProperty: 'navigation_title'
$skipNull: true

neusta_pimcore_import_export.page.property.navigation_name.populator:
class: Neusta\Pimcore\ImportExportBundle\PimcoreConverter\Populator\PropertyBasedMappingPopulator
arguments:
$propertyKey: 'navigation_name'
$targetProperty: 'navigation_name'
$skipNull: true

###########################################################
# Export Populator (Editable -> YamlEditable)
###########################################################
neusta_pimcore_import_export.editable.data.populator:
class: Neusta\Pimcore\ImportExportBundle\Documents\Export\Populator\EditableDataPopulator

52 changes: 45 additions & 7 deletions config/pimcore/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
neusta_converter:
converter:
###########################################################
# Import Converter (YamlExportPage -> Page)
# Import Converter (Page -> PimcorePage)
###########################################################
neusta_pimcore_import_export.import_page:
neusta_pimcore_import_export.import_document:
target: Pimcore\Model\Document\Page
populators:
- Neusta\Pimcore\ImportExportBundle\Documents\Import\PageImportPopulator
- Neusta\Pimcore\ImportExportBundle\Documents\Import\Populator\PageImportPopulator
properties:
id:
source: id
Expand All @@ -31,15 +31,33 @@ neusta_converter:
path:
source: path
default: '/'
skip_null: true
parentId:
source: parentId
default: 0

###########################################################
# Export Converter (Page -> YamlExportPage)
# Export Converter (Document/Folder -> Page)
###########################################################
neusta_pimcore_import_export.export_folder:
target: Neusta\Pimcore\ImportExportBundle\Documents\Model\Page
populators:
- neusta_pimcore_import_export.page.property.language.populator
- neusta_pimcore_import_export.page.property.navigation_title.populator
- neusta_pimcore_import_export.page.property.navigation_name.populator
properties:
id: ~
key: ~
type: ~
published: ~
path: ~
parentId: ~

###########################################################
# Export Converter (Pimcore Page -> Page)
###########################################################
neusta_pimcore_import_export.export_page:
target: Neusta\Pimcore\ImportExportBundle\Documents\Export\YamlExportPage
target: Neusta\Pimcore\ImportExportBundle\Documents\Model\Page
populators:
- neusta_pimcore_import_export.page.property.language.populator
- neusta_pimcore_import_export.page.property.navigation_title.populator
Expand All @@ -55,9 +73,29 @@ neusta_converter:
path: ~
parentId: ~

###########################################################
# Export Converter (Page Snippet -> Page)
###########################################################
neusta_pimcore_import_export.export_page_snippet:
target: Neusta\Pimcore\ImportExportBundle\Documents\Model\Page
populators:
- neusta_pimcore_import_export.page.property.language.populator
- neusta_pimcore_import_export.page.property.navigation_title.populator
- neusta_pimcore_import_export.page.property.navigation_name.populator
- neusta_pimcore_import_export.page.editables.populator
properties:
id: ~
key: ~
controller: ~
type: ~
published: ~
path: ~
parentId: ~

neusta_pimcore_import_export.editable_converter:
target: Neusta\Pimcore\ImportExportBundle\Documents\Export\YamlExportEditable
target: Neusta\Pimcore\ImportExportBundle\Documents\Model\Editable
populators:
- neusta_pimcore_import_export.editable.data.populator
properties:
type: ~
name: ~
data: ~
Loading
Loading