Update to Drupal 8.2.4. For more information, see https://www.drupal.org/project/drupal/releases/8.2.4

This commit is contained in:
Pantheon Automation 2016-12-07 12:19:38 -08:00 committed by Greg Anderson
parent 0a95b8440e
commit 8544b60b39
284 changed files with 12980 additions and 3199 deletions

View file

@ -23,15 +23,18 @@ use Drupal\migrate\Row;
* means to load data into storage, while traditionally Drupal uses "load" to
* mean load data from storage into memory.
*
* Source, process, and destination phases are each provided by plugins.
* Source plugins extract data from a data source in "rows", containing
* "properties". Each row is handed off to one or more process plugins which
* transform the row's properties. After all the properties are processed, the
* resulting row is handed off to a destination plugin, which saves the data.
* In the source phase, a set of data, called the row, is retrieved from the
* data source, typically a database but it can be a CSV, JSON or XML file. The
* row is sent to the process phase where it is transformed as needed by the
* destination, or marked to be skipped. Processing can also determine that a
* stub needs to be created, for example, if a term has a parent term that does
* not yet exist. After processing the transformed row is passed to the
* destination phase where it is loaded (saved) into the Drupal 8 site.
*
* A source plugin, one or more process plugins, and a destination plugin are
* brought together to extract, transform, and load (in the ETL sense) a specific
* type of data by a migration plugin.
* The ETL process is configured by the migration plugin. The different phases:
* source, process, and destination are also plugins, and are managed by the
* Migration plugin. So there are four types of plugins in the migration
* process: migration, source, process and destination.
*
* @section sec_migrations Migration plugins
* Migration plugin definitions are stored in a module's 'migrations' directory.
@ -50,8 +53,8 @@ use Drupal\migrate\Row;
* with \Drupal\migrate\Annotation\MigrateSource annotation, and must be in
* namespace subdirectory Plugin\migrate\source under the namespace of the
* module that defines them. Migration source plugins are managed by the
* \Drupal\migrate\Plugin\MigratePluginManager class. Source plugin providers
* are determined by their and their parents namespaces.
* \Drupal\migrate\Plugin\MigrateSourcePluginManager class. Source plugin
* providers are determined by their and their parents namespaces.
*
* @section sec_process Process plugins
* Migration process plugins implement
@ -107,6 +110,29 @@ function hook_migrate_prepare_row(Row $row, MigrateSourceInterface $source, Migr
}
}
/**
* Allows altering the list of discovered migration plugins.
*
* Modules are able to alter specific migrations structures or even remove or
* append additional migrations to the discovery. For example, this
* implementation filters out Drupal 6 migrations from the discovered migration
* list. This is done by checking the migration tags.
*
* @param array[] $migrations
* An associative array of migrations keyed by migration ID. Each value is the
* migration array, obtained by decoding the migration YAML file and enriched
* with some meta information added during discovery phase, like migration
* 'class', 'provider' or '_discovered_file_path'.
*
* @ingroup migration
*/
function hook_migration_plugins_alter(array &$migrations) {
$migrations = array_filter($migrations, function (array $migration) {
$tags = isset($migration['migration_tags']) ? (array) $migration['migration_tags'] : [];
return !in_array('Drupal 6', $tags);
});
}
/**
* @} End of "addtogroup hooks".
*/

View file

@ -398,7 +398,7 @@ class MigrateExecutable implements MigrateExecutableInterface {
$value = NULL;
break;
}
$multiple = $multiple || $plugin->multiple();
$multiple = $plugin->multiple();
}
}
// No plugins or no value means do not set.

View file

