Commit d5bb653b authored by webchick's avatar webchick

Issue #2183957 by vijaycs85, chx, Gábor Hojtsy: Provide configuration schema for Migration module.

parent 627470bc
......@@ -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) {
......
# 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'
# 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'
# 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'
# 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'
# 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'
......@@ -15,5 +15,6 @@ process:
destination:
plugin: config
config_name: contact.settings
dependencies:
- d6_contact_category
migration_dependencies:
required:
- d6_contact_category
<?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);
}
}
<?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;