Skip to content
Snippets Groups Projects
Select Git revision
  • 4.0.3
  • 4.1.x default
  • 4.0.x
  • 2.0.x
  • 1.0.x
  • 3.0.x
  • 4.0.2
  • 2.0.0
  • 1.0.0
  • 4.0.1
  • 4.0.0
  • 4.0.0-beta1
  • 4.0.0-alpha2
  • 4.0.0-alpha1
  • 3.0.0
  • 3.0.0-alpha1
  • 2.0.0-alpha3
  • 2.0.0-alpha2
  • 2.0.0-alpha1
  • 1.0.0-alpha1
20 results

menu_migration

  • Clone with SSH
  • Clone with HTTPS
  • Cristina's avatar
    Issue #3526804: Remove the FullyValidatable constraint plugin from schema...
    Drupal Lady authored
    Issue #3526804: Remove the FullyValidatable constraint plugin from schema until core min req is 10.3
    021e8976
    History

    Menu Migration

    The Menu Migration module facilitates the import and export of menu hierarchies from one Drupal copy to another one.

    Out of the box, the module allows the following:

    • Export menu hierarchies to a file in the codebase
    • Import menu hierarchies from a file in the codebase
    • Export menu hierarchies to a downloadable file
    • Import menu hierarchies from an uploaded file

    The module only supports MenuLinkContent menu items (the ones that are manually created), any other menu items will not be exported/imported (e.g. Views, Taonomy Menu etc.). It currently offers two formats: JSON & YAML.

    The export destinations, import sources and formats can be extended through the Plugin system.

    For a full description of the module, visit the project page.

    For a detailed documentation, visit the module documentation.

    Submit bug reports and feature suggestions, or track changes in the issue queue.

    Chat, news, support & feedback in the dedicated Slack channel.

    Table of contents

    Requirements

    File permissions actions might be required on the server for the Codebase Export Destination.

    Installation

    Install as you would normally install a contributed Drupal module. For further information, see Installing Drupal Modules.

    Configuration

    There are three configuration areas that are available:

    1. Menu Exports - allows defining menu exports that can later trigger exports
    2. Menu Imports - allows defining menu imports that can later trigger imports
    3. Quick Action Settings - allows configuring the quick exports and imports using Drush, without having to create Menu Exports and Menu Imports

    Defining a menu export

    In order to perform a menu export, a Menu Export needs to be created.

    Note that this step is not required if you plan to only use the quick exports functionality. See the drush menu_migration:quick-export (alias drush mmqe) command.

    1. Navigate to Configuration → Development → Menu Migration → Menu Exports
    2. Click on Add menu export and fill out the form
    3. The Menu export name can be anything relevant to you
    4. The machine name will be the ID of the menu export and will be used with Drush
    5. The Export Destination can have one of the following values: Codebase or Download
    6. The Codebase exports the menus to the file system, and the Download generates a downloadable file
    7. Set the Format to JSON or YAML
    8. Select the Menus that you wish to export
    9. Fill out any other field depending on the Export Destination choice.

    Note: On the Menu Exports listing page, you can drag and drop the menu exports to reorder them, which will update their weight accordingly.

    Export menu

    1. Navigate to Configuration → Development → Menu Migration → Menu Exports
    2. Here you have a listing of the available menu exports
    3. In the Operations column, click on Export for one of the menu exports
    4. You will be presented with a confirmation form that details all information about the export process & location
    5. If you are satisfied with the conditions, click on export and that's it

    Defining a menu import

    In order to perform a menu import, a Menu Import needs to be created.

    Note that this step is not required if you plan to only use the quick imports functionality. See the drush menu_migration:quick-import (alias drush mmqi) command.

    1. Navigate to Configuration → Development → Menu Migration → Menu Imports
    2. Click on Add Menu import and fill out the form
    3. The Menu import name can be anything relevant to you
    4. The machine name will be the ID of the Menu import and will be used with Drush
    5. The Import Source can have one of the following values: Codebase or File Upload.
    6. The Codebase Imports the menus from the file system, and the File Upload imports them from an uploaded file
    7. Set the Format to JSON or YAML
    8. Select the Menus that you wish to Import
    9. Fill out any other field depending on the Import Source choice.

    Note: On the Menu Imports listing page, you can drag and drop the menu imports to reorder them, which will update their weight accordingly.

    Import menu

    1. Navigate to Configuration → Development → Menu Migration → Menu Imports
    2. Here you have a listing of the available menu imports
    3. In the Operations column, click on Import for one of the menu exports
    4. You will be presented with a confirmation form that details all information about the import process & source
    5. If you are satisfied with the conditions, click on import and that's it

    Quick Action Settings

    Quick Action is a feature that allows Drush users to export and import menus directly by providing the menu IDs as arguments to the associated Drush commands. This allows for bypassing the creation of configuration entities which are intended for more stable and repetitive exports and imports.

    The quick action settings influence the behaviour of the following Drush commands: drush menu_migration:quick-export (alias drush mmqe) and drush menu_migration:quick-import (alias drush mmqi).

    1. Navigate to Configuration → Development → Menu Migration → Quick Action Settings
    2. Here you can control the export/import format (JSON or YAML) and the target/source directory for exports and imports.
    3. By default, the format is JSON and the directory is set to '../config/menu_migration/quick-export'

    Access and Permissions

    The following permissions are available:

    Machine name Title Usage
    administer menu migration Administer menu migration Bypasses any other menu_migration permission, and gives access to everything.
    administer menu migration export types Administer menu exports Administer Menu Exports: add, edit, delete, export. Anything related to Menu Exports.
    administer menu migration import types Administer menu imports Administer Menu Imports: add, edit, delete, export. Anything related to Menu Imports.
    perform export on menu migrations Perform export on any Menu Exports Access to the Menu Exports listing page and permission to perform exports.
    perform import on menu migrations Perform import on any Menu Imports Access to the Menu Exports listing page and permission to perform imports.

    Drush integration

    Menu migration provides six Drush commands for managing imports and exports. You can import one or more menus at a time through your already defined menu exports and menu imports, or you can import/export menus directly without having to define Configuration Entities using the quick import/export commands.

    Export Command

    Performs the export for the given menu export ID. Requires confirmation.

    • Command: drush menu_migration:export
    • Alias: drush mme

    Examples using the full command

    # Export the Menu Export with ID my_export_id.
    drush menu_migration:export my_export_id
    # Export the Menu Export with ID my_export_id, and skip confirmation question.
    drush menu_migration:export my_export_id -y

    Examples using the alias

    # Export the Menu Export with ID my_export_id.
    drush mme my_export_id
    # Export the Menu Export with ID my_export_id, and skip confirmation question.
    drush mme my_export_id -y

    Export List Command

    Lists all the available menu exports that support Drush.

    • Command: drush menu_migration:export-list
    • Alias: drush mmel

    Example using the full command

    # List all the available export entities
    drush menu_migration:export-list

    Example using the alias

    # List all the available export entities
    drush mmel

    Quick Export Command

    Performs the export of one or more menus by menu IDs. Requires confirmation.

    • Command: drush menu_migration:quick-export
    • Alias: drush mmqe
    • Options:
      • --format[=FORMAT] (optional)

    Examples using the full command

    # Export the main menu.
    drush menu_migration:quick-export main
    # Export the main menu and override the format (e.g. yaml).
    drush menu_migration:quick-export main --format=yaml
    # Export the main, footer, custom_menu menus.
    drush menu_migration:quick-export main,footer,custom_menu
    # Export the main menu, and skip confirmation question.
    drush menu_migration:quick-export main -y
    # Export the main, footer, custom_menu menus and skip the confirmation question.
    drush menu_migration:quick-export main,footer,custom_menu -y

    Examples using the alias

    # Export the main menu.
    drush mmqe main
    # Export the main menu and override the format (e.g. yaml).
    drush mmqe main --format=yaml
    # Export the main, footer, custom_menu menus.
    drush mmqe main,footer,custom_menu
    # Export the main menu, and skip confirmation question.
    drush mmqe main -y
    # Export the main, footer, custom_menu menus and skip the confirmation question.
    drush mmqe main,footer,custom_menu -y

    Import Command

    Performs the import for the given menu export ID. Requires confirmation.

    • Command: drush menu_migration:import
    • Alias: drush mmi

    Examples using the full command

    # Import the Menu Import with ID my_import_id.
    drush menu_migration:import my_import_id
    # Import the Menu Import with ID my_import_id, and skip the confirmation question.
    drush menu_migration:import my_import_id -y

    Examples using the alias

    # Import the Menu Import with ID my_import_id.
    drush mmi my_import_id
    # Import the Menu Import with ID my_import_id, and skip the confirmation question.
    drush mmi my_import_id -y

    Import List Command

    Lists all the available menu imports that support Drush.

    • Command: drush menu_migration:import-list
    • Alias: drush mmil

    Example using the full command

    # List all the available import entities
    drush menu_migration:import-list

    Example using the alias

    # List all the available import entities
    drush mmil

    Quick Import Command

    Performs the import of one or more menus by menu IDs. Requires confirmation.

    • Command: drush menu_migration:quick-import
    • Alias: drush mmqi
    • Options:
      • --format[=FORMAT] (optional)

    Examples using the full command

    # Import the main menu.
    drush menu_migration:quick-import main
    # Import the main menu and override the format (e.g. yaml).
    drush menu_migration:quick-import main --format=yaml
    # Import the main, footer, custom_menu menus.
    drush menu_migration:quick-import main,footer,custom_menu
    # Import the main menu, and skip confirmation question.
    drush menu_migration:quick-import main -y
    # Import the main, footer, custom_menu menus and skip the confirmation question.
    drush menu_migration:quick-import main,footer,custom_menu -y

    Examples using the alias

    # Import the main menu.
    drush mmqi main
    # Import the main menu and override the format (e.g. yaml).
    drush mmqi main --format=yaml
    # Import the main, footer, custom_menu menus.
    drush mmqi main,footer,custom_menu
    # Import the main menu, and skip confirmation question.
    drush mmqi main -y
    # Import the main, footer, custom_menu menus and skip the confirmation question.
    drush mmqi main,footer,custom_menu -y

    Extending Destinations

    You can easily extend export destinations, and add your own custom destination by implementing a MenuMigrationDestination plugin and defining its schema.

    Existing examples with more code in:

    • src/Plugin/menu_migration/ExportDestination/Codebase.php
    • src/Plugin/menu_migration/ExportDestination/Download.php

    Example:

    File: src/Plugin/menu_migration/ExportDestination/MyDestination.php

    File Contents:

    <?php
    
    namespace Drupal\mymodule\Plugin\menu_migration\ExportDestination;
    
    use Drupal\Core\StringTranslation\TranslatableMarkup;
    use Drupal\menu_migration\Attribute\MenuMigrationDestination;
    use Drupal\menu_migration\Plugin\menu_migration\ExportDestination\ExportDestinationBase;
    
    /**
     * Provides a MyDestination export destination.
     */
    #[MenuMigrationDestination(
      id: 'mydestination',
      label: new TranslatableMarkup('My Destination'),
      multiple: FALSE, # Optional, defaults to TRUE
      cli: TRUE # Optional, defaults to FALSE
    )]
    class MyDestination extends ExportDestinationBase {
    
      /**
       * {@inheritdoc}
       */
      public function exportMenu(string $menuName) {
        // TODO: Implement the export logic and return a boolean.
        // If the export fails, and you wish to display e detailed error message
        // about what went wrong, you interrupt the process and do the following:
        throw new MenuMigrationException(sprintf('My error message with the "%s" argument.', $argument));
      }
    
      /**
       * {@inheritdoc}
       */
      public function getExportDescription() {
        $description = parent::getExportDescription();
        // The parent contains the general export description. You can add details
        // specific to your export plugin here.
        $description[] = $this->t('The menus will have something special.');
        return $description;
      }
    
    }

    Additionally, if you'd like to display extra information in the listing pages about the destination plugin, you can implement the configurationSummary() method to do so. This method must return an array of one or more lines of text. A concrete example can be found in the Codebase destination plugin.

    The example below displays the Codebase export path below the plugin label in the export listing page:

    /**
     * {@inheritdoc}
     */
    public function configurationSummary() {
      return [
        $this->configuration['export_path'],
      ];
    }

    Define a schema for your new plugin by adding or modifying the following file: mymodule/config/schema/mymodule.schema.yml

    # This definition applies to ExportDestination plugins that don't allow multiple
    # menus, and that don't have extra configurable fields other than menus and
    # format.
    menu_migration.destination_config.mydestination:
      type: source_destination_config_single
      label: 'My Destination'

    where:

    • mydestination is the ID of your ExportDestination plugin
    • source_destination_config_single is the data type for plugins that don't allow multiple menus. If your plugin allows multiple menus, change this to source_destination_config_multiple

    If our example plugin were to define an extra configurable field called extra_config as textfield, our schema would become:

    menu_migration.destination_config.mydestination:
      type: source_destination_config_single
      label: 'My Destination'
      mapping:
        extra_config:
          type: string
          label: 'Extra Config'

    Exising examples can be found in menu_migration/config/schema/menu_migration.schema.yml

    Extending Formats

    You can easily extend export/import formats, and add your own custom format by implementing a MenuMigrationFormat plugin.

    Existing examples with more code in:

    • src/Plugin/menu_migration/Format/JsonFormat.php

    Example:

    File: src/Plugin/menu_migration/Format/MyFormat.php

    File Contents:

    <?php
    
    namespace Drupal\mymodule\Plugin\menu_migration\Format;
    
    use Drupal\Component\Serialization\Json;
    use Drupal\Core\StringTranslation\TranslatableMarkup;
    use Drupal\menu_migration\Attribute\MenuMigrationFormat;
    use Drupal\menu_migration\Plugin\menu_migration\Format\FormatBase;
    
    /**
     * Provides the myFormat import/export Format.
     */
    #[MenuMigrationFormat(
      id: 'myformat',
      label: new TranslatableMarkup('My Format')
    )]
    class MyFormat extends FormatBase {
    
      /**
       * {@inheritdoc}
       */
      public function encode(array $menuTree) {
        // Here you encode your menu tree. Example with JSON.
        return Json::encode($menuTree);
      }
    
      /**
       * {@inheritdoc}
       */
      public function decode(mixed $menuTree) {
        // Here you decode your menu tree. Example with JSON.
        return Json::decode($menuTree);
      }
    
      /**
       * {@inheritdoc}
       */
      public function allowedExtensions() {
        // Here you add allowed file extensions for sources like file_upload. If
        // applicable?
        return ['json'];
      }
    
      /**
       * {@inheritdoc}
       */
      public function defaultExtension() {
        // Here you add the default file extension for exports. If applicable?
        return 'json';
      }
    
      /**
       * {@inheritdoc}
       */
      public function mimeType() {
        // Here you add the default file mimetype for exports like download. If
        // applicable?
        return 'application/json';
      }
    
    }

    Extending Sources

    You can easily extend import sources, and add your own custom sources by implementing a MenuMigrationSource plugin and defining its schema.

    Existing examples with more code in:

    • src/Plugin/menu_migration/ImportSource/Codebase.php
    • src/Plugin/menu_migration/ImportSource/FileUpload.php

    Example:

    File: src/Plugin/menu_migration/ImportSource/MySource.php

    File Contents:

    <?php
    
    namespace Drupal\mymodule\Plugin\menu_migration\ImportSource;
    
    use Drupal\Core\StringTranslation\TranslatableMarkup;
    use Drupal\menu_migration\Attribute\MenuMigrationSource;
    use Drupal\menu_migration\Plugin\menu_migration\ImportSource\ImportSourceBase;
    
    /**
     * Provides a MySource import source.
     */
    #[MenuMigrationSource(
      id: 'mysource',
      label: new TranslatableMarkup('My Source'),
      multiple: FALSE, # Optional, defaults to TRUE
      cli: TRUE # Optional, defaults to FALSE
    )]
    class MySource extends ImportSourceBase {
    
      /**
       * {@inheritdoc}
       */
      public function importMenu(string $menuName) {
        // TODO: Implement the import logic and return a boolean.
        // If the import fails, and you wish to display e detailed error message
        // about what went wrong, you interrupt the process and do the following:
        throw new MenuMigrationException(sprintf('My error message with the "%s" argument.', $argument));
      }
    
      /**
       * {@inheritdoc}
       */
      public function getImportDescription() {
        $description = parent::getImportDescription();
        // The parent contains the general import description. You can add details
        // specific to your export plugin here.
        $description[] = $this->t('The menus will have something special.');
        return $description;
      }
    
    }

    Additionally, if you'd like to display extra information in the listing pages about the source plugin, you can implement the configurationSummary() method to do so. This method must return an array of one or more lines of text. A concrete example can be found in the Codebase source plugin.

    The example below displays the Codebase import path below the plugin label in the import listing page:

    /**
     * {@inheritdoc}
     */
    public function configurationSummary() {
      return [
        $this->configuration['import_path'],
      ];
    }

    Define a schema for your new plugin by adding or modifying the following file: mymodule/config/schema/mymodule.schema.yml

    # This definition applies to ImportSource plugins that don't allow multiple
    # menus, and that don't have extra configurable fields other than menus and
    # format.
    menu_migration.source_config.mysource:
      type: source_destination_config_single
      label: 'My Source'

    where:

    • mysource is the ID of your ImportSource plugin
    • source_destination_config_single is the data type for plugins that don't allow multiple menus. If your plugin allows multiple menus, change this to source_destination_config_multiple

    If our example plugin were to define an extra configurable field called extra_config as textfield, our schema would become:

    menu_migration.source_config.mysource:
      type: source_destination_config_single
      label: 'My Source'
      mapping:
        extra_config:
          type: string
          label: 'Extra Config'

    Exising examples can be found in menu_migration/config/schema/menu_migration.schema.yml

    Troubleshooting

    If you're getting errors that the menus can't be exported, please make sure that the target directory has writing access by the server user that is about to execute the exports when using the Codebase destination.

    If the menu item hierarchy is messed up after import, make sure menu items are only added via the menu UI (for example "Main navigation") and not a View.

    Maintainers

    Cristina B. - bbu23