@ -83,11 +83,8 @@ interface MigrateDestinationInterface extends PluginInspectionInterface {
* Derived classes must implement fields(), returning a list of available
* destination fields.
*
* @todo Review the cases where we need the Migration parameter, can we avoid
* that? To be resolved with https://www.drupal.org/node/2543568.
*
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
* (optional) The migration containing this destination. Defaults to NULL.
* Unused, will be removed before Drupal 9.0.x. Defaults to NULL.
*
* @return array
* - Keys: machine names of the fields

View file

@ -20,13 +20,6 @@ use Drupal\migrate\Plugin\Discovery\ProviderFilterDecorator;
*/
class MigrateSourcePluginManager extends MigratePluginManager {
/**
* The class loader.
*
* @var object
*/
protected $classLoader;
/**
* MigrateSourcePluginManager constructor.
*

View file

@ -0,0 +1,107 @@
<?php
namespace Drupal\migrate\Plugin\migrate\process;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
/**
* Builds an array based on the key and value configuration.
*
* The array_build plugin builds a single associative array by extracting keys
* and values from each array in the input value, which is expected to be an
* array of arrays. The keys of the returned array will be determined by the
* 'key' configuration option, and the values will be determined by the 'value'
* option.
*
* Available configuration keys
* - key: The key used to lookup a value in the source arrays to be used as
* a key in the destination array.
* - value: The key used to lookup a value in the source arrays to be used as
* a value in the destination array.
*
* Example:
*
* Consider the migration of language negotiation by domain.
* The source is an array of all the languages:
*
* @code
* languages: Array
* (
* [0] => Array
* (
* [language] => en
* ...
* [domain] => http://example.com
* )
* [1] => Array
* (
* [language] => fr
* ...
* [domain] => http://fr.example.com
* )
* ...
* @endcode
*
* The destination should be an array of all the domains keyed by their
* language code:
*
* @code
* domains: Array
* (
* [en] => http://example.com
* [fr] => http://fr.example.com
* ...
* @endcode
*
* The array_build process plugin would be used like this:
*
* @code
* process:
* domains:
* plugin: array_build
* key: language
* value: domain
* source: languages
* @endcode
*
* @see \Drupal\migrate\Plugin\MigrateProcessInterface
*
* @MigrateProcessPlugin(
* id = "array_build",
* handle_multiples = TRUE
* )
*/
class ArrayBuild extends ProcessPluginBase {
/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
$new_value = [];
foreach ((array) $value as $old_key => $old_value) {
// Checks that $old_value is an array.
if (!is_array($old_value)) {
throw new MigrateException("The input should be an array of arrays");
}
// Checks that the key exists.
if (!array_key_exists($this->configuration['key'], $old_value)) {
throw new MigrateException("The key '" . $this->configuration['key'] . "' does not exist");
}
// Checks that the value exists.
if (!array_key_exists($this->configuration['value'], $old_value)) {
throw new MigrateException("The key '" . $this->configuration['value'] . "' does not exist");
}
$new_value[$old_value[$this->configuration['key']]] = $old_value[$this->configuration['value']];
}
return $new_value;
}
}

View file

@ -10,6 +10,9 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Ensures value is not duplicated against an entity field.
*
* If the 'migrated' configuration value is true, an entity will only be
* considered a duplicate if it was migrated by the current migration.
*
* @link https://www.drupal.org/node/2135325 Online handbook documentation for dedupe_entity process plugin @endlink
*
* @MigrateProcessPlugin(
@ -25,11 +28,19 @@ class DedupeEntity extends DedupeBase implements ContainerFactoryPluginInterface
*/
protected $entityQueryFactory;
/**
* The current migration.
*
* @var \Drupal\migrate\Plugin\MigrationInterface
*/
protected $migration;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, QueryFactory $entity_query_factory) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->migration = $migration;
$this->entityQueryFactory = $entity_query_factory;
}
@ -51,12 +62,25 @@ class DedupeEntity extends DedupeBase implements ContainerFactoryPluginInterface
*/
protected function exists($value) {
// Plugins are cached so for every run we need a new query object.
return $this
$query = $this
->entityQueryFactory
->get($this->configuration['entity_type'], 'AND')
->condition($this->configuration['field'], $value)
->count()
->execute();
->condition($this->configuration['field'], $value);
if (!empty($this->configuration['migrated'])) {
// Check if each entity is in the ID map.
$idMap = $this->migration->getIdMap();
foreach ($query->execute() as $id) {
$dest_id_values[$this->configuration['field']] = $id;
if ($idMap->lookupSourceID($dest_id_values)) {
return TRUE;
}
}
return FALSE;
}
else {
// Just check if any such entity exists.
return $query->count()->execute();
}
}
}

