Migrating dimension config [v9]

Neos 9.x Content

This is content for the upcoming Neos 9.0 release with the rewritten Content Repository based on Event Sourcing.

We heavily work on these docs right now, so expect rough edges.

Dimensions are configured in Settings.yaml, but are also reflected in the content repository - thus in the database.

As a consequence, if you change dimension configuration in Settings.yaml you need to run some node migrations to adjust the content repository. On this page, we explain the different cases and how to run them:

  • adding a dimension
    • e.g. site without dimensions => site with a language dimension
    • e.g. site with one dimension language => site with dimensions language, market
  • adding a dimension value
    • e.g. site with language:en dimension value => site with language:en,de dimension values
  • adding a dimension value as fallback
    • e.g. site with language:de dimension value => site with language:de,ch dimension values; where de is the fallback of ch
  • renaming dimensions / dimension values
  • removing dimensions / dimension values

#General process

Adjusting dimension configuration of a running site works in two steps:

  1. Make sure your users do not have unpublished changes
  2. adjust dimension configuration in Settings.yaml at key Neos.ContentRepositoryRegistry.contentRepositories.default.contentDimensions (or analogous for other content repositories) - described on page Content Repository Configuration.
  3. Also adjust the Site Dimension Routing configuration in Settings.yaml at key Neos.Neos.sites.*.contentDimensions.resolver - described in the Routing docs.
  4. run node migrations migrations (through CLI commands) to apply your configuration changes to the content in your content repository
  5. flush the cache and test to ensure the updated routing configuration is active.

#Adding a dimension

no dimensions
no dimensions
Dimension language
Dimension language
de
de
Dimension language
Dimension language
de
de
en
en
Dimension language
Dimension language
de
de
en
en
Dimension market
Dimension market
b2c
b2c
b2b
b2b
Text is not SVG - cannot display

Adjust dimension configuration

In Settings.yaml you need to add the market dimension configuration.

Settings.yaml
Neos:
  ContentRepositoryRegistry:
    contentRepositories:
      default:
        contentDimensions:
          'language':
            label: 'Language'
            values:
              'en':
                label: English
              'de':
                label: German
          # Newly added:
          'market':
            label: 'Market'
            value:
              'b2b':
                label: B2B
              'b2c':
                label: B2C

Also adjust the Site Dimension Routing configuration in Settings.yaml at key Neos.Neos.sites.*.contentDimensions.resolver - described in the Routing docs, to configure how the dimension should be mapped to URLs.

Running dimension migrations

When switching from no dimensions to 1 dimension; or from 1 dimension to two dimensions, you need to move all existing DimensionSpacePoints, because they need the additional "axis" defined.

Moving needs to be done for all existing DimensionSpacePoints, because a 1-dimensional DimensionSpacePoint is not reachable if you have two dimensions configured. 

Please also check the references for node migration.

Your.Package/Migration/ContentRepository/Version20240924093814.yaml
# Example: No Dimensions => 1 Dimension
# Source: no dimensions
# Target: a "language" dimension, where the already existing content should appear as "en"

comments: 'Move all nodes without dimension values to language "en"'
migration:
  -
    transformations:
      -
        type: 'MoveDimensionSpacePoint'
        settings:
          from: { }
          to: { language: 'en' }
Your.Package/Migration/ContentRepository/Version20240924093814.yaml
# Example: 1 Dimension => 2 Dimensions (additional market dimension)
# For every existing dimension value in "language",  move it to the "b2c" market.

comments: 'Move all nodes into their market dimension'
migration:
  -
    transformations:
      -
        type: 'MoveDimensionSpacePoint'
        settings:
          from: { language: 'en' }
          to: { language: 'en', market: 'b2c' }
      -
        type: 'MoveDimensionSpacePoint'
        settings:
          from: { language: 'de' }
          to: { language: 'de', market: 'b2c' }

The root node is, by definition, existing in every DimensionSpacePoint. Thus, if you change dimension configuration, the root node(s) need to be updated as well. The following migration creates empty root node aggregate dimensions for each allowed dimension combination and removes them for all non-configured ones. You can create a dedicated migration file or just append it as additonal transformation to your dimension migration.

Your.Package/Migration/ContentRepository/Version20240924095647.yaml
comments: 'Synchronize root node aggregates with content repository configuration'
migration:
  -
    transformations:
      - 
        type: 'UpdateRootNodeAggregateDimensions'
        settings:
          nodeType : 'Neos.Neos:Sites'

Adjust the root node dimensions

If you want to move any content into a new dimension space point, you need to do that first, before you update the root node aggregate dimensions.

