Update to drupal 8.0.0-rc1. For more information, see https://www.drupal.org/node/2582663

This commit is contained in:
Greg Anderson 2015-10-08 11:40:12 -07:00
parent eb34d130a8
commit f32e58e4b1
8476 changed files with 211648 additions and 170042 deletions

View file

@ -59,7 +59,7 @@ interface MigrateDestinationInterface extends PluginInspectionInterface {
* Import the row.
*
* Derived classes must implement import(), to construct one new object
* (pre-populated) using ID mappings in the Migration).
* (pre-populated) using ID mappings in the Migration.
*
* @param \Drupal\migrate\Row $row
* The row object.
@ -72,11 +72,15 @@ interface MigrateDestinationInterface extends PluginInspectionInterface {
public function import(Row $row, array $old_destination_id_values = array());
/**
* Delete the specified IDs from the target Drupal.
* Delete the specified destination object from the target Drupal.
*
* @param array $destination_identifiers
* The destination ids to delete.
* @param array $destination_identifier
* The ID of the destination object to delete.
*/
public function rollbackMultiple(array $destination_identifiers);
public function rollback(array $destination_identifier);
/**
* @return bool
*/
public function supportsRollback();
}

View file

@ -26,21 +26,29 @@ use Drupal\migrate\Entity\MigrationInterface;
class MigrateDestinationPluginManager extends MigratePluginManager {
/**
* The theme handler
* The entity manager.
*
* @var \Drupal\Core\Extension\ThemeHandlerInterface
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $themeHandler;
protected $entityManager;
/**
* An associative array where the keys are the enabled modules and themes.
* Constructs a MigrateDestinationPluginManager object.
*
* @var array
*/
protected $providers;
/**
* {@inheritdoc}
* @param string $type
* The type of the plugin: row, source, process, destination, entity_field,
* id_map.
* @param \Traversable $namespaces
* An object that implements \Traversable which contains the root paths
* keyed by the corresponding namespace to look for plugin implementations.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* Cache backend instance to use.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler to invoke the alter hook with.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
* @param string $annotation
* The annotation class name.
*/
public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, EntityManagerInterface $entity_manager, $annotation = 'Drupal\migrate\Annotation\MigrateDestination') {
parent::__construct($type, $namespaces, $cache_backend, $module_handler, $annotation);

View file

@ -57,7 +57,7 @@ interface MigrateIdMapInterface extends \Iterator, PluginInspectionInterface {
* Saves a message related to a source record in the migration message table.
*
* @param array $source_id_values
* The source identifier values of the record in error.
* The source identifier keyed values of the record, e.g. ['nid' => 5].
* @param string $message
* The message to record.
* @param int $level
@ -69,7 +69,7 @@ interface MigrateIdMapInterface extends \Iterator, PluginInspectionInterface {
* Retrieves an iterator over messages relate to source records.
*
* @param array $source_id_values
* (optional) The source identifier values of a specific record to retrieve.
* (optional) The source identifier keyed values of the record, e.g. ['nid' => 5].
* If empty, all messages are retrieved.
* @param int $level
* (optional) Message severity. If NULL, retrieve messages of all severities.
@ -134,7 +134,7 @@ interface MigrateIdMapInterface extends \Iterator, PluginInspectionInterface {
* Deletes the map and message entries for a given source record.
*
* @param array $source_id_values
* The source identifier values of the record to delete.
* The source identifier keyed values of the record, e.g. ['nid' => 5].
* @param bool $messages_only
* TRUE to only delete the migrate messages.
*/
@ -144,19 +144,10 @@ interface MigrateIdMapInterface extends \Iterator, PluginInspectionInterface {
* Deletes the map and message table entries for a given destination row.
*
* @param array $destination_id_values
* The destination identifier values we should do the deletes for.
* The destination identifier key value pairs we should do the deletes for.
*/
public function deleteDestination(array $destination_id_values);
/**
* Deletes the map and message entries for a set of given source records.
*
* @param array $source_id_values
* The identifier values of the sources we should do the deletes for. Each
* array member is an array of identifier values for one source row.
*/
public function deleteBulk(array $source_id_values);
/**
* Clears all messages from the map.
*/
@ -166,7 +157,7 @@ interface MigrateIdMapInterface extends \Iterator, PluginInspectionInterface {
* Retrieves a row from the map table based on source identifier values.
*
* @param array $source_id_values
* The source identifier values of the record to retrieve.
* The source identifier keyed values of the record, e.g. ['nid' => 5].
*
* @return array
* The raw row data as an associative array.
@ -177,7 +168,7 @@ interface MigrateIdMapInterface extends \Iterator, PluginInspectionInterface {
* Retrieves a row by the destination identifiers.
*
* @param array $destination_id_values
* The destination identifier values of the record to retrieve.
* The destination identifier keyed values of the record, e.g. ['nid' => 5].
*
* @return array
* The row(s) of data.
@ -202,27 +193,36 @@ interface MigrateIdMapInterface extends \Iterator, PluginInspectionInterface {
* (possibly multi-field) source identifier value mapped to it.
*
* @param array $destination_id_values
* The destination identifier values of the record.
* The destination identifier keyed values of the record, e.g. ['nid' => 5].
*
* @return array
* The source identifier values of the record, or NULL on failure.
* The source identifier keyed values of the record, e.g. ['nid' => 5], or
* an empty array on failure.
*/
public function lookupSourceID(array $destination_id_values);
/**
* Looks up the destination identifier.
* Looks up the destination identifier corresponding to a source key.
*
* Given a (possibly multi-field) source identifier value, return the
* (possibly multi-field) destination identifier value it is mapped to.
*
* @param array $source_id_values
* The source identifier values of the record.
* The source identifier keyed values of the record, e.g. ['nid' => 5].
*
* @return array
* The destination identifier values of the record, or NULL on failure.
*/
public function lookupDestinationId(array $source_id_values);
/**
* Looks up the destination identifier currently being iterated.
*
* @return array
* The destination identifier values of the record, or NULL on failure.
*/
public function currentDestination();
/**
* Removes any persistent storage used by this map.
*

View file

@ -30,17 +30,6 @@ interface MigrateSourceInterface extends \Countable, \Iterator, PluginInspection
*/
public function fields();
/**
* Returns the iterator that will yield the row arrays to be processed.
*
* @return \Iterator
* The iterator object.
*
* @throws \Exception
* Cannot obtain a valid iterator.
*/
public function getIterator();
/**
* Add additional data to the row.
*

View file

@ -24,7 +24,7 @@ abstract class BuilderBase extends PluginBase implements MigrateBuilderInterface
* @param array $configuration
* (optional) Additional configuration for the plugin.
*
* @return \Drupal\migrate\Plugin\MigrateSourceInterface
* @return \Drupal\migrate\Plugin\MigrateSourceInterface|\Drupal\migrate\Plugin\RequirementsInterface
* The fully initialized source plugin.
*/
protected function getSourcePlugin($plugin_id, array $configuration = []) {

View file

@ -1,4 +1,5 @@
<?php
/**
* @file
* Contains \Drupal\migrate\Plugin\migrate\destination\Config.
@ -13,10 +14,8 @@ use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\DependencyTrait;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate\MigrateException;
use Drupal\migrate\Row;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Config\Config as ConfigObject;
/**
* Persist data to the config system.
@ -80,19 +79,7 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface,
}
}
$this->config->save();
return TRUE;
}
/**
* Throw an exception because config can not be rolled back.
*
* @param array $destination_keys
* The array of destination ids to roll back.
*
* @throws \Drupal\migrate\MigrateException
*/
public function rollbackMultiple(array $destination_keys) {
throw new MigrateException('Configuration can not be rolled back');
return [$this->config->getName()];
}
/**
@ -106,7 +93,8 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface,
* {@inheritdoc}
*/
public function getIds() {
return array();
$ids['config_name']['type'] = 'string';
return $ids;
}
/**

View file

@ -26,6 +26,13 @@ use Drupal\migrate\Plugin\RequirementsInterface;
*/
abstract class DestinationBase extends PluginBase implements MigrateDestinationInterface, RequirementsInterface {
/**
* Indicates whether the destination can be rolled back.
*
* @var bool
*/
protected $supportsRollback = FALSE;
/**
* The migration.
*
@ -62,8 +69,14 @@ abstract class DestinationBase extends PluginBase implements MigrateDestinationI
/**
* {@inheritdoc}
*/
public function rollbackMultiple(array $destination_identifiers) {
public function rollback(array $destination_identifier) {
// By default we do nothing.
}
/**
* {@inheritdoc}
*/
public function supportsRollback() {
return $this->supportsRollback;
}
}

View file

@ -58,6 +58,7 @@ abstract class Entity extends DestinationBase implements ContainerFactoryPluginI
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
$this->storage = $storage;
$this->bundles = $bundles;
$this->supportsRollback = TRUE;
}
/**
@ -113,12 +114,11 @@ abstract class Entity extends DestinationBase implements ContainerFactoryPluginI
$this->updateEntity($entity, $row);
}
else {
$values = $row->getDestination();
// Stubs might not have the bundle specified.
// Stubs might need some required fields filled in.
if ($row->isStub()) {
$values = $this->processStubValues($values);
$this->processStubRow($row);
}
$entity = $this->storage->create($values);
$entity = $this->storage->create($row->getDestination());
$entity->enforceIsNew();
}
return $entity;
@ -139,21 +139,14 @@ abstract class Entity extends DestinationBase implements ContainerFactoryPluginI
/**
* Process the stub values.
*
* @param array $values
* An array of destination values.
*
* @return array
* The processed stub values.
* @param \Drupal\migrate\Row $row
* The row of data.
*/
protected function processStubValues(array $values) {
$values = array_intersect_key($values, $this->getIds());
protected function processStubRow(Row $row) {
$bundle_key = $this->getKey('bundle');
if ($bundle_key && !isset($values[$bundle_key])) {
$values[$bundle_key] = reset($this->bundles);
if ($bundle_key && empty($row->getDestinationProperty($bundle_key))) {
$row->setDestinationProperty($bundle_key, reset($this->bundles));
}
return $values;
}
/**
@ -171,6 +164,17 @@ abstract class Entity extends DestinationBase implements ContainerFactoryPluginI
return $this->storage->getEntityType()->getKey($key);
}
/**
* {@inheritdoc}
*/
public function rollback(array $destination_identifier) {
// Delete the specified entity from Drupal if it exists.
$entity = $this->storage->load(reset($destination_identifier));
if ($entity) {
$entity->delete();
}
}
/**
* {@inheritdoc}
*/

View file

@ -43,8 +43,6 @@ class EntityContentBase extends Entity {
* The storage for this entity type.
* @param array $bundles
* The list of bundles this entity type has.
* @param \Drupal\migrate\Plugin\MigratePluginManager $plugin_manager
* The plugin manager.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager service.
*/

View file

@ -8,8 +8,6 @@
namespace Drupal\migrate\Plugin\migrate\id_map;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginBase;
@ -428,8 +426,8 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
public function getRowBySource(array $source_id_values) {
$query = $this->getDatabase()->select($this->mapTableName(), 'map')
->fields('map');
foreach ($this->sourceIdFields() as $source_id) {
$query = $query->condition("map.$source_id", array_shift($source_id_values), '=');
foreach ($this->sourceIdFields() as $field_name => $source_id) {
$query->condition("map.$source_id", $source_id_values[$field_name], '=');
}
$result = $query->execute();
return $result->fetchAssoc();
@ -441,8 +439,8 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
public function getRowByDestination(array $destination_id_values) {
$query = $this->getDatabase()->select($this->mapTableName(), 'map')
->fields('map');
foreach ($this->destinationIdFields() as $destination_id) {
$query = $query->condition("map.$destination_id", array_shift($destination_id_values), '=');
foreach ($this->destinationIdFields() as $field_name => $destination_id) {
$query->condition("map.$destination_id", $destination_id_values[$field_name], '=');
}
$result = $query->execute();
return $result->fetchAssoc();
@ -467,28 +465,36 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
/**
* {@inheritdoc}
*/
public function lookupSourceID(array $destination_id) {
$query = $this->getDatabase()->select($this->mapTableName(), 'map')
->fields('map', $this->sourceIdFields());
foreach ($this->destinationIdFields() as $key_name) {
$query = $query->condition("map.$key_name", array_shift($destination_id), '=');
public function lookupSourceID(array $destination_id_values) {
$source_id_fields = $this->sourceIdFields();
$query = $this->getDatabase()->select($this->mapTableName(), 'map');
foreach ($source_id_fields as $source_field_name => $idmap_field_name) {
$query->addField('map', $idmap_field_name, $source_field_name);
}
foreach ($this->destinationIdFields() as $field_name => $destination_id) {
$query->condition("map.$destination_id", $destination_id_values[$field_name], '=');
}
$result = $query->execute();
$source_id = $result->fetchAssoc();
return array_values($source_id ?: array());
return $result->fetchAssoc() ?: [];
}
/**
* {@inheritdoc}
*/
public function lookupDestinationId(array $source_id) {
if (empty($source_id)) {
public function lookupDestinationId(array $source_id_values) {
if (empty($source_id_values)) {
return array();
}
$query = $this->getDatabase()->select($this->mapTableName(), 'map')
->fields('map', $this->destinationIdFields());
foreach ($this->sourceIdFields() as $key_name) {
$query = $query->condition("map.$key_name", array_shift($source_id), '=');
// When looking up the destination ID we require an array with both the
// source key and value, e.g. ['nid' => 41]. However, the Migration process
// plugin doesn't currently have a way to get the source key so we presume
// the values have been passed through in the correct order.
$have_keys = !isset($source_id_values[0]);
foreach ($this->sourceIdFields() as $field_name => $source_id) {
$query->condition("map.$source_id", $have_keys ? $source_id_values[$field_name] : array_shift($source_id_values), '=');
}
$result = $query->execute();
$destination_id = $result->fetchAssoc();
@ -507,8 +513,8 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
// A NULL key value will fail.
if (!isset($source_id_values[$field_name])) {
$this->message->display(t(
'Could not save to map table due to NULL value for key field !field',
array('!field' => $field_name)), 'error');
'Could not save to map table due to NULL value for key field @field',
array('@field' => $field_name)), 'error');
return;
}
$keys[$key_name] = $source_id_values[$field_name];
@ -544,13 +550,12 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
* {@inheritdoc}
*/
public function saveMessage(array $source_id_values, $message, $level = MigrationInterface::MESSAGE_ERROR) {
$count = 1;
foreach ($source_id_values as $id_value) {
$fields['sourceid' . $count++] = $id_value;
foreach ($this->sourceIdFields() as $field_name => $source_id) {
// If any key value is not set, we can't save.
if (!isset($id_value)) {
if (!isset($source_id_values[$field_name])) {
return;
}
$fields[$source_id] = $source_id_values[$field_name];
}
$fields['level'] = $level;
$fields['message'] = $message;
@ -565,10 +570,12 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
public function getMessageIterator(array $source_id_values = [], $level = NULL) {
$query = $this->getDatabase()->select($this->messageTableName(), 'msg')
->fields('msg');
$count = 1;
foreach ($source_id_values as $id_value) {
$query->condition('sourceid' . $count++, $id_value);
foreach ($this->sourceIdFields() as $field_name => $source_id) {
if (isset($source_id_values[$field_name])) {
$query->condition($source_id, $source_id_values[$field_name]);
}
}
if ($level) {
$query->condition('level', $level);
}
@ -655,13 +662,11 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
$map_query = $this->getDatabase()->delete($this->mapTableName());
}
$message_query = $this->getDatabase()->delete($this->messageTableName());
$count = 1;
foreach ($source_id_values as $id_value) {
foreach ($this->sourceIdFields() as $field_name => $source_id) {
if (!$messages_only) {
$map_query->condition('sourceid' . $count, $id_value);
$map_query->condition($source_id, $source_id_values[$field_name]);
}
$message_query->condition('sourceid' . $count, $id_value);
$count++;
$message_query->condition($source_id, $source_id_values[$field_name]);
}
if (!$messages_only) {
@ -675,22 +680,20 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
/**
* {@inheritdoc}
*/
public function deleteDestination(array $destination_id) {
public function deleteDestination(array $destination_id_values) {
$map_query = $this->getDatabase()->delete($this->mapTableName());
$message_query = $this->getDatabase()->delete($this->messageTableName());
$source_id = $this->lookupSourceID($destination_id);
if (!empty($source_id)) {
$count = 1;
foreach ($destination_id as $key_value) {
$map_query->condition('destid' . $count, $key_value);
$count++;
$source_id_values = $this->lookupSourceID($destination_id_values);
if (!empty($source_id_values)) {
foreach ($this->destinationIdFields() as $field_name => $destination_id) {
$map_query->condition($destination_id, $destination_id_values[$field_name]);
}
// Notify anyone listening of the map row we're about to delete.
$this->eventDispatcher->dispatch(MigrateEvents::MAP_DELETE, new MigrateMapDeleteEvent($this, $source_id));
$this->eventDispatcher->dispatch(MigrateEvents::MAP_DELETE, new MigrateMapDeleteEvent($this, $source_id_values));
$map_query->execute();
$count = 1;
foreach ($source_id as $key_value) {
$message_query->condition('sourceid' . $count, $key_value);
foreach ($this->sourceIdFields() as $field_name => $source_id) {
$message_query->condition($source_id, $source_id_values[$field_name]);
$count++;
}
$message_query->execute();
@ -700,56 +703,20 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
/**
* {@inheritdoc}
*/
public function setUpdate(array $source_id) {
if (empty($source_id)) {
public function setUpdate(array $source_id_values) {
if (empty($source_id_values)) {
throw new MigrateException('No source identifiers provided to update.');
}
$query = $this->getDatabase()
->update($this->mapTableName())
->fields(array('source_row_status' => MigrateIdMapInterface::STATUS_NEEDS_UPDATE));
$count = 1;
foreach ($source_id as $key_value) {
$query->condition('sourceid' . $count++, $key_value);
foreach ($this->sourceIdFields() as $field_name => $source_id) {
$query->condition($source_id, $source_id_values[$field_name]);
}
$query->execute();
}
/**
* {@inheritdoc}
*/
public function deleteBulk(array $source_id_values) {
// If we have a single-column key, we can shortcut it.
if (count($this->migration->getSourcePlugin()->getIds()) == 1) {
$sourceids = array();
foreach ($source_id_values as $source_id) {
// Notify anyone listening of the map rows we're about to delete.
$this->eventDispatcher->dispatch(MigrateEvents::MAP_DELETE, new MigrateMapDeleteEvent($this, $source_id));
$sourceids[] = $source_id;
}
$this->getDatabase()->delete($this->mapTableName())
->condition('sourceid1', $sourceids, 'IN')
->execute();
$this->getDatabase()->delete($this->messageTableName())
->condition('sourceid1', $sourceids, 'IN')
->execute();
}
else {
foreach ($source_id_values as $source_id) {
// Notify anyone listening of the map rows we're deleting.
$this->eventDispatcher->dispatch(MigrateEvents::MAP_DELETE, new MigrateMapDeleteEvent($this, $source_id));
$map_query = $this->getDatabase()->delete($this->mapTableName());
$message_query = $this->getDatabase()->delete($this->messageTableName());
$count = 1;
foreach ($source_id as $key_value) {
$map_query->condition('sourceid' . $count, $key_value);
$message_query->condition('sourceid' . $count++, $key_value);
}
$map_query->execute();
$message_query->execute();
}
}
}
/**
* {@inheritdoc}
*/
@ -805,6 +772,22 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
return serialize($this->currentKey);
}
/**
* @inheritdoc
*/
public function currentDestination() {
if ($this->valid()) {
$result = array();
foreach ($this->destinationIdFields() as $destination_field_name => $idmap_field_name) {
$result[$destination_field_name] = $this->currentRow[$idmap_field_name];
}
return $result;
}
else {
return NULL;
}
}
/**
* Implementation of Iterator::next().
*

View file

@ -114,6 +114,7 @@ class Migration extends ProcessPluginBase implements ContainerFactoryPluginInter
$destination_plugin = $migration->getDestinationPlugin(TRUE);
// Only keep the process necessary to produce the destination ID.
$process = $migration->get('process');
// We already have the source id values but need to key them for the Row
// constructor.
$source_ids = $migration->getSourcePlugin()->getIds();

View file

@ -16,7 +16,7 @@ namespace Drupal\migrate\Plugin\migrate\source;
trait DummyQueryTrait {
/**
* @return \Drupal\Core\Database\Query\SelectInterface
* {@inheritdoc}
*/
public function query() {
// Pass an arbritrary table name - the query should never be executed anyway.
@ -26,4 +26,11 @@ trait DummyQueryTrait {
return $query;
}
/**
* {@inheritdoc}
*/
public function count() {
return 1;
}
}

View file

@ -125,14 +125,6 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter
*/
protected $iterator;
/**
* @TODO, find out how to remove this.
* @see https://www.drupal.org/node/2443617
*
* @var MigrateExecutableInterface
*/
public $migrateExecutable;
/**
* {@inheritdoc}
*/
@ -199,11 +191,8 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter
if ($skip) {
// Make sure we replace any previous messages for this item with any
// new ones.
$id_map = $this->migration->getIdMap();
$id_map->delete($this->currentSourceIds, TRUE);
$this->migrateExecutable->saveQueuedMessages();
if ($save_to_map) {
$id_map->saveIdMapping($row, array(), MigrateIdMapInterface::STATUS_IGNORED, $this->migrateExecutable->rollbackAction);
$this->idMap->saveIdMapping($row, array(), MigrateIdMapInterface::STATUS_IGNORED);
$this->currentRow = NULL;
$this->currentSourceIds = NULL;
}
@ -224,7 +213,7 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter
*
* @return \Iterator
*/
public function getIterator() {
protected function getIterator() {
if (!isset($this->iterator)) {
$this->iterator = $this->initializeIterator();
}
@ -307,6 +296,12 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter
$row->setIdMap($id_map);
}
// Clear any previous messages for this row before potentially adding
// new ones.
if (!empty($this->currentSourceIds)) {
$this->idMap->delete($this->currentSourceIds, TRUE);
}
// Preparing the row gives source plugins the chance to skip.
if ($this->prepareRow($row) === FALSE) {
continue;

View file

@ -8,9 +8,12 @@
namespace Drupal\migrate\Plugin\migrate\source;
use Drupal\Core\Database\Database;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\State\StateInterface;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate\Plugin\migrate\id_map\Sql;
use Drupal\migrate\Plugin\MigrateIdMapInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Sources whose data may be fetched via DBTNG.
@ -21,7 +24,7 @@ use Drupal\migrate\Plugin\MigrateIdMapInterface;
* is present, it is used as a database connection information array to define
* the connection.
*/
abstract class SqlBase extends SourcePluginBase {
abstract class SqlBase extends SourcePluginBase implements ContainerFactoryPluginInterface {
/**
* @var \Drupal\Core\Database\Query\SelectInterface
@ -33,11 +36,32 @@ abstract class SqlBase extends SourcePluginBase {
*/
protected $database;
/**
* State service for retrieving database info.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration) {
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
$this->state = $state;
}
/**
* {@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('state')
);
}
/**
@ -58,26 +82,51 @@ abstract class SqlBase extends SourcePluginBase {
*/
public function getDatabase() {
if (!isset($this->database)) {
if (isset($this->configuration['target'])) {
$target = $this->configuration['target'];
// See if the database info is in state - if not, fallback to
// configuration.
if (isset($this->configuration['database_state_key'])) {
$this->database = $this->setUpDatabase($this->state->get($this->configuration['database_state_key']));
}
else {
$target = 'default';
$this->database = $this->setUpDatabase($this->configuration);
}
if (isset($this->configuration['key'])) {
$key = $this->configuration['key'];
}
else {
$key = 'migrate';
}
if (isset($this->configuration['database'])) {
Database::addConnectionInfo($key, $target, $this->configuration['database']);
}
$this->database = Database::getConnection($target, $key);
}
return $this->database;
}
/**
* Get a connection to the referenced database, adding the connection if
* necessary.
*
* @param array $database_info
* Configuration for the source database connection. The keys are:
* 'key' - The database connection key.
* 'target' - The database connection target.
* 'database' - Database configuration array as accepted by
* Database::addConnectionInfo.
*
* @return \Drupal\Core\Database\Connection
* The connection to use for this plugin's queries.
*/
protected function setUpDatabase(array $database_info) {
if (isset($database_info['key'])) {
$key = $database_info['key'];
}
else {
$key = 'migrate';
}
if (isset($database_info['target'])) {
$target = $database_info['target'];
}
else {
$target = 'default';
}
if (isset($database_info['database'])) {
Database::addConnectionInfo($key, $target, $database_info['database']);
}
return Database::getConnection($target, $key);
}
/**
* Wrapper for database select.
*/
@ -135,7 +184,7 @@ abstract class SqlBase extends SourcePluginBase {
$delimiter = '';
foreach ($this->getIds() as $field_name => $field_schema) {
if (isset($field_schema['alias'])) {
$field_name = $field_schema['alias'] . '.' . $field_name;
$field_name = $field_schema['alias'] . '.' . $this->query->escapeField($field_name);
}
$map_join .= "$delimiter$field_name = map.sourceid" . $count++;
$delimiter = ' AND ';