Update to Drupal 8.0.0 beta 14. For more information, see https://drupal.org/node/2544542

This commit is contained in:
Pantheon Automation 2015-08-27 12:03:05 -07:00 committed by Greg Anderson
parent 3b2511d96d
commit 81ccda77eb
2155 changed files with 54307 additions and 46870 deletions

View file

@ -5,6 +5,9 @@ services:
- { name: cache.bin }
factory: cache_factory:get
arguments: [migrate]
migrate.template_storage:
class: Drupal\migrate\MigrateTemplateStorage
arguments: ['@module_handler']
plugin.manager.migrate.source:
class: Drupal\migrate\Plugin\MigratePluginManager
arguments: [source, '@container.namespaces', '@cache.discovery', '@module_handler', 'Drupal\migrate\Annotation\MigrateSource']

View file

@ -7,7 +7,6 @@
namespace Drupal\migrate\Entity;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\migrate\Exception\RequirementsException;
use Drupal\migrate\MigrateException;
@ -381,7 +380,7 @@ class Migration extends ConfigEntityBase implements MigrationInterface, Requirem
}
}
if ($missing_migrations) {
throw new RequirementsException(SafeMarkup::format('Missing migrations @requirements.', ['@requirements' => implode(', ', $missing_migrations)]), ['requirements' => $missing_migrations]);
throw new RequirementsException('Missing migrations ' . implode(', ', $missing_migrations) . '.', ['requirements' => $missing_migrations]);
}
}

View file

@ -0,0 +1,102 @@
<?php
/**
* @file
* Contains \Drupal\migrate\MigrateTemplateStorage.
*/
namespace Drupal\migrate;
use Drupal\Component\Serialization\Yaml;
use Drupal\Core\Extension\ModuleHandlerInterface;
/**
* Storage to access migration template configuration in enabled extensions.
*/
class MigrateTemplateStorage {
/**
* Extension sub-directory containing default configuration for migrations.
*/
const MIGRATION_TEMPLATE_DIRECTORY = 'migration_templates';
/**
* Template subdirectory.
*
* @var string
*/
protected $directory;
/**
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* {@inheritdoc}
*/
public function __construct(ModuleHandlerInterface $module_handler, $directory = self::MIGRATION_TEMPLATE_DIRECTORY) {
$this->moduleHandler = $module_handler;
$this->directory = $directory;
}
/**
* Find all migration templates with the specified tag.
*
* @param $tag
* The tag to match.
*
* @return array
* Any templates (parsed YAML config) that matched, keyed by the ID.
*/
public function findTemplatesByTag($tag) {
$templates = $this->getAllTemplates();
$matched_templates = [];
foreach ($templates as $template_name => $template) {
if (!empty($template['migration_tags'])) {
if (in_array($tag, $template['migration_tags'])) {
$matched_templates[$template_name] = $template;
}
}
}
return $matched_templates;
}
/**
* Retrieve a template given a specific name.
*
* @param string $name
* A migration template name.
*
* @return NULL|array
* A parsed migration template, or NULL if it doesn't exist.
*/
public function getTemplateByName($name) {
$templates = $this->getAllTemplates();
return isset($templates[$name]) ? $templates[$name] : NULL;
}
/**
* Retrieves all migration templates belonging to enabled extensions.
*
* @return array
* Array of parsed templates, keyed by the fully-qualified id.
*/
public function getAllTemplates() {
$templates = [];
foreach ($this->moduleHandler->getModuleDirectories() as $directory) {
$full_directory = $directory . '/' . $this->directory;
if (file_exists($full_directory)) {
$files = scandir($full_directory);
foreach ($files as $file) {
if ($file[0] !== '.' && fnmatch('*.yml', $file)) {
$templates[basename($file, '.yml')] = Yaml::decode(file_get_contents("$full_directory/$file"));
}
}
}
}
return $templates;
}
}

View file

