Extending Formats

Last updated on
31 January 2026

Overview

Formats are plugins of type Format that reside in Plugin\menu_migration\Format.

They are used within Export Destinations and Import Sources to handle the encoding and decoding of menu hierarchies, allowing the module to work with different data formats during export and import operations.

The module comes with three predefined formats:

  • JsonFormat - Encodes/decodes menu hierarchies to/from JSON format
  • YamlFormat - Encodes/decodes menu hierarchies to/from YAML format
  • RawFormat - Passes menu hierarchies through without conversion (added in version 4.1.0)

Format Types

JSON Format

The JSON format plugin encodes menu hierarchies into JSON strings for export and decodes JSON strings back into arrays for import. This format is ideal for:

  • API integrations
  • Web-based data exchange
  • When you need a compact, widely-supported format

Files exported in JSON format have a .json extension and use the application/json MIME type.

YAML Format

The YAML format plugin encodes menu hierarchies into YAML strings for export and decodes YAML strings back into arrays for import. This format is ideal for:

  • Human-readable configuration files
  • Version control-friendly exports
  • When readability is more important than compactness

Files exported in YAML format can have either .yaml or .yml extensions and use the text/plain MIME type.

Raw Format

The Raw format plugin is a special format that doesn't perform any encoding or decoding - it passes the menu hierarchy array through unchanged. This format is primarily used internally for:

  • Menu-to-menu transfers (see the AnotherMenu export destination)
  • Operations where the menu hierarchy remains in PHP array format throughout the process
  • Custom integrations that handle their own data transformation

The Raw format has no associated file extensions or MIME type since it's not designed for file-based operations.

Note: Some Export Destinations and Import Sources may restrict which formats are available. For example, the AnotherMenu export destination only allows the Raw format since it transfers menus directly without file serialization.

Creating Custom Formats

If the formats included with this module don't fully meet your requirements, you have the flexibility to create your own custom format plugins.

Tip: If you develop a format plugin that could be beneficial to others, I encourage you to contribute it back to the module.

Step 1: Create the Plugin Class

For this demonstration, let's create a plugin named ExampleFormat. Within your custom module (we'll refer to it as MY_MODULE for this example), create the following file:

MY_MODULE/src/Plugin/menu_migration/Format/ExampleFormat.php

<?php

namespace Drupal\MY_MODULE\Plugin\menu_migration\Format;

use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\menu_migration\Attribute\MenuMigrationFormat;
use Drupal\menu_migration\Plugin\menu_migration\Format\FormatBase;

/**
 * Provides the Example import/export Format.
 */
#[MenuMigrationFormat(
  id: 'example',
  label: new TranslatableMarkup('Example')
)]
class ExampleFormat extends FormatBase {

  /**
   * {@inheritdoc}
   */
  public function encode(array $menuTree): string {
    // Convert the menu tree array to your custom format
    // Example: XML, CSV, custom binary format, etc.
    return $this->convertToCustomFormat($menuTree);
  }

  /**
   * {@inheritdoc}
   */
  public function decode(mixed $menuTree): array {
    // Convert from your custom format back to menu tree array
    return $this->convertFromCustomFormat($menuTree);
  }

  /**
   * {@inheritdoc}
   */
  public function allowedExtensions(): array {
    // Return allowed file extensions for this format
    return ['example', 'ex'];
  }

  /**
   * {@inheritdoc}
   */
  public function defaultExtension(): string {
    // Return the default file extension
    return 'example';
  }

  /**
   * {@inheritdoc}
   */
  public function mimeType(): string {
    // Return the MIME type for this format
    return 'application/x-example';
  }

  /**
   * Helper method to convert menu tree to custom format.
   */
  protected function convertToCustomFormat(array $menuTree): string {
    // Implement your encoding logic here
    return '';
  }

  /**
   * Helper method to convert from custom format to menu tree.
   */
  protected function convertFromCustomFormat(mixed $data): array {
    // Implement your decoding logic here
    return [];
  }

}

