From 52d4ba85030c7a4a46269322ac7ff5211948c648 Mon Sep 17 00:00:00 2001 From: Mike Ryan <mikeryan@virtuoso-performance.com> Date: Mon, 11 Apr 2016 09:35:48 -0500 Subject: [PATCH] Issue #2701277 by mikeryan: Use configuration entities as a registration mechanism for migrations --- .../schema/migrate_plus.data_types.schema.yml | 40 +++++ .../migrate_plus.destination.schema.yml | 18 +++ config/schema/migrate_plus.process.schema.yml | 145 ++++++++++++++++++ config/schema/migrate_plus.schema.yml | 49 +++++- config/schema/migrate_plus.source.schema.yml | 34 ++++ .../migrate_plus.migration.beer_comment.yml} | 0 .../migrate_plus.migration.beer_node.yml} | 0 .../migrate_plus.migration.beer_term.yml} | 3 + .../migrate_plus.migration.beer_user.yml} | 4 +- migrate_plus.services.yml | 3 + src/Entity/Migration.php | 44 ++++++ src/Entity/MigrationGroup.php | 1 - src/Entity/MigrationInterface.php | 17 ++ .../Discovery/ConfigEntityDiscovery.php | 54 +++++++ .../MigrationConfigEntityPluginManager.php | 30 ++++ 15 files changed, 439 insertions(+), 3 deletions(-) create mode 100644 config/schema/migrate_plus.data_types.schema.yml create mode 100644 config/schema/migrate_plus.destination.schema.yml create mode 100644 config/schema/migrate_plus.process.schema.yml create mode 100644 config/schema/migrate_plus.source.schema.yml rename migrate_example/{migrations/migrate.migration.beer_comment.yml => config/install/migrate_plus.migration.beer_comment.yml} (100%) rename migrate_example/{migrations/migrate.migration.beer_node.yml => config/install/migrate_plus.migration.beer_node.yml} (100%) rename migrate_example/{migrations/migrate.migration.beer_term.yml => config/install/migrate_plus.migration.beer_term.yml} (97%) rename migrate_example/{migrations/migrate.migration.beer_user.yml => config/install/migrate_plus.migration.beer_user.yml} (97%) create mode 100644 src/Entity/Migration.php create mode 100644 src/Entity/MigrationInterface.php create mode 100644 src/Plugin/Discovery/ConfigEntityDiscovery.php create mode 100644 src/Plugin/MigrationConfigEntityPluginManager.php diff --git a/config/schema/migrate_plus.data_types.schema.yml b/config/schema/migrate_plus.data_types.schema.yml new file mode 100644 index 00000000..27c8006f --- /dev/null +++ b/config/schema/migrate_plus.data_types.schema.yml @@ -0,0 +1,40 @@ +# Basic data types for Migrate. + +migrate_plugin: + type: mapping + mapping: + plugin: + type: string + label: 'Plugin' + +migrate_destination: + type: migrate_plugin + label: 'Destination' + mapping: + overwrite_properties: + type: sequence + label: 'Properties to overwrite' + sequence: + type: string + label: 'Property' + +migrate_source: + type: migrate_plugin + label: 'Source' + mapping: + constants: + type: ignore + label: 'Constants' + +migrate_process: + type: migrate_plugin + label: 'Process' + +# Base schema for migrate source plugins that extend +# \Drupal\migrate\Plugin\migrate\source\SqlBase. +migrate_source_sql: + type: migrate_source + mapping: + target: + type: string + label: 'The migration database target' diff --git a/config/schema/migrate_plus.destination.schema.yml b/config/schema/migrate_plus.destination.schema.yml new file mode 100644 index 00000000..58ad74e5 --- /dev/null +++ b/config/schema/migrate_plus.destination.schema.yml @@ -0,0 +1,18 @@ +# Schema for the migrate destination plugins. + +migrate_plus.destination.*: + type: migrate_destination + label: 'Default destination' + mapping: + no_stub: + type: boolean + label: 'Whether stubbing is allowed.' + default: false + +migrate_plus.destination.config: + type: migrate_destination + label: 'Config' + mapping: + config_name: + type: string + label: 'Configuration name' diff --git a/config/schema/migrate_plus.process.schema.yml b/config/schema/migrate_plus.process.schema.yml new file mode 100644 index 00000000..b1f123bc --- /dev/null +++ b/config/schema/migrate_plus.process.schema.yml @@ -0,0 +1,145 @@ +# Schema for the migrate process plugins. + +migrate_plus.process.*: + type: migrate_process + label: 'Default process' + +migrate_plus.process.callback: + type: migrate_process + label: 'Callback process' + mapping: + callback: + type: string + label: 'Callback' + +migrate_plus.process.concat: + type: migrate_process + label: 'Concat process' + mapping: + delimiter: + type: string + label: 'Delimiter' + +migrate_plus.process.dedupe_entity: + type: migrate_process + label: 'Dedupe Entity process' + mapping: + entity_type: + type: string + label: 'Entity type' + field: + type: string + label: 'Field name' + postfix: + type: string + label: 'Postfix' + start: + type: integer + label: 'Start' + length: + type: integer + label: 'Length' + +migrate_plus.process.explode: + type: migrate_process + label: 'Explode process' + mapping: + delimiter: + type: string + label: 'Delimiter' + limit: + type: integer + label: 'Limit' + +migrate_plus.process.extract: + type: migrate_process + label: 'Extract process' + mapping: + default: + type: string + label: 'Default value' + +migrate_plus.process.flatten: + type: migrate_process + label: 'Flatten process' + +migrate_plus.process.get: + type: migrate_process + label: 'Get process' + mapping: + source: + type: string + label: 'Source key' + +migrate_plus.process.iterator: + type: migrate_process + label: 'Iterator process' + mapping: + process: + type: ignore + label: 'Process' + key: + type: string + label: 'Key' + +migrate_plus.process.machine_name: + type: migrate_process + label: 'Machine name process' + +migrate_plus.process.migration: + type: migrate_process + label: 'Migration process' + mapping: + migration: + type: sequence + label: 'Migration' + source: + type: sequence + label: 'Source keys' + source_ids: + type: string + label: 'Source IDs' + stub_id: + type: string + label: 'Stub ID' + +migrate_plus.process.route: + type: migrate_process + label: 'Route process' + +migrate_plus.process.skip_on_empty: + type: migrate_process + label: 'Skip on Empty' + +migrate_plus.process.skip_row_if_not_set: + type: migrate_process + label: 'Skip Row process if not set' + mapping: + index: + type: integer + label: 'Index' + +migrate_plus.process.static_map: + type: migrate_process + label: 'Static Map' + mapping: + map: + type: sequence + label: 'Map' + default_value: + type: string + label: 'Default value' + bypass: + type: boolean + label: 'Bypass lookup' + +migrate_plus.process.default_value: + type: migrate_process + label: 'Default value' + mapping: + strict: + type: boolean + label: 'Strict type check' + default_value: + type: string + label: 'Default value' diff --git a/config/schema/migrate_plus.schema.yml b/config/schema/migrate_plus.schema.yml index 63712fbb..a2c682d4 100644 --- a/config/schema/migrate_plus.schema.yml +++ b/config/schema/migrate_plus.schema.yml @@ -1,3 +1,50 @@ +# Schema for the configuration files of the Migrate Plus module. + +migrate_plus.migration.*: + type: config_entity + label: 'Migration' + mapping: + id: + type: string + label: 'ID' + migration_tags: + type: sequence + label: 'Migration Tags' + sequence: + type: string + label: 'Tag' + label: + type: label + label: 'Label' + source: + type: migrate_plus.source.[plugin] + label: 'Source' + process: + type: ignore + label: 'Process' + destination: + type: migrate_plus.destination.[plugin] + label: 'Destination' + template: + type: string + label: 'Template' + migration_dependencies: + type: mapping + label: 'Dependencies' + mapping: + required: + type: sequence + label: 'Required dependencies' + sequence: + type: string + label: 'Dependency' + optional: + type: sequence + label: 'Optional dependencies' + sequence: + type: string + label: 'Dependency' + migrate_plus.migration_group.*: type: config_entity label: 'Migration Group' @@ -20,7 +67,7 @@ migrate_plus.migration_group.*: shared_configuration: type: ignore label: 'Shared migration configuration' -migrate.migration.*.third_party.migrate_plus: +migrate_plus.migration.*.third_party.migrate_plus: type: mapping label: 'Group' mapping: diff --git a/config/schema/migrate_plus.source.schema.yml b/config/schema/migrate_plus.source.schema.yml new file mode 100644 index 00000000..4117ea41 --- /dev/null +++ b/config/schema/migrate_plus.source.schema.yml @@ -0,0 +1,34 @@ +# Schema for the migrate source plugins. + +migrate_plus.source.*: + type: migrate_source + label: 'Default source' + +migrate_plus.source.empty: + type: migrate_source_sql + label: 'Empty source' + mapping: + provider: + type: string + label: 'Provider' + +migrate_plus.source.embedded_data: + type: migrate_source + label: 'Embedded data source' + mapping: + data_rows: + type: sequence + label: 'Data rows' + sequence: + type: ignore + label: 'Data row' + ids: + type: sequence + label: 'Unique key' + sequence: + type: mapping + label: 'Key column' + mapping: + type: + type: string + label: 'Column type' diff --git a/migrate_example/migrations/migrate.migration.beer_comment.yml b/migrate_example/config/install/migrate_plus.migration.beer_comment.yml similarity index 100% rename from migrate_example/migrations/migrate.migration.beer_comment.yml rename to migrate_example/config/install/migrate_plus.migration.beer_comment.yml diff --git a/migrate_example/migrations/migrate.migration.beer_node.yml b/migrate_example/config/install/migrate_plus.migration.beer_node.yml similarity index 100% rename from migrate_example/migrations/migrate.migration.beer_node.yml rename to migrate_example/config/install/migrate_plus.migration.beer_node.yml diff --git a/migrate_example/migrations/migrate.migration.beer_term.yml b/migrate_example/config/install/migrate_plus.migration.beer_term.yml similarity index 97% rename from migrate_example/migrations/migrate.migration.beer_term.yml rename to migrate_example/config/install/migrate_plus.migration.beer_term.yml index d92a8b38..b0ee91ac 100644 --- a/migrate_example/migrations/migrate.migration.beer_term.yml +++ b/migrate_example/config/install/migrate_plus.migration.beer_term.yml @@ -82,3 +82,6 @@ process: # with the Drupal term ID of the referenced style (or NULL if style_parent # was empty). source: style_parent + +# We'll learn more about dependencies in beer_node - here, we leave them empty. +migration_dependencies: {} diff --git a/migrate_example/migrations/migrate.migration.beer_user.yml b/migrate_example/config/install/migrate_plus.migration.beer_user.yml similarity index 97% rename from migrate_example/migrations/migrate.migration.beer_user.yml rename to migrate_example/config/install/migrate_plus.migration.beer_user.yml index 7f4a4ab7..fcbb4702 100644 --- a/migrate_example/migrations/migrate.migration.beer_user.yml +++ b/migrate_example/config/install/migrate_plus.migration.beer_user.yml @@ -1,5 +1,5 @@ # Migration configuration for user accounts. We've described most of what goes -# into migration configuration in migrate.migration.beer_term.yml, so won't +# into migration configuration in migrate_plus.migration.beer_term.yml, so won't # repeat that here. id: beer_user label: Beer Drinkers of the world @@ -95,3 +95,5 @@ process: # plugin: migration # source: beers # migration: beer_node + +migration_dependencies: {} diff --git a/migrate_plus.services.yml b/migrate_plus.services.yml index 3efe3607..da0bc916 100644 --- a/migrate_plus.services.yml +++ b/migrate_plus.services.yml @@ -5,3 +5,6 @@ services: plugin.manager.migrate_plus.data_parser: class: Drupal\migrate_plus\DataParserPluginManager parent: default_plugin_manager + plugin.manager.config_entity_migration: + class: Drupal\migrate_plus\Plugin\MigrationConfigEntityPluginManager + arguments: ['@module_handler', '@cache.discovery', '@language_manager'] diff --git a/src/Entity/Migration.php b/src/Entity/Migration.php new file mode 100644 index 00000000..b1b72f65 --- /dev/null +++ b/src/Entity/Migration.php @@ -0,0 +1,44 @@ +<?php + +/** + * @file + * Contains Drupal\migrate_plus\Entity\Migration. + */ + +namespace Drupal\migrate_plus\Entity; + +use Drupal\Core\Config\Entity\ConfigEntityBase; + +/** + * Defines the Migration entity. + * + * The migration entity stores the information about a single migration, like + * the source, process and destination plugins. + * + * @ConfigEntityType( + * id = "migration", + * label = @Translation("Migration"), + * entity_keys = { + * "id" = "id", + * "label" = "label", + * "weight" = "weight" + * } + * ) + */ +class Migration extends ConfigEntityBase implements MigrationInterface { + + /** + * The migration ID (machine name). + * + * @var string + */ + protected $id; + + /** + * The human-readable label for the migration. + * + * @var string + */ + protected $label; + +} diff --git a/src/Entity/MigrationGroup.php b/src/Entity/MigrationGroup.php index 589f1d7d..35e1ecaf 100644 --- a/src/Entity/MigrationGroup.php +++ b/src/Entity/MigrationGroup.php @@ -8,7 +8,6 @@ namespace Drupal\migrate_plus\Entity; use Drupal\Core\Config\Entity\ConfigEntityBase; -use Drupal\migrate\Plugin\MigrationInterface; /** * Defines the Migration Group entity. diff --git a/src/Entity/MigrationInterface.php b/src/Entity/MigrationInterface.php new file mode 100644 index 00000000..728c287e --- /dev/null +++ b/src/Entity/MigrationInterface.php @@ -0,0 +1,17 @@ +<?php + +/** + * @file + * Contains \Drupal\migrate_plus\Entity\MigrationInterface. + */ + +namespace Drupal\migrate_plus\Entity; + +use Drupal\Core\Config\Entity\ConfigEntityInterface; + +/** + * Interface for migrations. + */ +interface MigrationInterface extends ConfigEntityInterface { + +} diff --git a/src/Plugin/Discovery/ConfigEntityDiscovery.php b/src/Plugin/Discovery/ConfigEntityDiscovery.php new file mode 100644 index 00000000..3367e168 --- /dev/null +++ b/src/Plugin/Discovery/ConfigEntityDiscovery.php @@ -0,0 +1,54 @@ +<?php + +/** + * @file + * Contains \Drupal\migrate_plus\Plugin\Discovery\ConfigEntityDiscovery. + */ + +namespace Drupal\migrate_plus\Plugin\Discovery; + +use Drupal\Component\Plugin\Discovery\DiscoveryInterface; +use Drupal\Component\Plugin\Discovery\DiscoveryTrait; + +/** + * Allows configuration entities to define plugin definitions. + */ +class ConfigEntityDiscovery implements DiscoveryInterface { + + use DiscoveryTrait; + + /** + * Entity type to query. + * + * @var string + */ + protected $entityType; + + /** + * Construct a YamlDiscovery object. + * + * @param string $entity_type + * The entity type to query for. + */ + function __construct($entity_type) { + $this->entityType = $entity_type; + } + + /** + * {@inheritdoc} + */ + public function getDefinitions() { + $definition = \Drupal::entityTypeManager()->getDefinition($this->entityType); + $prefix = $definition->getConfigPrefix() . '.'; + $storage = \Drupal::service('config.storage'); + $query = \Drupal::entityQuery($this->entityType); + $ids = $query->execute(); + $definitions = []; + foreach ($ids as $id) { + $definitions[$id] = $storage->read($prefix . $id); + } + + return $definitions; + } + +} diff --git a/src/Plugin/MigrationConfigEntityPluginManager.php b/src/Plugin/MigrationConfigEntityPluginManager.php new file mode 100644 index 00000000..61c0cb5c --- /dev/null +++ b/src/Plugin/MigrationConfigEntityPluginManager.php @@ -0,0 +1,30 @@ +<?php + +/** + * @file + * Contains \Drupal\migrate_plus\Plugin\MigrationConfigEntityPluginManager. + */ + +namespace Drupal\migrate_plus\Plugin; + +use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator; +use Drupal\migrate\Plugin\MigrationPluginManager; +use Drupal\migrate_plus\Plugin\Discovery\ConfigEntityDiscovery; + +/** + * Plugin manager for migration plugins. + */ +class MigrationConfigEntityPluginManager extends MigrationPluginManager { + + /** + * {@inheritdoc} + */ + protected function getDiscovery() { + if (!isset($this->discovery)) { + $discovery = new ConfigEntityDiscovery('migration'); + $this->discovery = new ContainerDerivativeDiscoveryDecorator($discovery); + } + return $this->discovery; + } + +} -- GitLab