@ -70,20 +70,4 @@ class MigratePluginManager extends DefaultPluginManager {
return $plugin;
}
/**
* Helper for the plugin type to interface map.
*
* @return array
* An array map from plugin type to interface.
*/
protected function getPluginInterfaceMap() {
return [
'destination' => 'Drupal\migrate\Plugin\MigrateDestinationInterface',
'process' => 'Drupal\migrate\Plugin\MigrateProcessInterface',
'source' => 'Drupal\migrate\Plugin\MigrateSourceInterface',
'id_map' => 'Drupal\migrate\Plugin\MigrateIdMapInterface',
'entity_field' => 'Drupal\migrate\Plugin\MigrateEntityDestinationFieldInterface',
];
}
}

View file

@ -1,35 +0,0 @@
<?php
/**
* @file
* Contains \Drupal\migrate\Plugin\migrate\destination\Book.
*/
namespace Drupal\migrate\Plugin\migrate\destination;
use Drupal\Core\Entity\EntityInterface;
use Drupal\migrate\Row;
/**
* @MigrateDestination(
* id = "book",
* provider = "book"
* )
*/
class Book extends EntityContentBase {
/**
* {@inheritdoc}
*/
protected static function getEntityTypeId($plugin_id) {
return 'node';
}
/**
* {@inheritdoc}
*/
protected function updateEntity(EntityInterface $entity, Row $row) {
$entity->book = $row->getDestinationProperty('book');
}
}

View file