View file

@ -38,6 +38,13 @@ class Migration extends ProcessPluginBase implements ContainerFactoryPluginInter
*/
protected $migrationPluginManager;
/**
* The migration to be executed.
*
* @var \Drupal\migrate\Plugin\MigrationInterface
*/
protected $migration;
/**
* {@inheritdoc}
*/
@ -70,9 +77,7 @@ class Migration extends ProcessPluginBase implements ContainerFactoryPluginInter
if (!is_array($migration_ids)) {
$migration_ids = array($migration_ids);
}
$scalar = FALSE;
if (!is_array($value)) {
$scalar = TRUE;
$value = array($value);
}
$this->skipOnEmpty($value);
@ -145,10 +150,8 @@ class Migration extends ProcessPluginBase implements ContainerFactoryPluginInter
}
}
if ($destination_ids) {
if ($scalar) {
if (count($destination_ids) == 1) {
return reset($destination_ids);
}
if (count($destination_ids) == 1) {
return reset($destination_ids);
}
else {
return $destination_ids;

View file

@ -3,10 +3,10 @@
namespace Drupal\migrate\Plugin\migrate\process;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\Core\Path\PathValidatorInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
@ -55,7 +55,14 @@ class Route extends ProcessPluginBase implements ContainerFactoryPluginInterface
* Set the destination route information based on the source link_path.
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
list($link_path, $options) = $value;
if (is_string($value)) {
$link_path = $value;
$options = [];
}
else {
list($link_path, $options) = $value;
}
$extracted = $this->pathValidator->getUrlIfValidWithoutAccessCheck($link_path);
$route = array();

View file

@ -60,7 +60,7 @@ class DownloadTest extends FileTestBase {
/**
* Tests that an exception is thrown if the destination URI is not writable.
*/
public function testWriteProectedDestination() {
public function testWriteProtectedDestination() {
// Create a pre-existing file at the destination, to test overwrite behavior.
$destination_uri = $this->createUri('not-writable.txt');

View file

@ -0,0 +1,138 @@
<?php
namespace Drupal\Tests\migrate\Kernel\process;
use Drupal\KernelTests\KernelTestBase;
use Drupal\migrate\MigrateExecutable;
use Drupal\migrate\MigrateMessage;
use Drupal\migrate\Plugin\MigrationInterface;
/**
* Tests process pipelines with scalar and multiple values handling.
*
* @group migrate
*/
class HandleMultiplesTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['migrate'];
/**
* Provides the test migration definition.
*
* @return array
*/
public function getDefinition() {
return [
'source' => [
'plugin' => 'embedded_data',
'data_rows' => [],
'ids' => [
'id' => ['type' => 'string'],
],
],
'process' => [
// Process pipeline for testing values from string to array to string.
'first' => [
// Expects a string and returns an array.
[
'plugin' => 'explode',
'source' => 'scalar',
'delimiter' => '/',
],
// Expects an array and returns a string.
[
'plugin' => 'extract',
'index' => [1],
],
// Expects a string and returns a string.
[
'plugin' => 'callback',
'callable' => 'strtoupper',
],
],
// Process pipeline for testing values from array to string to array.
'second' => [
// Expects an array and returns a string.
[
'plugin' => 'extract',
'source' => 'multiple',
'index' => [1],
],
// Expects a string and returns a string.
[
'plugin' => 'callback',
'callable' => 'strtoupper',
],
// Expects a string and returns an array.
[
'plugin' => 'explode',
'delimiter' => '/',
],
],
],
'destination' => [
'plugin' => 'config',
'config_name' => 'migrate_test.settings',
],
];
}
/**
* Tests process pipelines with scalar and multiple values handling.
*
* @dataProvider scalarAndMultipleValuesProviderSource
*
* @param array $source_data
* @param array $expected_data
*/
public function testScalarAndMultipleValues(array $source_data, array $expected_data) {
$definition = $this->getDefinition();
$definition['source']['data_rows'] = [$source_data];
$migration = \Drupal::service('plugin.manager.migration')->createStubMigration($definition);
$executable = new MigrateExecutable($migration, new MigrateMessage());
$result = $executable->import();
// Migration needs to succeed before further assertions are made.
$this->assertSame(MigrationInterface::RESULT_COMPLETED, $result);
// Compare with expected data.
$this->assertEquals($expected_data, \Drupal::config('migrate_test.settings')->get());
}
/**
* Provides the source data with scalar and multiple values.
*
* @return array
*/
public function scalarAndMultipleValuesProviderSource() {
return [
[
'source_data' => [
'id' => '1',
// Source value for the first pipeline.
'scalar' => 'foo/bar',
// Source value for the second pipeline.
'multiple' => [
'foo',
'bar/baz',
],
],
'expected_data' => [
// Expected value from the first pipeline.
'first' => 'BAR',
// Expected value from the second pipeline.
'second' => [
'BAR',
'BAZ',
],
],
],
];
}
}

View file

@ -0,0 +1,278 @@
<?php
namespace Drupal\Tests\migrate\Kernel\process;
use Drupal\KernelTests\KernelTestBase;
use Drupal\migrate\Plugin\migrate\process\Route;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Row;
use Drupal\user\Entity\User;
/**
* Tests the route process plugin.
*
* @coversDefaultClass \Drupal\migrate\Plugin\migrate\process\Route
*
* @group migrate
*/
class RouteTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'system'];
/**
* Tests Route plugin based on providerTestRoute() values.
*
* @param mixed $value
* Input value for the Route process plugin.
* @param array $expected
* The expected results from the Route transform process.
*
* @dataProvider providerTestRoute
*/
public function testRoute($value, $expected) {
$actual = $this->doTransform($value);
$this->assertSame($expected, $actual);
}
/**
* Data provider for testRoute().
*
* @return array
* An array of arrays, where the first element is the input to the Route
* process plugin, and the second is the expected results.
*/
public function providerTestRoute() {
// Internal link tests.
// Valid link path and options.
$values[0] = [
'user/login',
[
'attributes' => [
'title' => 'Test menu link 1',
],
],
];
$expected[0] = [
'route_name' => 'user.login',
'route_parameters' => [],
'options' => [
'query' => [],
'attributes' => [
'title' => 'Test menu link 1',
],
],
'url' => NULL,
];
// Valid link path and empty options.
$values[1] = [
'user/login',
[],
];
$expected[1] = [
'route_name' => 'user.login',
'route_parameters' => [],
'options' => [
'query' => [],
],
'url' => NULL,
];
// Valid link path and no options.
$values[2] = 'user/login';
$expected[2] = [
'route_name' => 'user.login',
'route_parameters' => [],
'options' => [
'query' => [],
],
'url' => NULL,
];
// Invalid link path.
$values[3] = 'users';
$expected[3] = [];
// Valid link path with parameter.
$values[4] = [
'system/timezone/nzdt',
[
'attributes' => [
'title' => 'Show NZDT',
],
],
];
$expected[4] = [
'route_name' => 'system.timezone',
'route_parameters' => [
'abbreviation' => 'nzdt',
'offset' => -1,
'is_daylight_saving_time' => NULL,
],
'options' => [
'query' => [],
'attributes' => [
'title' => 'Show NZDT',
],
],
'url' => NULL,
];
// External link tests.
// Valid external link path and options.
$values[5] = [
'https://www.drupal.org',
[
'attributes' => [
'title' => 'Drupal',
],
],
];
$expected[5] = [
'route_name' => NULL,
'route_parameters' => [],
'options' => [
'attributes' => [
'title' => 'Drupal',
],
],
'url' => 'https://www.drupal.org',
];
// Valid external link path and options.
$values[6] = [
'https://www.drupal.org/user/1/edit?pass-reset-token=QgtDKcRV4e4fjg6v2HTa6CbWx-XzMZ5XBZTufinqsM73qIhscIuU_BjZ6J2tv4dQI6N50ZJOag',
[
'attributes' => [
'title' => 'Drupal password reset',
],
],
];
$expected[6] = [
'route_name' => NULL,
'route_parameters' => [],
'options' => [
'attributes' => [
'title' => 'Drupal password reset',
],
],
'url' => 'https://www.drupal.org/user/1/edit?pass-reset-token=QgtDKcRV4e4fjg6v2HTa6CbWx-XzMZ5XBZTufinqsM73qIhscIuU_BjZ6J2tv4dQI6N50ZJOag',
];
return [
// Test data for internal paths.
// Test with valid link path and options.
[$values[0], $expected[0]],
// Test with valid link path and empty options.
[$values[1], $expected[1]],
// Test with valid link path and no options.
[$values[2], $expected[2]],
// Test with Invalid link path.
[$values[3], $expected[3]],
// Test with Valid link path with query options and parameters.
[$values[4], $expected[4]],
// Test data for external paths.
// Test with external link path and options.
[$values[5], $expected[5]],
// Test with valid link path and query options.
[$values[6], $expected[6]],
];
}
/**
* Tests Route plugin based on providerTestRoute() values.
*
* @param mixed $value
* Input value for the Route process plugin.
* @param array $expected
* The expected results from the Route transform process.
*
* @dataProvider providerTestRouteWithParamQuery
*/
public function testRouteWithParamQuery($value, $expected) {
$this->installSchema('system', ['sequences']);
$this->installEntitySchema('user');
$this->installConfig(['user']);
// Create a user so that user/1/edit is a valid path.
$adminUser = User::create([
'name' => $this->randomMachineName(),
]);
$adminUser->save();
$actual = $this->doTransform($value);
$this->assertSame($expected, $actual);
}
/**
* Data provider for testRouteWithParamQuery().
*
* @return array
* An array of arrays, where the first element is the input to the Route
* process plugin, and the second is the expected results.
*/
public function providerTestRouteWithParamQuery() {
$values = [];
$expected = [];
// Valid link path with query options and parameters.
$values[0] = [
'user/1/edit',
[
'attributes' => [
'title' => 'Edit admin',
],
'query' => [
'destination' => '/admin/people',
],
],
];
$expected[0] = [
'route_name' => 'entity.user.edit_form',
'route_parameters' => [
'user' => '1',
],
'options' => [
'attributes' => [
'title' => 'Edit admin',
],
'query' => [
'destination' => '/admin/people',
],
],
'url' => NULL,
];
return [
// Test with valid link path with parameters and options.
[$values[0], $expected[0]],
];
}
/**
* Transforms link path data to a route.
*
* @param array|string $value
* Source link path information.
*
* @return array $actual
* The route information based on the source link_path.
*/
protected function doTransform($value) {
// Rebuild the routes.
$this->container->get('router.builder')->rebuild();
$pathValidator = $this->container->get('path.validator');
$row = new Row();
$migration = $this->prophesize(MigrationInterface::class)->reveal();
$executable = $this->prophesize(MigrateExecutableInterface::class)->reveal();
$plugin = new Route([], 'route', [], $migration, $pathValidator);
$actual = $plugin->transform($value, $executable, $row, 'destinationproperty');
return $actual;
}
}

View file

@ -0,0 +1,82 @@
<?php
namespace Drupal\Tests\migrate\Unit\process;
use Drupal\migrate\MigrateException;
use Drupal\migrate\Plugin\migrate\process\ArrayBuild;
/**
* @coversDefaultClass \Drupal\migrate\Plugin\migrate\process\ArrayBuild
* @group migrate
*/
class ArrayBuildTest extends MigrateProcessTestCase {
/**
* {@inheritdoc}
*/
protected function setUp() {
$configuration = [
'key' => 'foo',
'value' => 'bar',
];
$this->plugin = new ArrayBuild($configuration, 'map', []);
parent::setUp();
}
/**
* Tests successful transformation.
*/
public function testTransform() {
$source = [
['foo' => 'Foo', 'bar' => 'Bar'],
['foo' => 'foo bar', 'bar' => 'bar foo'],
];
$expected = [
'Foo' => 'Bar',
'foo bar' => 'bar foo',
];
$value = $this->plugin->transform($source, $this->migrateExecutable, $this->row, 'destinationproperty');
$this->assertSame($value, $expected);
}
/**
* Tests non-existent key for the key configuration.
*/
public function testNonExistentKey() {
$source = [
['bar' => 'foo'],
];
$this->setExpectedException(MigrateException::class, "The key 'foo' does not exist");
$this->plugin->transform($source, $this->migrateExecutable, $this->row, 'destinationproperty');
}
/**
* Tests non-existent key for the value configuration.
*/
public function testNonExistentValue() {
$source = [
['foo' => 'bar'],
];
$this->setExpectedException(MigrateException::class, "The key 'bar' does not exist");
$this->plugin->transform($source, $this->migrateExecutable, $this->row, 'destinationproperty');
}
/**
* Tests one-dimensional array input.
*/
public function testOneDimensionalArrayInput() {
$source = ['foo' => 'bar'];
$this->setExpectedException(MigrateException::class, 'The input should be an array of arrays');
$this->plugin->transform($source, $this->migrateExecutable, $this->row, 'destinationproperty');
}
/**
* Tests string input.
*/
public function testStringInput() {
$source = 'foo';
$this->setExpectedException(MigrateException::class, 'The input should be an array of arrays');
$this->plugin->transform($source, $this->migrateExecutable, $this->row, 'destinationproperty');
}
}

View file

@ -2,6 +2,7 @@
namespace Drupal\Tests\migrate\Unit\process;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\migrate\Plugin\migrate\process\DedupeEntity;
use Drupal\Component\Utility\Unicode;
@ -161,4 +162,47 @@ class DedupeEntityTest extends MigrateProcessTestCase {
->will($this->returnCallback(function () use (&$count) { return $count--;}));
}
/**
* Test deduplicating only migrated entities.
*/
public function testDedupeMigrated() {
$configuration = array(
'entity_type' => 'test_entity_type',
'field' => 'test_field',
'migrated' => TRUE,
);
$plugin = new DedupeEntity($configuration, 'dedupe_entity', array(), $this->getMigration(), $this->entityQueryFactory);
// Setup the entityQuery used in DedupeEntity::exists. The map, $map, is
// an array consisting of the four input parameters to the query condition
// method and then the query to return. Both 'forum' and
// 'test_vocab' are existing entities. There is no 'test_vocab1'.
$map = [];
foreach (['forums', 'test_vocab', 'test_vocab1'] as $id) {
$query = $this->prophesize(QueryInterface::class);
$query->willBeConstructedWith([]);
$query->execute()->willReturn($id === 'test_vocab1' ? [] : [$id]);
$map[] = ['test_field', $id, NULL, NULL, $query->reveal()];
}
$this->entityQuery
->method('condition')
->will($this->returnValueMap($map));
// Entity 'forums' is pre-existing, entity 'test_vocab' was migrated.
$this->idMap
->method('lookupSourceID')
->will($this->returnValueMap([
[['test_field' => 'forums'], FALSE],
[['test_field' => 'test_vocab'], ['source_id' => 42]],
]));
// Existing entity 'forums' was not migrated, it should not be deduplicated.
$actual = $plugin->transform('forums', $this->migrateExecutable, $this->row, 'testproperty');
$this->assertEquals('forums', $actual, 'Pre-existing name is re-used');
// Entity 'test_vocab' was migrated, should be deduplicated.
$actual = $plugin->transform('test_vocab', $this->migrateExecutable, $this->row, 'testproperty');
$this->assertEquals('test_vocab1', $actual, 'Migrated name is deduplicated');
}
}

View file

@ -89,7 +89,7 @@ class MigrationTest extends MigrateProcessTestCase {
/**
* Tests that processing is skipped when the input value is empty.
*
*
* @expectedException \Drupal\migrate\MigrateSkipProcessException
*/
public function testSkipOnEmpty() {
@ -107,8 +107,19 @@ class MigrationTest extends MigrateProcessTestCase {
/**
* Tests a successful lookup.
*
* @dataProvider successfulLookupDataProvider
*
* @param array $source_id_values
* The source id(s) of the migration map.
* @param array $destination_id_values
* The destination id(s) of the migration map.
* @param string|array $source_value
* The source value(s) for the migration process plugin.
* @param string|array $expected_value
* The expected value(s) of the migration process plugin.
*/
public function testSuccessfulLookup() {
public function testSuccessfulLookup($source_id_values, $destination_id_values, $source_value, $expected_value) {
$migration_plugin = $this->prophesize(MigrationInterface::class);
$migration_plugin_manager = $this->prophesize(MigrationPluginManagerInterface::class);
$process_plugin_manager = $this->prophesize(MigratePluginManager::class);
@ -119,7 +130,7 @@ class MigrationTest extends MigrateProcessTestCase {
$migration_plugin->id()->willReturn(uniqid());
$id_map = $this->prophesize(MigrateIdMapInterface::class);
$id_map->lookupDestinationId([1])->willReturn([3]);
$id_map->lookupDestinationId($source_id_values)->willReturn($destination_id_values);
$migration_plugin->getIdMap()->willReturn($id_map->reveal());
$migration_plugin_manager->createInstances(['foobaz'])
@ -131,7 +142,61 @@ class MigrationTest extends MigrateProcessTestCase {
->willReturn([$migration_plugin->reveal()]);
$migration = new Migration($configuration, 'migration', [], $migration_plugin->reveal(), $migration_plugin_manager->reveal(), $process_plugin_manager->reveal());
$this->assertSame(3, $migration->transform(1, $this->migrateExecutable, $this->row, 'foo'));
$this->assertSame($expected_value, $migration->transform($source_value, $this->migrateExecutable, $this->row, 'foo'));
}
/**
* Provides data for the successful lookup test.
*
* @return array
*/
public function successfulLookupDataProvider() {
return [
// Test data for scalar to scalar.
[
// Source ID of the migration map.
[1],
// Destination ID of the migration map.
[3],
// Input value for the migration plugin.
1,
// Expected output value of the migration plugin.
3,
],
// Test data for scalar to array.
[
// Source ID of the migration map.
[1],
// Destination IDs of the migration map.
[3, 'foo'],
// Input value for the migration plugin.
1,
// Expected output values of the migration plugin.
[3, 'foo'],
],
// Test data for array to scalar.
[
// Source IDs of the migration map.
[1, 3],
// Destination ID of the migration map.
['foo'],
// Input values for the migration plugin.
[1, 3],
// Expected output value of the migration plugin.
'foo',
],
// Test data for array to array.
[
// Source IDs of the migration map.
[1, 3],
// Destination IDs of the migration map.
[3, 'foo'],
// Input values for the migration plugin.
[1, 3],
// Expected output values of the migration plugin.
[3, 'foo'],
],
];
}
}