diff --git a/core/modules/config/src/Tests/DefaultConfigTest.php b/core/modules/config/src/Tests/DefaultConfigTest.php index 04b697b58df39844f776c9298f24c8145dee45ae..265461bd738cb540b0d97fe470521152a4d8529e 100644 --- a/core/modules/config/src/Tests/DefaultConfigTest.php +++ b/core/modules/config/src/Tests/DefaultConfigTest.php @@ -54,12 +54,6 @@ public function testDefaultConfig() { $default_config_storage = new TestInstallStorage(); foreach ($default_config_storage->listAll() as $config_name) { - // @todo: remove once migration (https://drupal.org/node/2183957) schemas - // are in. - if (strpos($config_name, 'migrate.migration') === 0) { - continue; - } - // Skip files provided by the config_schema_test module since that module // is explicitly for testing schema. if (strpos($config_name, 'config_schema_test') === 0) { diff --git a/core/modules/migrate/config/schema/migrate.data_types.schema.yml b/core/modules/migrate/config/schema/migrate.data_types.schema.yml new file mode 100644 index 0000000000000000000000000000000000000000..efdee08ca772c0e6288c731479f3eeb3f73337c9 --- /dev/null +++ b/core/modules/migrate/config/schema/migrate.data_types.schema.yml @@ -0,0 +1,20 @@ +# Basic data types for Migrate. + +migrate_plugin: + type: mapping + mapping: + plugin: + type: string + label: 'Plugin' + +migrate_destination: + type: migrate_plugin + label: 'Destination' + +migrate_source: + type: migrate_plugin + label: 'Source' + +migrate_load: + type: migrate_plugin + label: 'Load' diff --git a/core/modules/migrate/config/schema/migrate.destination.schema.yml b/core/modules/migrate/config/schema/migrate.destination.schema.yml new file mode 100644 index 0000000000000000000000000000000000000000..97cf48c3e716d90ad1396373bfe6b4c4b2be9dd0 --- /dev/null +++ b/core/modules/migrate/config/schema/migrate.destination.schema.yml @@ -0,0 +1,29 @@ +# Schema for the migrate destination plugins. + +migrate.destination.*: + type: migrate_destination + label: 'Default destination' + +migrate.destination.config: + type: migrate_destination + label: 'Config' + mapping: + config_name: + type: string + label: 'Configuration name' + +"migrate.destination.entity:user": + type: migrate_destination + label: 'User' + mapping: + md5_passwords: + type: boolean + label: 'Passwords' + +"migrate.destination.entity:file": + type: migrate_destination + label: 'Picture' + mapping: + source_path_property: + type: string + label: 'Source path' diff --git a/core/modules/migrate/config/schema/migrate.load.schema.yml b/core/modules/migrate/config/schema/migrate.load.schema.yml new file mode 100644 index 0000000000000000000000000000000000000000..aab94691cae6f6de59b41602189c4f6c50c52af2 --- /dev/null +++ b/core/modules/migrate/config/schema/migrate.load.schema.yml @@ -0,0 +1,21 @@ +# Schema for the migrate load plugins. + +migrate.load.*: + type: migrate_load + label: 'Default load' + +migrate.load.drupal_entity: + type: migrate_load + label: 'Default source' + mapping: + bundle_migration: + type: string + label: 'Bundle migration' + +migrate.load.d6_term_node: + type: migrate_load + label: 'Default source' + mapping: + bundle_migration: + type: string + label: 'Bundle migration' diff --git a/core/modules/migrate/config/schema/migrate.schema.yml b/core/modules/migrate/config/schema/migrate.schema.yml new file mode 100644 index 0000000000000000000000000000000000000000..cdca049a7f1b8657e7cb3cc07007d4a7e6b998d1 --- /dev/null +++ b/core/modules/migrate/config/schema/migrate.schema.yml @@ -0,0 +1,40 @@ +# Schema for the configuration files of the Migrate module. + +migrate.migration.*: + type: mapping + label: 'Migration' + mapping: + id: + type: string + lable: 'ID' + label: + type: label + label: 'Label' + load: + type: migrate.load.[plugin] + label: 'Source' + source: + type: migrate.source.[plugin] + label: 'Source' + process: + type: ignore + label: 'Process' + destination: + type: migrate.destination.[plugin] + label: 'Destination' + 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' diff --git a/core/modules/migrate/config/schema/migrate.source.schema.yml b/core/modules/migrate/config/schema/migrate.source.schema.yml new file mode 100644 index 0000000000000000000000000000000000000000..b0ff9e76ca9c390410972084dfdc2519f4e0382e --- /dev/null +++ b/core/modules/migrate/config/schema/migrate.source.schema.yml @@ -0,0 +1,388 @@ +# Schema for the migrate source plugins. + +migrate.source.*: + type: migrate_source + label: 'Default source' + +migrate.source.variable: + type: migrate_source + label: 'Variable' + mapping: + variables: + type: sequence + label: 'Variables' + sequence: + - type: string + label: 'Variable' + constants: + type: mapping + label: 'Constants' + mapping: + entity_type: + type: string + label: 'Entity type' + id: + type: string + label: 'ID' + label: + type: label + label: 'Label' + description: + type: text + label: 'Description' + path: + type: string + label: 'Path' + plugin: + type: string + label: 'Plugin' + +migrate.source.d6_comment: + type: migrate_source + label: 'Drupal 6 book' + mapping: + constants: + type: mapping + label: 'Constants' + mapping: + field_id: + type: string + label: 'Field ID' + entity_type: + type: string + label: 'Entity type' + +migrate.source.d6_comment_variable: + type: migrate_source + label: 'Drupal 6 book' + mapping: + constants: + type: mapping + label: 'Constants' + mapping: + entity_type: + type: string + label: 'Entity type' + field_name: + type: string + label: 'Entity type' + view_mode: + type: string + label: 'Entity type' + options: + type: sequence + label: 'Options' + sequence: + - type: string + label: 'Option' + type: + type: string + label: 'Type' + id: + type: string + label: 'ID' + name: + type: label + label: 'Name' + +migrate.source.d6_comment: + type: migrate_source + label: 'Drupal 6 comment' + mapping: + constants: + type: mapping + label: 'Constants' + mapping: + field_name: + type: string + label: 'Field name' + comment_type: + type: string + label: 'Comment type' + entity_type: + type: string + label: 'Entity type' + +migrate.source.d6_box: + type: migrate_source + label: 'Drupal 6 box' + mapping: + constants: + type: mapping + label: 'Constants' + mapping: + type: + type: string + label: 'Type' + +migrate.source.d6_taxonomy_vocabulary: + type: migrate_source + label: 'Drupal 6 field instance form display' + mapping: + constants: + type: migrate_entity_constant + label: 'Constants' + +migrate.source.d6_field_instance_per_form_display: + type: migrate_source + label: 'Drupal 6 field instance form display' + mapping: + constants: + type: migrate_entity_constant + label: 'Constants' + +migrate.source.d6_taxonomy_vocabulary_per_type: + type: migrate_source + label: 'Drupal 6 field instance form display' + mapping: + constants: + type: migrate_entity_constant + label: 'Constants' + +migrate.source.d6_taxonomy_vocabulary_per_type: + type: migrate_source + label: 'Drupal 6 field instance form display' + mapping: + constants: + type: migrate_entity_constant + label: 'Constants' + +migrate.source.d6_field: + type: migrate_source + label: 'Drupal 6 box' + mapping: + constants: + type: migrate_entity_constant + label: 'Constants' + +migrate.source.variable_multirow: + type: migrate_source + label: 'Drupal 6 box' + mapping: + variables: + type: sequence + label: 'Variables' + sequence: + - type: string + label: 'Variable' + +migrate.source.d6_comment_variable: + type: migrate_source + label: 'Drupal 6 comment variable' + mapping: + constants: + type: migrate_entity_constant + label: 'Constants' + +migrate.source.d6_contact_settings: + type: migrate_source + label: 'Drupal 6 contact settings' + mapping: + variables: + type: sequence + label: 'Variables' + sequence: + - type: string + label: 'Variable' + +migrate.source.d6_view_mode: + type: migrate_source + label: 'Drupal 6 view mode' + mapping: + constants: + type: mapping + label: 'Constants' + mapping: + targetEntityType: + type: string + label: 'Target entity type' + status: + type: boolean + label: 'Status' + +migrate.source.d6_profile_field: + type: migrate_source + label: 'Drupal 6 profile field' + mapping: + constants: + type: migrate_entity_constant + label: 'Constants' + +migrate.source.d6_field_formatter_settings: + type: migrate_source + label: 'Drupal 6 field formatter settings' + mapping: + constants: + type: migrate_entity_constant + label: 'Constants' + +migrate.source.d6_node_type: + type: migrate_source + label: 'Drupal 6 node type' + mapping: + constants: + type: mapping + label: 'Constants' + mapping: + preview: + type: integer + label: 'Preview' + create_body: + type: boolean + label: 'create body' + +migrate.source.d6_upload_instance: + type: migrate_source + label: 'Drupal 6 upload form display' + mapping: + constants: + type: migrate_entity_constant + label: 'Constants' + +migrate.source.d6_field_instance: + type: migrate_source + label: 'Drupal 6 field instance' + mapping: + constants: + type: migrate_entity_constant + label: 'Constants' + +migrate.source.d6_field_instance_per_view_mode: + type: migrate_source + label: 'Drupal 6 field formatter' + mapping: + constants: + type: migrate_entity_constant + label: 'Constants' + +migrate.source.empty: + type: migrate_source + label: 'Drupal 6 field formatter' + mapping: + provider: + type: string + label: 'Provider' + constants: + type: mapping + label: 'Constants' + mapping: + entity_type: + type: string + label: 'Entity type' + type: + type: string + label: 'Type' + name: + type: string + label: 'Name' + cardinality: + type: integer + label: 'Cardinality' + display_field: + type: boolean + label: 'Display field' + +migrate.source.d6_user_picture_file: + type: migrate_source + label: 'Drupal 6 user picure display' + mapping: + constants: + type: mapping + label: 'Constant' + mapping: + is_public: + type: boolean + label: 'Public' + +migrate.source.d6_user_picture_instance: + type: migrate_source + label: 'Drupal 6 user picure display' + mapping: + provider: + type: string + label: 'Provider' + constants: + type: migrate_entity_constant + label: 'Constants' + +migrate_entity_constant: + type: mapping + mapping: + entity_type: + type: string + label: 'Entity type' + bundle: + type: string + label: 'Bundle' + label: + type: label + label: 'Label' + id: + type: string + label: 'ID' + view_mode: + type: string + label: 'View mode' + form_mode: + type: string + label: 'Form mode' + field_name: + type: string + label: 'Field name' + empty: + type: sequence + label: 'Empty' + sequence: + - type: string + label: 'Empty' + name: + type: string + label: 'Name' + required: + type: boolean + label: 'Required' + type: + type: string + label: 'Type' + cardinality: + type: integer + label: 'Cardinality' + parent: + type: integer + label: 'Parent' + langcode: + type: string + label: 'Type' + third_party_settings: + type: sequence + label: 'Settings' + sequence: + - type: ignore + label: 'Settings' + settings: + type: sequence + label: 'Settings' + sequence: + - type: ignore + label: 'Settings' + options: + type: mapping + label: 'Options' + mapping: + label: + type: string + label: 'label' + type: + type: string + label: 'Type' + weight: + type: integer + label: 'Weight' + settings: + type: sequence + label: 'Settings' + sequence: + - type: string + label: 'Settings' + + diff --git a/core/modules/migrate_drupal/config/install/migrate.migration.d6_contact_settings.yml b/core/modules/migrate_drupal/config/install/migrate.migration.d6_contact_settings.yml index 65b0082419dae1ee5092c33295e079c4d905f58f..e45dde1e5b4fbe306d8f5f4b7671d36565ac4c49 100644 --- a/core/modules/migrate_drupal/config/install/migrate.migration.d6_contact_settings.yml +++ b/core/modules/migrate_drupal/config/install/migrate.migration.d6_contact_settings.yml @@ -15,5 +15,6 @@ process: destination: plugin: config config_name: contact.settings -dependencies: - - d6_contact_category +migration_dependencies: + required: + - d6_contact_category diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateActionConfigSchemaTest.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateActionConfigSchemaTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a0d27920b350c81b59643466ea48c6c278a1ea19 --- /dev/null +++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateActionConfigSchemaTest.php @@ -0,0 +1,56 @@ +<?php + +/** + * @file + * Contains \Drupal\migrate_drupal\Tests\d6\MigrateActionConfigSchemaTest. + */ + +namespace Drupal\migrate_drupal\Tests\d6; + +use Drupal\migrate\MigrateExecutable; + +/** + * Tests the language config schema. + */ +class MigrateActionConfigSchemaTest extends MigrateConfigSchemaBase { + /** + * Modules to enable. + * + * @var array + */ + public static $modules = array('action'); + + /** + * {@inheritdoc} + */ + public static function getInfo() { + return array( + 'name' => 'Migrate action configuration schema', + 'description' => 'Tests the configuration schema of action module', + 'group' => 'Migrate Drupal', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + $migration = entity_load('migration', 'd6_action_settings'); + $dumps = array( + $this->getDumpDirectory() . '/Drupal6ActionSettings.php', + ); + $this->prepare($migration, $dumps); + $executable = new MigrateExecutable($migration, $this); + $executable->import(); + } + + /** + * Tests migration of action variables to action.settings.yml. + */ + public function testActionConfigSchema() { + $config_data = \Drupal::config('action.settings')->get(); + $this->assertConfigSchema(\Drupal::service('config.typed'), 'action.settings', $config_data); + } + +} diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateConfigSchemaBase.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateConfigSchemaBase.php new file mode 100644 index 0000000000000000000000000000000000000000..7af563f0a10f5aa985dbb8c9b0740494f4bbe8d1 --- /dev/null +++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateConfigSchemaBase.php @@ -0,0 +1,145 @@ +<?php + +/** + * @file + * Contains \Drupal\migrate_drupal\Tests\MigrateDrupalTestBase. + */ + +namespace Drupal\migrate_drupal\Tests\d6; + +use Drupal\Core\Config\Schema\ArrayElement; +use Drupal\Core\Config\TypedConfigManagerInterface; +use Drupal\Core\TypedData\Type\BooleanInterface; +use Drupal\Core\TypedData\Type\StringInterface; +use Drupal\Component\Utility\String; +use Drupal\Core\Config\Schema\SchemaIncompleteException; +use Drupal\Core\TypedData\PrimitiveInterface; +use Drupal\Core\TypedData\Type\FloatInterface; +use Drupal\Core\TypedData\Type\IntegerInterface; +use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase; + +/** + * Base class for Drupal migration tests. + */ +abstract class MigrateConfigSchemaBase extends MigrateDrupalTestBase { + + + /** + * The config schema wrapper object for the configuration object under test. + * + * @var \Drupal\Core\Config\Schema\Element + */ + protected $schema; + + /** + * The configuration object name under test. + * + * @var string + */ + protected $configName; + + /** + * Global state for whether the config has a valid schema. + * + * @var boolean + */ + protected $configPass; + + /** + * Asserts the TypedConfigManager has a valid schema for the configuration. + * + * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config + * The TypedConfigManager. + * @param string $config_name + * The configuration name. + * @param array $config_data + * The configuration data. + */ + public function assertConfigSchema(TypedConfigManagerInterface $typed_config, $config_name, $config_data) { + $this->configName = $config_name; + if (!$typed_config->hasConfigSchema($config_name)) { + $this->fail(String::format('No schema for !config_name', array('!config_name' => $config_name))); + return; + } + $definition = $typed_config->getDefinition($config_name); + $data_definition = $typed_config->buildDataDefinition($definition, $config_data); + $this->schema = $typed_config->create($data_definition, $config_data); + $this->configPass = TRUE; + foreach ($config_data as $key => $value) { + $this->checkValue($key, $value); + } + if ($this->configPass) { + $this->pass(String::format('Schema found for !config_name and values comply with schema.', array('!config_name' => $config_name))); + } + } + + /** + * Helper method to check data type. + * + * @param string $key + * A string of configuration key. + * @param mixed $value + * Value of given key. + * + * @return mixed + * Returns mixed value. + */ + protected function checkValue($key, $value) { + $element = FALSE; + try { + $element = $this->schema->get($key); + } + catch (SchemaIncompleteException $e) { + if (is_scalar($value) || $value === NULL) { + $this->fail("{$this->configName}:$key has no schema."); + } + } + // Do not check value if it is defined to be ignored. + if ($element && $element instanceof Ignore) { + return $value; + } + + if (is_scalar($value) || $value === NULL) { + $success = FALSE; + $type = gettype($value); + if ($element instanceof PrimitiveInterface) { + $success = + ($type == 'integer' && $element instanceof IntegerInterface) || + ($type == 'double' && $element instanceof FloatInterface) || + ($type == 'boolean' && $element instanceof BooleanInterface) || + ($type == 'string' && $element instanceof StringInterface) || + // Null values are allowed for all types. + ($value === NULL); + } + $class = get_class($element); + if (!$success) { + $this->fail("{$this->configName}:$key has the wrong schema. Variable type is $type and schema class is $class."); + } + } + else { + if (!$element instanceof ArrayElement) { + $this->fail("Non-scalar {$this->configName}:$key is not defined as an array type (such as mapping or sequence)."); + } + + // Go on processing so we can get errors on all levels. Any non-scalar + // value must be an array so cast to an array. + if (!is_array($value)) { + $value = (array) $value; + } + // Recurse into any nested keys. + foreach ($value as $nested_value_key => $nested_value) { + $value[$nested_value_key] = $this->checkValue($key . '.' . $nested_value_key, $nested_value); + } + } + return $value; + } + + /** + * {@inheritdoc} + */ + protected function fail($message = NULL, $group = 'Other') { + $this->configPass = FALSE; + return parent::fail($message, $group); + } + +}