@ -7,7 +7,6 @@
namespace Drupal\migrate\Plugin\migrate\destination;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\File\FileSystemInterface;
@ -83,7 +82,7 @@ class EntityFile extends EntityContentBase {
// Ensure the source file exists, if it's a local URI or path.
if ($this->isLocalUri($source) && !file_exists($source)) {
throw new MigrateException(SafeMarkup::format('File @source does not exist.', ['@source' => $source]));
throw new MigrateException("File '$source' does not exist.");
}
// If the start and end file is exactly the same, there is nothing to do.
@ -99,7 +98,7 @@ class EntityFile extends EntityContentBase {
$success = $this->writeFile($source, $destination, $replace);
}
else {
throw new MigrateException(SafeMarkup::format('Could not create directory @dir', ['@dir' => $dir]));
throw new MigrateException("Could not create directory '$dir'");
}
}
@ -107,7 +106,7 @@ class EntityFile extends EntityContentBase {
return parent::import($row, $old_destination_id_values);
}
else {
throw new MigrateException(SafeMarkup::format('File %source could not be copied to %destination.', ['%source' => $source, '%destination' => $destination]));
throw new MigrateException("File $source could not be copied to $destination.");
}
}
@ -121,7 +120,7 @@ class EntityFile extends EntityContentBase {
* @param integer $replace
* FILE_EXISTS_REPLACE (default) or FILE_EXISTS_RENAME.
*
* @return boolean
* @return bool
* TRUE on success, FALSE on failure.
*/
protected function writeFile($source, $destination, $replace = FILE_EXISTS_REPLACE) {
@ -164,7 +163,7 @@ class EntityFile extends EntityContentBase {
* @param string $uri
* The URI or path.
*
* @return boolean|string
* @return string|false
* The directory component of the path or URI, or FALSE if it could not
* be determined.
*/
@ -187,7 +186,7 @@ class EntityFile extends EntityContentBase {
* @param string $destination
* The destination URI.
*
* @return boolean
* @return bool
* TRUE if the source and destination URIs refer to the same physical path,
* otherwise FALSE.
*/
@ -210,7 +209,7 @@ class EntityFile extends EntityContentBase {
* @param string $uri
* The URI or path to test.
*
* @return boolean
* @return bool
*/
protected function isLocalUri($uri) {
$scheme = $this->fileSystem->uriScheme($uri);

View file

@ -1,33 +0,0 @@
<?php
/**
* @file
* Contains \Drupal\migrate\Plugin\migrate\destination\EntitySearchPage.
*/
namespace Drupal\migrate\Plugin\migrate\destination;
use Drupal\Core\Entity\EntityInterface;
use Drupal\migrate\Row;
/**
* @MigrateDestination(
* id = "entity:search_page"
* )
*/
class EntitySearchPage extends EntityConfigBase {
/**
* Updates the entity with the contents of a row.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The search page entity.
* @param \Drupal\migrate\Row $row
* The row object to update from.
*/
protected function updateEntity(EntityInterface $entity, Row $row) {
$entity->setPlugin($row->getDestinationProperty('plugin'));
$entity->getPlugin()->setConfiguration($row->getDestinationProperty('configuration'));
}
}

View file

@ -1,29 +0,0 @@
<?php
/**
* @file
* Contains \Drupal\migrate\Plugin\migrate\destination\EntityTaxonomyTerm.
*/
namespace Drupal\migrate\Plugin\migrate\destination;
use Drupal\migrate\Row;
/**
* @MigrateDestination(
* id = "entity:taxonomy_term"
* )
*/
class EntityTaxonomyTerm extends EntityContentBase {
/**
* {@inheritdoc}
*/
protected function getEntity(Row $row, array $old_destination_id_values) {
if ($row->isStub()) {
$row->setDestinationProperty('name', $this->t('Stub name for source tid:') . $row->getSourceProperty('tid'));
}
return parent::getEntity($row, $old_destination_id_values);
}
}

View file

@ -2,7 +2,7 @@
/**
* @file
* Contains \Drupal\migrate\Plugin\migrate\destination\Null.
* Contains \Drupal\migrate\Plugin\migrate\destination\NullDestination.
*/
namespace Drupal\migrate\Plugin\migrate\destination;
@ -16,7 +16,7 @@ use Drupal\migrate\Row;
* requirements_met = false
* )
*/
class Null extends DestinationBase {
class NullDestination extends DestinationBase {
/**
* {@inheritdoc}

View file

@ -1,97 +0,0 @@
<?php
/**
* @file
* Contains \Drupal\migrate\Plugin\migrate\destination\UrlAlias.
*/
namespace Drupal\migrate\Plugin\migrate\destination;
use Drupal\Core\Path\AliasStorage;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate\Row;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
/**
* @MigrateDestination(
* id = "url_alias"
* )
*/
class UrlAlias extends DestinationBase implements ContainerFactoryPluginInterface {
/**
* The alias storage service.
*
* @var \Drupal\Core\Path\AliasStorage $aliasStorage
*/
protected $aliasStorage;
/**
* Constructs an entity destination plugin.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param MigrationInterface $migration
* The migration.
* @param \Drupal\Core\Path\AliasStorage $alias_storage
* The alias storage service.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, AliasStorage $alias_storage) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
$this->aliasStorage = $alias_storage;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$migration,
$container->get('path.alias_storage')
);
}
/**
* {@inheritdoc}
*/
public function import(Row $row, array $old_destination_id_values = array()) {
$path = $this->aliasStorage->save(
$row->getDestinationProperty('source'),
$row->getDestinationProperty('alias'),
$row->getDestinationProperty('langcode'),
$old_destination_id_values ? $old_destination_id_values[0] : NULL
);
return array($path['pid']);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['pid']['type'] = 'integer';
return $ids;
}
/**
* {@inheritdoc}
*/
public function fields(MigrationInterface $migration = NULL) {
return [
'pid' => 'The path id',
'source' => 'The source path.',
'alias' => 'The url alias.',
'langcode' => 'The language code for the url.',
];
}
}

View file

@ -7,7 +7,6 @@
namespace Drupal\migrate\Plugin\migrate\process;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
@ -34,7 +33,7 @@ class Concat extends ProcessPluginBase {
return implode($delimiter, $value);
}
else {
throw new MigrateException(sprintf('%s is not an array', SafeMarkup::checkPlain(var_export($value, TRUE))));
throw new MigrateException(sprintf('%s is not an array', var_export($value, TRUE)));
}
}

View file

@ -0,0 +1,29 @@
<?php
/**
* @file
* Contains \Drupal\migrate\Plugin\migrate\source\DummyQueryTrait.
*/
namespace Drupal\migrate\Plugin\migrate\source;
/**
* Trait providing a dummy select query object for source plugins based on
* SqlBase which override initializeIterator() to obtain their data from other
* SqlBase services instead of a direct query. This ensures that query() returns
* a valid object, even though it isn't used for iteration.
*/
trait DummyQueryTrait {
/**
* @return \Drupal\Core\Database\Query\SelectInterface
*/
public function query() {
// Pass an arbritrary table name - the query should never be executed anyway.
$query = $this->select(uniqid(), 's')
->range(0, 1);
$query->addExpression('1');
return $query;
}
}

View file

@ -94,7 +94,7 @@ class EntityFileTest extends KernelTestBase {
$this->fail('Expected Drupal\migrate\MigrateException when importing ' . $destination);
}
catch (MigrateException $e) {
$this->assertIdentical($e->getMessage(), 'File ' . $destination . ' does not exist.');
$this->assertIdentical($e->getMessage(), "File '$destination' does not exist.");
}
}

View file

@ -8,7 +8,9 @@
namespace Drupal\migrate\Tests;
use Drupal\Core\Database\Database;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate\MigrateExecutable;
use Drupal\migrate\MigrateMessageInterface;
use Drupal\migrate\Row;
use Drupal\simpletest\KernelTestBase;
@ -43,6 +45,13 @@ abstract class MigrateTestBase extends KernelTestBase implements MigrateMessageI
*/
protected $migrateMessages;
/**
* The primary migration being tested.
*
* @var \Drupal\migrate\Entity\MigrationInterface
*/
protected $migration;
public static $modules = array('migrate');
/**
@ -73,21 +82,6 @@ abstract class MigrateTestBase extends KernelTestBase implements MigrateMessageI
parent::tearDown();
}
/**
* Prepare the migration.
*
* @param \Drupal\migrate\Entity\MigrationInterface $migration
* The migration object.
* @param array $files
* An array of files.
*/
protected function prepare(MigrationInterface $migration, array $files = array()) {
$this->loadDumps($files);
if ($this instanceof MigrateDumpAlterInterface) {
static::migrateDumpAlter($this);
}
}
/**
* Load Drupal 6 database dumps to be used.
*
@ -96,7 +90,7 @@ abstract class MigrateTestBase extends KernelTestBase implements MigrateMessageI
* @param string $method
* The name of the method in the dump class to use. Defaults to load.
*/
protected function loadDumps($files, $method = 'load') {
protected function loadDumps(array $files, $method = 'load') {
// Load the database from the portable PHP dump.
// The files may be gzipped.
foreach ($files as $file) {
@ -137,6 +131,25 @@ abstract class MigrateTestBase extends KernelTestBase implements MigrateMessageI
}
}
/**
* Executes a single migration.
*
* @param string|\Drupal\migrate\Entity\MigrationInterface $migration
* The migration to execute, or its ID.
*/
protected function executeMigration($migration) {
if (is_string($migration)) {
$this->migration = Migration::load($migration);
}
else {
$this->migration = $migration;
}
if ($this instanceof MigrateDumpAlterInterface) {
static::migrateDumpAlter($this);
}
(new MigrateExecutable($this->migration, $this))->import();
}
/**
* {@inheritdoc}
*/

View file

@ -0,0 +1,78 @@
<?php
/**
* @file
* Contains \Drupal\migrate\Tests\TemplateTest
*/
namespace Drupal\migrate\Tests;
/**
* Test the migration template functionality.
*
* @group migrate
*/
class TemplateTest extends MigrateTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('template_test');
/**
* Test different connection types.
*/
public function testTemplates() {
$migration_templates = \Drupal::service('migrate.template_storage')->findTemplatesByTag("Template Test");
$expected_url = [
'id' => 'url_template',
'label' => 'Template test - url',
'migration_tags' => ['Template Test'],
'source' => ['plugin' => 'empty'],
'process' => ['src' => 'foobar'],
'destination' => ['plugin' => 'url_alias'],
];
$expected_node = [
'id' => 'node_template',
'label' => 'Template test - node',
'migration_tags' => ['Template Test'],
'source' => ['plugin' => 'empty'],
'process' => ['src' => 'barfoo'],
'destination' => ['plugin' => 'entity:node'],
];
$this->assertIdentical($migration_templates['migrate.migration.url_template'], $expected_url);
$this->assertIdentical($migration_templates['migrate.migration.node_template'], $expected_node);
$this->assertFalse(isset($migration_templates['migrate.migration.other_template']));
}
/**
* Tests retrieving a template by name.
*/
public function testGetTemplateByName() {
/** @var \Drupal\migrate\MigrateTemplateStorage $template_storage */
$template_storage = \Drupal::service('migrate.template_storage');
$expected_url = [
'id' => 'url_template',
'label' => 'Template test - url',
'migration_tags' => ['Template Test'],
'source' => ['plugin' => 'empty'],
'process' => ['src' => 'foobar'],
'destination' => ['plugin' => 'url_alias'],
];
$expected_node = [
'id' => 'node_template',
'label' => 'Template test - node',
'migration_tags' => ['Template Test'],
'source' => ['plugin' => 'empty'],
'process' => ['src' => 'barfoo'],
'destination' => ['plugin' => 'entity:node'],
];
$this->assertIdentical($template_storage->getTemplateByName('migrate.migration.url_template'), $expected_url);
$this->assertIdentical($template_storage->getTemplateByName('migrate.migration.node_template'), $expected_node);
$this->assertNull($template_storage->getTemplateByName('migrate.migration.dne'));
}
}

View file

@ -0,0 +1,10 @@
id: node_template
label: Template test - node
migration_tags:
- Template Test
source:
plugin: empty
process:
src: barfoo
destination:
plugin: entity:node

View file

@ -0,0 +1,10 @@
id: other_template
label: Template with a different tag
migration_tags:
- Different Template Test
source:
plugin: empty
process:
src: raboof
destination:
plugin: entity:user

View file

@ -0,0 +1,10 @@
id: url_template
label: Template test - url
migration_tags:
- Template Test
source:
plugin: empty
process:
src: foobar
destination:
plugin: url_alias

View file

@ -0,0 +1,5 @@
name: 'Migration template test'
type: module
package: Testing
version: VERSION
core: 8.x

View file

@ -58,6 +58,13 @@ abstract class MigrateSqlSourceTestCase extends MigrateTestCase {
*/
protected $expectedResults = array();
/**
* Expected count of source rows.
*
* @var int
*/
protected $expectedCount = 0;
/**
* The source plugin instance under test.
*
@ -97,6 +104,7 @@ abstract class MigrateSqlSourceTestCase extends MigrateTestCase {
->method('getSourcePlugin')
->will($this->returnValue($plugin));
$this->source = $plugin;
$this->expectedCount = count($this->expectedResults);
}
/**
@ -106,6 +114,13 @@ abstract class MigrateSqlSourceTestCase extends MigrateTestCase {
$this->queryResultTest($this->source, $this->expectedResults);
}
/**
* Test the source returns the row count expected.
*/
public function testSourceCount() {
$this->assertEquals($this->source->count(), $this->expectedCount);
}
/**
* @param \Drupal\migrate\Row $row
* @param string $key

View file

@ -7,7 +7,6 @@
namespace Drupal\Tests\migrate\Unit;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Database\Connection;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate\MigrateException;
@ -61,7 +60,7 @@ class TestSqlIdMap extends Sql implements \Iterator {
'not null' => FALSE,
);
default:
throw new MigrateException(SafeMarkup::format('@type not supported', array('@type' => $id_definition['type'])));
throw new MigrateException($id_definition['type'] . ' not supported');
}
}
}

View file

@ -19,12 +19,6 @@ class StaticMapTest extends MigrateProcessTestCase {
* {@inheritdoc}
*/
protected function setUp() {
$this->row = $this->getMockBuilder('Drupal\migrate\Row')
->disableOriginalConstructor()
->getMock();
$this->migrateExecutable = $this->getMockBuilder('Drupal\migrate\MigrateExecutable')
->disableOriginalConstructor()
->getMock();
$configuration['map']['foo']['bar'] = 'baz';
$this->plugin = new StaticMap($configuration, 'map', array());
parent::setUp();