Skip to content
Draft
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
6 changes: 6 additions & 0 deletions code_samples/data_migration/examples/create_blog_post_ct.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
metadata:
identifier: blog_post
mainTranslation: eng-GB
nameSchema: '<title>'
urlAliasSchema: '<title>'
container: true
defaultAlwaysAvailable: true
defaultSortField: 2 # Location::SORT_FIELD_PUBLISHED
defaultSortOrder: 0 # Location::SORT_ORDER_DESC
contentTypeGroups:
- Content
translations:
Expand Down
24 changes: 24 additions & 0 deletions code_samples/data_migration/examples/create_content_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-
type: content
mode: create
metadata:
contentType: folder
mainTranslation: eng-GB
creatorId: 14
modificationDate: '2025-06-01T10:00:00+00:00'
publicationDate: '2025-06-01T10:00:00+00:00'
remoteId: options_folder
alwaysAvailable: true
section:
identifier: standard
location:
parentLocationId: 2
locationRemoteId: options_folder_location
hidden: false
priority: 10
sortField: 9 # Location::SORT_FIELD_NAME
sortOrder: ASC
fields:
- fieldDefIdentifier: name
languageCode: eng-GB
value: 'Folder with all options'
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-
type: product_availability
mode: create
product_code: ergo_desk
is_available: true
is_infinite: false
stock: 100
8 changes: 8 additions & 0 deletions code_samples/data_migration/examples/service_call_step.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-
type: service_call
mode: execute
service: App\Migration\ContentImporter
method: import
arguments:
- content.csv
- 42
16 changes: 16 additions & 0 deletions code_samples/data_migration/examples/update_content.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-
type: content
mode: update
match:
field: content_remote_id
value: options_folder
metadata:
mainLanguageCode: eng-GB
name: 'Updated folder'
ownerId: 14
alwaysAvailable: false
modificationDate: '2025-06-15T10:00:00+00:00'
fields:
- fieldDefIdentifier: name
languageCode: eng-GB
value: 'Updated folder'
7 changes: 7 additions & 0 deletions code_samples/data_migration/examples/update_language.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-
type: language
mode: update
languageCode: fre-FR
metadata:
name: French
enabled: true
2 changes: 2 additions & 0 deletions code_samples/data_migration/examples/update_user.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@
field: login
value: admin
metadata:
email: admin@example.com
enabled: true
password: '###XXX env("ADMIN_PASSWORD") XXX###'
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ When executed, this migration:

The following migration actions are available out of the box:

- `assign_dashboard_to_user` (Content Create)
- `assign_object_state` (Content Create)
- `assign_parent_location` (Content Create / Update)
- `assign_section` (Content Update)
Expand Down Expand Up @@ -91,6 +92,13 @@ mode: Update
- { action: assign_section, identifier: 'media' }
```

When creating a [dashboard](customize_dashboard.md) content item, you can assign it to a specific user, identified by their login:

``` yaml
actions:
- { action: assign_dashboard_to_user, value: admin }
```

### Content types

mode: Create
Expand Down
75 changes: 68 additions & 7 deletions docs/content_management/data_migration/importing_data.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,15 @@
| `action_configuration` | &#10004; | &#10004; | &#10004; | | |
| `attribute` | &#10004; | &#10004; | &#10004; | | |
| `attribute_group` | &#10004; | &#10004; | &#10004; | | |
| `company` | &#10004; | | | | |
| `content_type` | &#10004; | &#10004; | &#10004; | | |
| `content_type_group` | &#10004; | &#10004; | &#10004; | | |
| `content` | &#10004; | &#10004; | &#10004; | | |
| `currency` | &#10004; | &#10004; | &#10004; | | |
| `customer_group` | &#10004; | &#10004; | &#10004; | | |
| `discount` | &#10004; | &#10004; | | | |
| `discount_code` | &#10004; | | | | |
| `language` | &#10004; | | | | |
| `language` | &#10004; | &#10004; | | | |
| `location` | | &#10004; | | &#10004; | &#10004; |
| `object_state` | &#10004; | | | | |
| `object_state_group` | &#10004; | | | | |
Expand All @@ -71,16 +72,21 @@
| `segment` | &#10004; | &#10004; | &#10004; | | |
| `segment_group` | &#10004; | &#10004; | &#10004; | | |
| `setting` | &#10004; | &#10004; | &#10004; | | |
| `shipping_method` | &#10004; | | | | |
| `user` | &#10004; | &#10004; | | | |
| `user_group` | &#10004; | &#10004; | &#10004; | | |

Additionally, the following special migration types are available:

| `type` | `execute` |
|------------------------|:---------:|
| `repeatable` | &#10004; |
| `sql` | &#10004; |
| `try_catch` | &#10004; |
| `type` | `mode` |
|----------------|-------------------------------|
| `reference` | `load`, `save`, `set`, `list` |
| `repeatable` | `create` |
| `service_call` | `execute` |
| `sql` | `execute` |
| `try_catch` | `execute` |

For more information about the `reference` type, see [References](managing_migrations.md#references).

### Repeatable steps

Expand Down Expand Up @@ -112,6 +118,7 @@
!!! note

Iteration counter is assigned to `i` by default, but you can modify it in the `iteration_counter_name` setting.
The counter starts at `0` by default. You can change this with the `iteration_counter_starting_value` setting.

#### Repeatable steps with items

Expand Down Expand Up @@ -209,6 +216,25 @@
The migration step is marked as successful and the migration process continues.
Non-matching exceptions throw immediately, halting the migration process and returning an error.

### Service calls

You can call a method on a service from the dependency injection container by using the `service_call` migration type.
Use it when a migration requires custom logic that isn't covered by the built-in migration types.

A `service_call` migration requires the `service` and `method` properties, and accepts an optional `arguments` list that is passed to the method:

Check notice on line 224 in docs/content_management/data_migration/importing_data.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/content_management/data_migration/importing_data.md#L224

[Ibexa.Passive] Try to avoid passive tense, when possible.
Raw output
{"message": "[Ibexa.Passive] Try to avoid passive tense, when possible.", "location": {"path": "docs/content_management/data_migration/importing_data.md", "range": {"start": {"line": 224, "column": 122}}}, "severity": "INFO"}

```yaml
[[= include_file('code_samples/data_migration/examples/service_call_step.yaml') =]]
```

You can only call services that are explicitly listed under the `ibexa_migrations.callable_services` configuration key:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I think about it, we probably should also tag those services. Or straight up use a tag to create that ServiceLocator. Probably a jira ticket is in order.


```yaml
ibexa_migrations:
callable_services:
- App\Migration\ContentImporter

Check notice on line 235 in docs/content_management/data_migration/importing_data.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/content_management/data_migration/importing_data.md#L235

[Ibexa.Lists] Verify list formatting: Full sentences should start with uppercase and end with a period. Sentence fragments should start with lowercase and have no period.
Raw output
{"message": "[Ibexa.Lists] Verify list formatting: Full sentences should start with uppercase and end with a period. Sentence fragments should start with lowercase and have no period.", "location": {"path": "docs/content_management/data_migration/importing_data.md", "range": {"start": {"line": 235, "column": 1}}}, "severity": "INFO"}
```

### Expression syntax

You can use [Symfony expression syntax]([[= symfony_doc =]]/reference/formats/expression_language.html) in data migrations, like in [repeatable steps](#repeatable-steps), where you can use it to generate varied content in migration steps.
Expand Down Expand Up @@ -300,6 +326,8 @@
The following example shows how to create a content type with two field definitions.

The required metadata keys are: `identifier`, `mainTranslation`, `contentTypeGroups` and `translations`.
The example also shows the optional metadata keys: `nameSchema`, `urlAliasSchema`, `container`, `defaultAlwaysAvailable`, `defaultSortField`, and `defaultSortOrder`.
You can additionally set `remoteId` and `creatorId`.

The default values of field definition properties mirror the underlying PHP API, for example:

Expand All @@ -323,6 +351,22 @@
[[= include_file('code_samples/data_migration/examples/create_parent_and_child_content.yaml') =]]
```

The following example shows the optional `metadata` and `location` properties that you can set when creating a content item.
Instead of `parentLocationId`, you can identify the parent location with `parentLocationRemoteId`.
`sortField` takes the numeric value of one of the `SORT_FIELD_*` constants from the [`Location` class](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Location.html), and `sortOrder` takes `ASC` or `DESC`:

``` yaml
[[= include_file('code_samples/data_migration/examples/create_content_options.yaml') =]]
```

Use the `update` mode to modify an existing content item.
You can match the content item by `content_remote_id`, `location_id`, `parent_location_id`, or `content_type_identifier`.
All `metadata` keys are optional: `initialLanguageCode`, `creatorId`, `remoteId`, `alwaysAvailable`, `mainLanguageCode`, `mainLocationId`, `modificationDate`, `publishedDate`, `name`, and `ownerId`:

``` yaml
[[= include_file('code_samples/data_migration/examples/update_content.yaml') =]]
```

Use the `delete` mode to delete content items:

``` yaml
Expand Down Expand Up @@ -412,7 +456,8 @@
[[= include_file('code_samples/data_migration/examples/create_user.yaml') =]]
```

You can also update user information, including passwords:
You can also update the user's email, enabled status, and password.
All `metadata` keys are optional:

``` yaml
[[= include_file('code_samples/data_migration/examples/update_user.yaml') =]]
Expand All @@ -428,6 +473,13 @@
[[= include_file('code_samples/data_migration/examples/create_language.yaml') =]]
```

You can also update an existing language, identified by its `languageCode`.
Both `metadata` keys are optional:

``` yaml
[[= include_file('code_samples/data_migration/examples/update_language.yaml') =]]
```

### Product catalog

#### Attributes and attribute groups
Expand Down Expand Up @@ -503,6 +555,15 @@
[[= include_file('code_samples/data_migration/examples/create_product_price.yaml') =]]
```

#### Product availability

The following example shows how to define the availability and stock of a product identified by its code.
When `is_infinite` is set to `true`, `stock` can be `null`:

``` yaml
[[= include_file('code_samples/data_migration/examples/create_product_availability.yaml') =]]
```

#### Customer groups

The following example shows how to create a customer group with a defined global price discount:
Expand Down
19 changes: 19 additions & 0 deletions docs/content_management/data_migration/managing_migrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,20 @@
filename: 'references/new_references.yaml'
```

You can also set a reference value manually with the `set` mode, and use the `list` mode to print all references collected so far to the migration log:

```yaml
-

Check notice on line 173 in docs/content_management/data_migration/managing_migrations.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/content_management/data_migration/managing_migrations.md#L173

[Ibexa.Lists] Verify list formatting: Full sentences should start with uppercase and end with a period. Sentence fragments should start with lowercase and have no period.
Raw output
{"message": "[Ibexa.Lists] Verify list formatting: Full sentences should start with uppercase and end with a period. Sentence fragments should start with lowercase and have no period.", "location": {"path": "docs/content_management/data_migration/managing_migrations.md", "range": {"start": {"line": 173, "column": 1}}}, "severity": "INFO"}
type: reference
mode: set
name: parent_location_id
value: 2

Check notice on line 178 in docs/content_management/data_migration/managing_migrations.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/content_management/data_migration/managing_migrations.md#L178

[Ibexa.Lists] Verify list formatting: Full sentences should start with uppercase and end with a period. Sentence fragments should start with lowercase and have no period.
Raw output
{"message": "[Ibexa.Lists] Verify list formatting: Full sentences should start with uppercase and end with a period. Sentence fragments should start with lowercase and have no period.", "location": {"path": "docs/content_management/data_migration/managing_migrations.md", "range": {"start": {"line": 178, "column": 1}}}, "severity": "INFO"}
-
type: reference
mode: list
```

## Available reference types

- `content`
Expand All @@ -177,7 +191,12 @@
- content_type_id
- `language`
- language_id
- language_code

Check failure on line 194 in docs/content_management/data_migration/managing_migrations.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/content_management/data_migration/managing_migrations.md#L194

[Ibexa.Spellcheck] Did you really mean 'language_code'?
Raw output
{"message": "[Ibexa.Spellcheck] Did you really mean 'language_code'?", "location": {"path": "docs/content_management/data_migration/managing_migrations.md", "range": {"start": {"line": 194, "column": 7}}}, "severity": "ERROR"}
- `role`
- role_id
- `section`
- section_id
- `user`
- user_id
- `user_group`
- user_group_id
Loading