bash
# Run the node migration to apply the changes to the dimension values
./flow nodemigration:execute 20240924093814 # Move dimension values
./flow nodemigration:execute 20240924095647 # Update root aggregate dimensions

Finally, flush the cache, to ensure no cached routes or cached rendered pages still exist. Then, test your changes:

bash
./flow flow:cache:flush

#Adding a dimension value

Dimension language
Dimension language
en
en
Dimension language
Dimension language
en
en
de
de
de
de
fr
fr
Text is not SVG - cannot display

Adjust dimension configuration

In Settings.yaml you need to add the new value for the existing content dimension.

Settings.yaml
Neos:
  ContentRepositoryRegistry:
    contentRepositories:
      default:
        contentDimensions:
          'language':
            label: 'Language'
            values:
              'en':
                label: English
              'de':
                label: German
              # Newly added:
              'fr':
                label: French

Also adjust the Site Dimension Routing configuration in Settings.yaml at key Neos.Neos.sites.*.contentDimensions.resolver - described in the Routing docs, to configure how the dimension should be mapped to URLs.

Running dimension migrations

The root node is, by definition, existing in every DimensionSpacePoint. Thus, if you change dimension configuration, the root node(s) need to be updated as well. The following migration creates empty root node aggregate dimensions for each allowed dimension combination and removes them for all non-configured ones.

Please also check the references for node migration.

Your.Package/Migration/ContentRepository/Version20240924095647.yaml
comments: 'Synchronize root node aggregates with content repository configuration'
migration:
  -
    transformations:
      - 
        type: 'UpdateRootNodeAggregateDimensions'
        settings:
          nodeType : 'Neos.Neos:Sites'

Adjust the root node dimensions

If you want to move any content into a new dimension space point, you need to do that first, before you update the root node aggregate dimensions.

bash
# Run the node migration to apply the changes to the dimension values
./flow nodemigration:execute 20240924095647 # Update root aggregate dimensions

Optional: Copy content from existing dimension

You can translate - as usual - in the Neos backend, by using the dimension switcher. Sometimes, however, it is useful to pre-populate content from an existing dimension. This can be done via the ./flow content:createVariantsRecursively command as shown below:

bash
# copy all content from "en" to "fr"
./flow content:createVariantsRecursively  '{"language": "en"}' '{"language": "fr"}'

In case you need this, you could also add the dimension value as a fallback. The difference is:

  • When not using fallbacks and copying content, the content is disconnected from the original dimension value. If a node in one dimension changes, it does not in the other.
  • When using fallbacks (see below), then a change on the base dimension (e.g. de) will be automatically visible in the specialized dimension (e.g. ch), as long as no specific content has been created for the specialization (e.g. ch).

Finally, flush the cache, to ensure no cached routes or cached rendered pages still exist. Then, test your changes:

bash
./flow flow:cache:flush

#Adding a dimension value as fallback

Dimension language
Dimension language
en
en
Dimension language
Dimension language
en
en
de
de
de
de
ch
ch
Text is not SVG - cannot display

Adjust dimension configuration

In Settings.yaml you need to add the new value for the existing content dimension, underneath specializations of the parent dimension value:

Settings.yaml
Neos:
  ContentRepositoryRegistry:
    contentRepositories:
      default:
        contentDimensions:
          'language':
            label: 'Language'
            values:
              'en':
                label: English
              'de':
                label: German
                # Newly added:
                specializations:
                  'ch':
                    label: Swiss

Also adjust the Site Dimension Routing configuration in Settings.yaml at key Neos.Neos.sites.*.contentDimensions.resolver - described in the Routing docs, to configure how the dimension should be mapped to URLs.

Running dimension migrations

Dimension shine through in the event-sourced content repository is implemented on the write side. This means that dimension fallbacks are resolved when writing changes. While reading, dimension fallbacks do not matter.

This is why you need to migrate the content to add a dimension shine-through; possible through a node migration like the following. 

Please also check the references for node migration.

Your.Package/Migration/ContentRepository/Version20240814180321.yaml

comments: 'Add shine through from german to swiss german'
migration:
  -
    transformations:
      -
        type: 'AddDimensionShineThrough'
        settings:
          from: { language: 'de' }
          to: { language: 'ch' }

In this scenario it's not necessary to update the root node aggregated dimension space points.

bash
# Run the node migration to apply the shine through
./flow nodemigration:execute 20240814180321

Finally, flush the cache, to ensure no cached routes or cached rendered pages still exist. Then, test your changes:

bash
./flow flow:cache:flush