Step 2: Understanding the Plugin Annotation

The #[MenuMigrationFormat] attribute supports the following properties:

  • id - The unique machine name of the plugin (required)
  • label - The human-readable name displayed in the user interface (required)

Step 3: Implementing Required Methods

Your format plugin must implement the following methods from the FormatInterface:

encode(array $menuTree)

Transforms the menu tree array structure into your desired format for export.

  • Parameter: $menuTree - A nested array representing the menu hierarchy
  • Returns: The encoded data in your format (typically a string, but can be mixed type)

decode(mixed $menuTree)

Transforms data from your custom format back into the standard menu tree array structure for import.

  • Parameter: $menuTree - Data in your custom format
  • Returns: An array representing the menu hierarchy

allowedExtensions()

Defines valid file extensions for import operations. Used by the FileUpload import source plugin to validate uploaded files.

  • Returns: An array of allowed extensions (e.g., ['json', 'yaml'])
  • Note: Return an empty array if your format doesn't support file-based operations

defaultExtension()

Sets the default file extension for exported files. Used by the Download export destination plugin when generating filenames.

  • Returns: A string representing the default extension (e.g., 'json', 'yaml')
  • Note: Return an empty string if your format doesn't support file-based operations

mimeType()

Sets the appropriate MIME type for download headers. Used by the Download export destination plugin.

  • Returns: A string representing the MIME type (e.g., 'application/json', 'text/plain')
  • Note: Return an empty string if your format doesn't support file-based operations

Step 4: Enable Your Format in Export Destinations and Import Sources

After creating your custom format plugin, you need to explicitly enable it in the Export Destinations and/or Import Sources where you want to use it. This is done by adding your format's plugin ID to the allowed_formats property in their plugin annotations.

For example, to enable your example format in the Download export destination and FileUpload import source, you would modify their annotations:

// In Download.php
#[MenuMigrationDestination(
  id: 'download',
  label: new TranslatableMarkup('Download'),
  allowed_formats: ['json', 'yaml', 'example'], // Add your format here
  multiple: FALSE,
  cli: TRUE
)]

// In FileUpload.php
#[MenuMigrationSource(
  id: 'file_upload',
  label: new TranslatableMarkup('File upload'),
  allowed_formats: ['json', 'yaml', 'example'], // Add your format here
  multiple: FALSE,
  cli: TRUE
)]

Note: As of version 4.1.0, the allowed_formats property is required for all Export Destination and Import Source plugins. If omitted, a deprecation warning is triggered and the default formats (json and yaml) are used. In version 5.0.0, omitting this property will cause an error. See drupal.org/node/3498853 for more information.

Step 5: Clear Cache

Once you have created your custom format plugin and updated the relevant Export Destinations and Import Sources, clear Drupal's caches:

drush cr

Your new format should now be available in the destinations and sources you've configured.

Using Your Custom Format

After enabling your custom format in the appropriate Export Destinations and/or Import Sources (as described in Step 5), you can use it in your menu export and import operations.

For Exports

Navigate to ConfigurationDevelopmentMenu MigrationMenu Exports, and click on +Add menu export. When you select an Export Destination that includes your format in its allowed_formats list, your custom format will appear in the format selection dropdown.

Menu Migration custom format export

For Imports

Navigate to ConfigurationDevelopmentMenu MigrationMenu Imports, and click on +Add menu import. When you select an Import Source that includes your format in its allowed_formats list, your custom format will appear in the format selection options.

Menu Migration custom format import

Reference Implementations

For complete examples of Format implementations, refer to the following files in the menu_migration/src/Plugin/menu_migration/Format/ directory:

  • JsonFormat.php - Example of encoding/decoding with JSON serialization
  • YamlFormat.php - Example of encoding/decoding with YAML serialization
  • RawFormat.php - Example of a pass-through format with no transformation

Help improve this page

Page status: No known problems

You can: