updated core to 8.6.1 via composer

This commit is contained in:
2018-09-12 13:58:26 +02:00
parent a9a219f2ed
commit ea56b9fba3
4443 changed files with 112098 additions and 40708 deletions
@@ -13,7 +13,7 @@ use Drupal\Component\Annotation\Plugin;
* \Drupal\migrate\Plugin\migrate\destination\UrlAlias
*
* @see \Drupal\migrate\Plugin\MigrateDestinationInterface
* @see \Drupal\migrate\Plugin\destination\DestinationBase
* @see \Drupal\migrate\Plugin\migrate\destination\DestinationBase
* @see \Drupal\migrate\Plugin\MigrateDestinationPluginManager
* @see \Drupal\migrate\Annotation\MigrateSource
* @see \Drupal\migrate\Annotation\MigrateProcessPlugin
@@ -221,7 +221,9 @@ class MigrateExecutable implements MigrateExecutableInterface {
if ($save) {
try {
$this->getEventDispatcher()->dispatch(MigrateEvents::PRE_ROW_SAVE, new MigratePreRowSaveEvent($this->migration, $this->message, $row));
$destination_id_values = $destination->import($row, $id_map->lookupDestinationId($this->sourceIdValues));
$destination_ids = $id_map->lookupDestinationIds($this->sourceIdValues);
$destination_id_values = $destination_ids ? reset($destination_ids) : [];
$destination_id_values = $destination->import($row, $destination_id_values);
$this->getEventDispatcher()->dispatch(MigrateEvents::POST_ROW_SAVE, new MigratePostRowSaveEvent($this->migration, $this->message, $row, $destination_id_values));
if ($destination_id_values) {
// We do not save an idMap entry for config.
@@ -29,7 +29,7 @@ interface MigrateExecutableInterface {
* Usually setting this is not necessary as $process typically starts with
* a 'get'. This is useful only when the $process contains a single
* destination and needs to access a value outside of the source. See
* \Drupal\migrate\Plugin\migrate\process\Iterator::transformKey for an
* \Drupal\migrate\Plugin\migrate\process\SubProcess::transformKey for an
* example.
*
* @throws \Drupal\migrate\MigrateException
@@ -48,7 +48,6 @@ class AnnotatedClassDiscoveryAutomatedProviders extends AnnotatedClassDiscovery
$this->finder = new ClassFinder();
}
/**
* {@inheritdoc}
*/
@@ -11,7 +11,7 @@ use Drupal\migrate\Row;
* Destinations are responsible for persisting source data into the destination
* Drupal.
*
* @see \Drupal\migrate\Plugin\destination\DestinationBase
* @see \Drupal\migrate\Plugin\migrate\destination\DestinationBase
* @see \Drupal\migrate\Plugin\MigrateDestinationPluginManager
* @see \Drupal\migrate\Annotation\MigrateDestination
* @see plugin_api
@@ -10,7 +10,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface;
* Plugin manager for migrate destination plugins.
*
* @see \Drupal\migrate\Plugin\MigrateDestinationInterface
* @see \Drupal\migrate\Plugin\destination\DestinationBase
* @see \Drupal\migrate\Plugin\migrate\destination\DestinationBase
* @see \Drupal\migrate\Annotation\MigrateDestination
* @see plugin_api
*
@@ -103,7 +103,6 @@ interface MigrateIdMapInterface extends \Iterator, PluginInspectionInterface {
*/
public function importedCount();
/**
* Returns a count of items which are marked as needing update.
*
@@ -197,7 +196,7 @@ interface MigrateIdMapInterface extends \Iterator, PluginInspectionInterface {
* 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);
public function lookupSourceId(array $destination_id_values);
/**
* Looks up the destination identifier corresponding to a source key.
@@ -9,11 +9,16 @@ use Drupal\migrate\Row;
/**
* An interface for migrate process plugins.
*
* A process plugin can use any number of methods instead of (but not in
* addition to) transform with the same arguments and then the plugin
* configuration needs to provide the name of the method to be called via the
* "method" key. See \Drupal\migrate\Plugin\migrate\process\SkipOnEmpty and
* migrate.migration.d6_field_instance_widget_settings.yml for examples.
* A process plugin will typically implement the transform() method to perform
* its work. However, it is possible instead for a process plugin to use any
* number of methods, thus offering different alternatives ways of processing.
* In this case, the transform() method should not be implemented, and the
* plugin configuration must provide the name of the method to be called via the
* "method" key. Each method must have the same signature as transform().
* The base class \Drupal\migrate\ProcessPluginBase takes care of implementing
* transform() and calling the configured method. See
* \Drupal\migrate\Plugin\migrate\process\SkipOnEmpty and
* d6_field_instance_widget_settings.yml for examples.
*
* @see \Drupal\migrate\Plugin\MigratePluginManager
* @see \Drupal\migrate\ProcessPluginBase
@@ -87,10 +87,10 @@ interface MigrateSourceInterface extends \Countable, \Iterator, PluginInspection
*
* Additional custom keys/values that are not part of field storage
* definition can be added as shown below. The most common setting
* passed along to the ID definition is 'alias', used by the SqlBase source
* plugin in order to distinguish between ambiguous column names - for
* example, when a SQL source query joins two tables with the same column
* names.
* passed along to the ID definition is table 'alias', used by the SqlBase
* source plugin in order to distinguish between ambiguous column names -
* for example, when a SQL source query joins two tables with the same
* column names.
* @code
* return [
* 'nid' => [
@@ -410,7 +410,7 @@ class Migration extends PluginBase implements MigrationInterface, RequirementsIn
*/
public function getDestinationPlugin($stub_being_requested = FALSE) {
if ($stub_being_requested && !empty($this->destination['no_stub'])) {
throw new MigrateSkipRowException();
throw new MigrateSkipRowException('Stub requested but not made because no_stub configuration is set.');
}
if (!isset($this->destinationPlugin)) {
$this->destinationPlugin = $this->destinationPluginManager->createInstance($this->destination['plugin'], $this->destination, $this);
@@ -554,7 +554,6 @@ class Migration extends PluginBase implements MigrationInterface, RequirementsIn
return $this;
}
/**
* {@inheritdoc}
*/
@@ -620,19 +619,22 @@ class Migration extends PluginBase implements MigrationInterface, RequirementsIn
}
/**
* Find migration dependencies from the migration and the iterator plugins.
* Find migration dependencies from migration_lookup and sub_process plugins.
*
* @param array $process
* A process configuration array.
*
* @param $process
* @return array
* The migration dependencies.
*/
protected function findMigrationDependencies($process) {
$return = [];
foreach ($this->getProcessNormalized($process) as $process_pipeline) {
foreach ($process_pipeline as $plugin_configuration) {
if ($plugin_configuration['plugin'] == 'migration') {
if (in_array($plugin_configuration['plugin'], ['migration', 'migration_lookup'], TRUE)) {
$return = array_merge($return, (array) $plugin_configuration['migration']);
}
if ($plugin_configuration['plugin'] == 'sub_process') {
if (in_array($plugin_configuration['plugin'], ['iterator', 'sub_process'], TRUE)) {
$return = array_merge($return, $this->findMigrationDependencies($plugin_configuration['process']));
}
}
@@ -83,7 +83,7 @@ class MigrationPluginManager extends DefaultPluginManager implements MigrationPl
// This gets rid of migrations which try to use a non-existent source
// plugin. The common case for this is if the source plugin has, or
// specifies, a non-existent provider.
$only_with_source_discovery = new NoSourcePluginDecorator($yaml_discovery);
$only_with_source_discovery = new NoSourcePluginDecorator($yaml_discovery);
// This gets rid of migrations with explicit providers set if one of the
// providers do not exist before we try to use a potentially non-existing
// deriver. This is a rare case.
@@ -160,7 +160,6 @@ class MigrationPluginManager extends DefaultPluginManager implements MigrationPl
return $plugin_ids;
}
/**
* {@inheritdoc}
*/
@@ -12,7 +12,7 @@ use Drupal\migrate\Plugin\RequirementsInterface;
/**
* Base class for migrate destination classes.
*
* Migrate destination plugins perfom the import operation of the migration.
* Migrate destination plugins perform the import operation of the migration.
* Destination plugins extend this abstract base class. A destination plugin
* must implement at least fields(), getIds() and import() methods. Destination
* plugins can also support rollback operations. For more
@@ -72,7 +72,7 @@ class EntityConfigBase extends Entity {
/**
* The configuration factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface;
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
@@ -148,7 +148,7 @@ class EntityContentBase extends Entity implements HighestIdInterface {
}
$ids = $this->save($entity, $old_destination_id_values);
if (!empty($this->configuration['translations'])) {
if ($this->isTranslationDestination()) {
$ids[] = $entity->language()->getId();
}
return $ids;
@@ -181,12 +181,15 @@ class EntityContentBase extends Entity implements HighestIdInterface {
* {@inheritdoc}
*/
public function getIds() {
$ids = [];
$id_key = $this->getKey('id');
$ids[$id_key] = $this->getDefinitionFromEntity($id_key);
if ($this->isTranslationDestination()) {
if (!$langcode_key = $this->getKey('langcode')) {
throw new MigrateException('This entity type does not support translation.');
$langcode_key = $this->getKey('langcode');
if (!$langcode_key) {
throw new MigrateException(sprintf('The "%s" entity type does not support translations.', $this->storage->getEntityTypeId()));
}
$ids[$langcode_key] = $this->getDefinitionFromEntity($langcode_key);
}
@@ -202,8 +205,8 @@ class EntityContentBase extends Entity implements HighestIdInterface {
* @param \Drupal\migrate\Row $row
* The row object to update from.
*
* @return \Drupal\Core\Entity\EntityInterface|null
* An updated entity, or NULL if it's the same as the one passed in.
* @return \Drupal\Core\Entity\EntityInterface
* An updated entity from row values.
*/
protected function updateEntity(EntityInterface $entity, Row $row) {
$empty_destinations = $row->getEmptyDestinationProperties();
@@ -160,7 +160,9 @@ class EntityRevision extends EntityContentBase {
$entity->enforceIsNew(FALSE);
$entity->setNewRevision(TRUE);
}
$this->updateEntity($entity, $row);
// We need to update the entity, so that the destination row IDs are
// correct.
$entity = $this->updateEntity($entity, $row);
$entity->isDefaultRevision(FALSE);
return $entity;
}
@@ -177,10 +179,23 @@ class EntityRevision extends EntityContentBase {
* {@inheritdoc}
*/
public function getIds() {
if ($key = $this->getKey('revision')) {
return [$key => $this->getDefinitionFromEntity($key)];
$ids = [];
$revision_key = $this->getKey('revision');
if (!$revision_key) {
throw new MigrateException(sprintf('The "%s" entity type does not support revisions.', $this->storage->getEntityTypeId()));
}
throw new MigrateException('This entity type does not support revisions.');
$ids[$revision_key] = $this->getDefinitionFromEntity($revision_key);
if ($this->isTranslationDestination()) {
$langcode_key = $this->getKey('langcode');
if (!$langcode_key) {
throw new MigrateException(sprintf('The "%s" entity type does not support translations.', $this->storage->getEntityTypeId()));
}
$ids[$langcode_key] = $this->getDefinitionFromEntity($langcode_key);
}
return $ids;
}
/**
@@ -48,7 +48,7 @@ class NullIdMap extends PluginBase implements MigrateIdMapInterface {
/**
* {@inheritdoc}
*/
public function lookupSourceID(array $destination_id_values) {
public function lookupSourceId(array $destination_id_values) {
return [];
}
@@ -2,7 +2,7 @@
namespace Drupal\migrate\Plugin\migrate\id_map;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Database\DatabaseException;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginBase;
@@ -161,6 +161,18 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
$this->migration = $migration;
$this->eventDispatcher = $event_dispatcher;
$this->message = new MigrateMessage();
if (!isset($this->database)) {
$this->database = \Drupal::database();
}
// Default generated table names, limited to 63 characters.
$machine_name = str_replace(':', '__', $this->migration->id());
$prefix_length = strlen($this->database->tablePrefix());
$this->mapTableName = 'migrate_map_' . mb_strtolower($machine_name);
$this->mapTableName = mb_substr($this->mapTableName, 0, 63 - $prefix_length);
$this->messageTableName = 'migrate_message_' . mb_strtolower($machine_name);
$this->messageTableName = mb_substr($this->messageTableName, 0, 63 - $prefix_length);
}
/**
@@ -187,7 +199,7 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
* @return string
* An hash containing the hashed values of the source identifiers.
*/
public function getSourceIDsHash(array $source_id_values) {
public function getSourceIdsHash(array $source_id_values) {
// When looking up the destination ID we require an array with both the
// source key and value, e.g. ['nid' => 41]. In this case, $source_id_values
// need to be ordered the same order as $this->sourceIdFields().
@@ -246,7 +258,6 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
* The map table name.
*/
public function mapTableName() {
$this->init();
return $this->mapTableName;
}
@@ -257,7 +268,6 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
* The message table name.
*/
public function messageTableName() {
$this->init();
return $this->messageTableName;
}
@@ -278,9 +288,6 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
* The database connection object.
*/
public function getDatabase() {
if (!isset($this->database)) {
$this->database = \Drupal::database();
}
$this->init();
return $this->database;
}
@@ -291,13 +298,6 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
protected function init() {
if (!$this->initialized) {
$this->initialized = TRUE;
// Default generated table names, limited to 63 characters.
$machine_name = str_replace(':', '__', $this->migration->id());
$prefix_length = strlen($this->getDatabase()->tablePrefix());
$this->mapTableName = 'migrate_map_' . Unicode::strtolower($machine_name);
$this->mapTableName = Unicode::substr($this->mapTableName, 0, 63 - $prefix_length);
$this->messageTableName = 'migrate_message_' . Unicode::strtolower($machine_name);
$this->messageTableName = Unicode::substr($this->messageTableName, 0, 63 - $prefix_length);
$this->ensureTables();
}
}
@@ -491,7 +491,7 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
public function getRowBySource(array $source_id_values) {
$query = $this->getDatabase()->select($this->mapTableName(), 'map')
->fields('map');
$query->condition(static::SOURCE_IDS_HASH, $this->getSourceIDsHash($source_id_values));
$query->condition(static::SOURCE_IDS_HASH, $this->getSourceIdsHash($source_id_values));
$result = $query->execute();
return $result->fetchAssoc();
}
@@ -528,7 +528,7 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
/**
* {@inheritdoc}
*/
public function lookupSourceID(array $destination_id_values) {
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) {
@@ -562,9 +562,13 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
$conditions = [];
foreach ($this->sourceIdFields() as $field_name => $db_field) {
if ($is_associative) {
// Associative $source_id_values can have fields out of order.
if (isset($source_id_values[$field_name])) {
$conditions[$db_field] = $source_id_values[$field_name];
// Ensure to handle array elements with a NULL value.
if (array_key_exists($field_name, $source_id_values)) {
// Associative $source_id_values can have fields out of order.
if (isset($source_id_values[$field_name])) {
// Only add a condition if the value is not NULL.
$conditions[$db_field] = $source_id_values[$field_name];
}
unset($source_id_values[$field_name]);
}
}
@@ -579,14 +583,15 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
}
if (!empty($source_id_values)) {
throw new MigrateException("Extra unknown items in source IDs");
$var_dump = var_export($source_id_values, TRUE);
throw new MigrateException(sprintf("Extra unknown items in source IDs: %s", $var_dump));
}
$query = $this->getDatabase()->select($this->mapTableName(), 'map')
->fields('map', $this->destinationIdFields());
if (count($this->sourceIdFields()) === count($conditions)) {
// Optimization: Use the primary key.
$query->condition(self::SOURCE_IDS_HASH, $this->getSourceIDsHash(array_values($conditions)));
$query->condition(self::SOURCE_IDS_HASH, $this->getSourceIdsHash(array_values($conditions)));
}
else {
foreach ($conditions as $db_field => $value) {
@@ -636,7 +641,7 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
if ($this->migration->getTrackLastImported()) {
$fields['last_imported'] = time();
}
$keys = [static::SOURCE_IDS_HASH => $this->getSourceIDsHash($source_id_values)];
$keys = [static::SOURCE_IDS_HASH => $this->getSourceIdsHash($source_id_values)];
// Notify anyone listening of the map row we're about to save.
$this->eventDispatcher->dispatch(MigrateEvents::MAP_SAVE, new MigrateMapSaveEvent($this, $fields));
$this->getDatabase()->merge($this->mapTableName())
@@ -655,7 +660,7 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
return;
}
}
$fields[static::SOURCE_IDS_HASH] = $this->getSourceIDsHash($source_id_values);
$fields[static::SOURCE_IDS_HASH] = $this->getSourceIdsHash($source_id_values);
$fields['level'] = $level;
$fields['message'] = $message;
$this->getDatabase()->insert($this->messageTableName())
@@ -674,7 +679,7 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
$query = $this->getDatabase()->select($this->messageTableName(), 'msg')
->fields('msg');
if ($source_id_values) {
$query->condition(static::SOURCE_IDS_HASH, $this->getSourceIDsHash($source_id_values));
$query->condition(static::SOURCE_IDS_HASH, $this->getSourceIdsHash($source_id_values));
}
if ($level) {
@@ -696,21 +701,17 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
* {@inheritdoc}
*/
public function processedCount() {
return (int) $this->getDatabase()->select($this->mapTableName())
->countQuery()
->execute()
->fetchField();
return $this->countHelper(NULL, $this->mapTableName());
}
/**
* {@inheritdoc}
*/
public function importedCount() {
return (int) $this->getDatabase()->select($this->mapTableName())
->condition('source_row_status', [MigrateIdMapInterface::STATUS_IMPORTED, MigrateIdMapInterface::STATUS_NEEDS_UPDATE], 'IN')
->countQuery()
->execute()
->fetchField();
return $this->countHelper([
MigrateIdMapInterface::STATUS_IMPORTED,
MigrateIdMapInterface::STATUS_NEEDS_UPDATE,
]);
}
/**
@@ -737,20 +738,28 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
/**
* Counts records in a table.
*
* @param int $status
* An integer for the source_row_status column.
* @param int|array $status
* (optional) Status code(s) to filter the source_row_status column.
* @param string $table
* (optional) The table to work. Defaults to NULL.
*
* @return int
* The number of records.
*/
protected function countHelper($status, $table = NULL) {
$query = $this->getDatabase()->select($table ?: $this->mapTableName());
protected function countHelper($status = NULL, $table = NULL) {
// Use database directly to avoid creating tables.
$query = $this->database->select($table ?: $this->mapTableName());
if (isset($status)) {
$query->condition('source_row_status', $status);
$query->condition('source_row_status', $status, is_array($status) ? 'IN' : '=');
}
return (int) $query->countQuery()->execute()->fetchField();
try {
$count = (int) $query->countQuery()->execute()->fetchField();
}
catch (DatabaseException $e) {
// The table does not exist, therefore there are no records.
$count = 0;
}
return $count;
}
/**
@@ -763,13 +772,13 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
if (!$messages_only) {
$map_query = $this->getDatabase()->delete($this->mapTableName());
$map_query->condition(static::SOURCE_IDS_HASH, $this->getSourceIDsHash($source_id_values));
$map_query->condition(static::SOURCE_IDS_HASH, $this->getSourceIdsHash($source_id_values));
// Notify anyone listening of the map row we're about to delete.
$this->eventDispatcher->dispatch(MigrateEvents::MAP_DELETE, new MigrateMapDeleteEvent($this, $source_id_values));
$map_query->execute();
}
$message_query = $this->getDatabase()->delete($this->messageTableName());
$message_query->condition(static::SOURCE_IDS_HASH, $this->getSourceIDsHash($source_id_values));
$message_query->condition(static::SOURCE_IDS_HASH, $this->getSourceIdsHash($source_id_values));
$message_query->execute();
}
@@ -779,7 +788,7 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
public function deleteDestination(array $destination_id_values) {
$map_query = $this->getDatabase()->delete($this->mapTableName());
$message_query = $this->getDatabase()->delete($this->messageTableName());
$source_id_values = $this->lookupSourceID($destination_id_values);
$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]);
@@ -788,7 +797,7 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
$this->eventDispatcher->dispatch(MigrateEvents::MAP_DELETE, new MigrateMapDeleteEvent($this, $source_id_values));
$map_query->execute();
$message_query->condition(static::SOURCE_IDS_HASH, $this->getSourceIDsHash($source_id_values));
$message_query->condition(static::SOURCE_IDS_HASH, $this->getSourceIdsHash($source_id_values));
$message_query->execute();
}
}
@@ -976,8 +985,9 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
// Get the highest id from the list of map tables.
$ids = [0];
foreach ($map_tables as $map_table) {
// If the map_table does not exist then continue on to the next map_table.
if (!$this->getDatabase()->schema()->tableExists($map_table)) {
break;
continue;
}
$query = $this->getDatabase()->select($map_table, 'map')
@@ -49,11 +49,21 @@ class Callback extends ProcessPluginBase {
/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if (is_callable($this->configuration['callable'])) {
$value = call_user_func($this->configuration['callable'], $value);
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
if (!isset($configuration['callable'])) {
throw new \InvalidArgumentException('The "callable" must be set.');
}
return $value;
elseif (!is_callable($configuration['callable'])) {
throw new \InvalidArgumentException('The "callable" must be a valid function or method.');
}
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
return call_user_func($this->configuration['callable'], $value);
}
}
@@ -6,7 +6,6 @@ use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
use GuzzleHttp\Client;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -19,8 +18,12 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
* - destination URI, e.g. 'public://images/foo.img'
*
* Available configuration keys:
* - rename: (optional) If set, a unique destination URI is generated. If not
* set, the destination URI will be overwritten if it exists.
* - file_exists: (optional) Replace behavior when the destination file already
* exists:
* - 'replace' - (default) Replace the existing file.
* - 'rename' - Append _{incrementing number} until the filename is
* unique.
* - 'use existing' - Do nothing and return FALSE.
* - guzzle_options: (optional)
* @link http://docs.guzzlephp.org/en/latest/request-options.html Array of request options for Guzzle. @endlink
*
@@ -42,7 +45,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
* source:
* - source_url
* - destination_uri
* rename: true
* file_exists: rename
* @endcode
*
* This will download source_url to destination_uri and ensure that the
@@ -53,7 +56,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
* id = "download"
* )
*/
class Download extends ProcessPluginBase implements ContainerFactoryPluginInterface {
class Download extends FileProcessBase implements ContainerFactoryPluginInterface {
/**
* The file system service.
@@ -85,7 +88,6 @@ class Download extends ProcessPluginBase implements ContainerFactoryPluginInterf
*/
public function __construct(array $configuration, $plugin_id, array $plugin_definition, FileSystemInterface $file_system, Client $http_client) {
$configuration += [
'rename' => FALSE,
'guzzle_options' => [],
];
parent::__construct($configuration, $plugin_id, $plugin_definition);
@@ -118,10 +120,12 @@ class Download extends ProcessPluginBase implements ContainerFactoryPluginInterf
list($source, $destination) = $value;
// Modify the destination filename if necessary.
$replace = !empty($this->configuration['rename']) ?
FILE_EXISTS_RENAME :
FILE_EXISTS_REPLACE;
$final_destination = file_destination($destination, $replace);
$final_destination = file_destination($destination, $this->configuration['file_exists']);
// Reuse if file exists.
if (!$final_destination) {
return $destination;
}
// Try opening the file first, to avoid calling file_prepare_directory()
// unnecessarily. We're suppressing fopen() errors because we want to try
@@ -9,7 +9,6 @@ use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Plugin\MigrateProcessInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -26,10 +25,12 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
* Available configuration keys:
* - move: (optional) Boolean, if TRUE, move the file, otherwise copy the file.
* Defaults to FALSE.
* - rename: (optional) Boolean, if TRUE, rename the file by appending a number
* until the name is unique. Defaults to FALSE.
* - reuse: (optional) Boolean, if TRUE, reuse the current file in its existing
* location rather than move/copy/rename the file. Defaults to FALSE.
* - file_exists: (optional) Replace behavior when the destination file already
* exists:
* - 'replace' - (default) Replace the existing file.
* - 'rename' - Append _{incrementing number} until the filename is
* unique.
* - 'use existing' - Do nothing and return FALSE.
*
* Examples:
*
@@ -48,7 +49,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
* id = "file_copy"
* )
*/
class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterface {
class FileCopy extends FileProcessBase implements ContainerFactoryPluginInterface {
/**
* The stream wrapper manager service.
@@ -90,8 +91,6 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf
public function __construct(array $configuration, $plugin_id, array $plugin_definition, StreamWrapperManagerInterface $stream_wrappers, FileSystemInterface $file_system, MigrateProcessInterface $download_plugin) {
$configuration += [
'move' => FALSE,
'rename' => FALSE,
'reuse' => FALSE,
];
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->streamWrapperManager = $stream_wrappers;
@@ -109,7 +108,7 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf
$plugin_definition,
$container->get('stream_wrapper_manager'),
$container->get('file_system'),
$container->get('plugin.manager.migrate.process')->createInstance('download')
$container->get('plugin.manager.migrate.process')->createInstance('download', $configuration)
);
}
@@ -150,7 +149,7 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf
}
}
$final_destination = $this->writeFile($source, $destination, $this->getOverwriteMode());
$final_destination = $this->writeFile($source, $destination, $this->configuration['file_exists']);
if ($final_destination) {
return $final_destination;
}
@@ -181,24 +180,6 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf
return $function($source, $destination, $replace);
}
/**
* Determines how to handle file conflicts.
*
* @return int
* FILE_EXISTS_REPLACE (default), FILE_EXISTS_RENAME, or FILE_EXISTS_ERROR
* depending on the current configuration.
*/
protected function getOverwriteMode() {
if (!empty($this->configuration['rename'])) {
return FILE_EXISTS_RENAME;
}
if (!empty($this->configuration['reuse'])) {
return FILE_EXISTS_ERROR;
}
return FILE_EXISTS_REPLACE;
}
/**
* Returns the directory component of a URI or path.
*
@@ -0,0 +1,59 @@
<?php
namespace Drupal\migrate\Plugin\migrate\process;
use Drupal\migrate\ProcessPluginBase;
/**
* Provides functionality for file process plugins.
*
* Available configuration keys:
* - file_exists: (optional) Replace behavior when the destination file already
* exists:
* - 'replace' - (default) Replace the existing file.
* - 'rename' - Append _{incrementing number} until the filename is
* unique.
* - 'use existing' - Do nothing and return FALSE.
*/
abstract class FileProcessBase extends ProcessPluginBase {
/**
* Constructs a file process plugin.
*
* @param array $configuration
* The plugin configuration.
* @param string $plugin_id
* The plugin ID.
* @param mixed $plugin_definition
* The plugin definition.
*/
public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
if (array_key_exists('file_exists', $configuration)) {
switch ($configuration['file_exists']) {
case 'use existing':
$configuration['file_exists'] = FILE_EXISTS_ERROR;
break;
case 'rename':
$configuration['file_exists'] = FILE_EXISTS_RENAME;
break;
default:
$configuration['file_exists'] = FILE_EXISTS_REPLACE;
}
}
if (array_key_exists('reuse', $configuration)) {
@trigger_error("Using the key 'reuse' is deprecated, use 'file_exists' => 'use existing' instead. See https://www.drupal.org/node/2981389.", E_USER_DEPRECATED);
if (!empty($configuration['reuse'])) {
$configuration['file_exists'] = FILE_EXISTS_ERROR;
}
}
if (array_key_exists('rename', $configuration)) {
@trigger_error("Using the key 'rename' is deprecated, use 'file_exists' => 'rename' instead. See https://www.drupal.org/node/2981389.", E_USER_DEPRECATED);
if (!empty($configuration['rename'])) {
$configuration['file_exists'] = FILE_EXISTS_RENAME;
}
}
$configuration += ['file_exists' => FILE_EXISTS_REPLACE];
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
}
@@ -70,8 +70,8 @@ use Drupal\migrate\Row;
* property bar. foo configuration is included for illustration purposes.
*
* Because of this, if the source or destination property actually starts with a
* @, that character must be escaped with @@.
* The referenced property becomes, for example, @@@foo.
* "@", that character must be escaped with "@@". The referenced property
* becomes, for example, "@@@foo".
*
* @code
* process:
@@ -6,7 +6,6 @@ use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Row;
use Drupal\migrate\MigrateException;
use Drupal\Component\Utility\Unicode;
/**
* This plugin ensures the source value is unique.
@@ -56,7 +55,7 @@ abstract class MakeUniqueBase extends ProcessPluginBase {
throw new MigrateException('The character length configuration key should be an integer. Omit this key to capture the entire string.');
}
// Use optional start or length to return a portion of the unique value.
$value = Unicode::substr($value, $start, $length);
$value = mb_substr($value, $start, $length);
$new_value = $value;
while ($this->exists($new_value)) {
$new_value = $value . $postfix . $i++;
@@ -134,7 +134,7 @@ class MakeUniqueEntityField extends MakeUniqueBase implements ContainerFactoryPl
$idMap = $this->migration->getIdMap();
foreach ($query->execute() as $id) {
$dest_id_values[$this->configuration['field']] = $id;
if ($idMap->lookupSourceID($dest_id_values)) {
if ($idMap->lookupSourceId($dest_id_values)) {
return TRUE;
}
}
@@ -97,7 +97,7 @@ class MenuLinkParent extends ProcessPluginBase implements ContainerFactoryPlugin
}
}
}
throw new MigrateSkipRowException();
throw new MigrateSkipRowException(sprintf("No parent link found for plid '%d' in menu '%s'.", $parent_id, $value[0]));
}
}
@@ -3,6 +3,7 @@
namespace Drupal\migrate\Plugin\migrate\process;
use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\Variable;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
@@ -140,7 +141,7 @@ class StaticMap extends ProcessPluginBase {
return $this->configuration['default_value'];
}
if (empty($this->configuration['bypass'])) {
throw new MigrateSkipRowException();
throw new MigrateSkipRowException(sprintf("No static mapping found for '%s' and no default value provided for destination '%s'.", Variable::export($value), $destination_property));
}
else {
return $value;
@@ -6,14 +6,12 @@ use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Row;
use Drupal\migrate\MigrateException;
use Drupal\Component\Utility\Unicode;
/**
* Returns a substring of the input value.
*
* The substr process plugin returns the portion of the input value specified by
* the start and length parameters. This is a wrapper around
* \Drupal\Component\Utility\Unicode::substr().
* the start and length parameters. This is a wrapper around mb_substr().
*
* Available configuration keys:
* - start: (optional) The returned string will start this many characters after
@@ -85,7 +83,7 @@ class Substr extends ProcessPluginBase {
}
// Use optional start or length to return a portion of $value.
$new_value = Unicode::substr($value, $start, $length);
$new_value = mb_substr($value, $start, $length);
return $new_value;
}
@@ -19,7 +19,8 @@ namespace Drupal\migrate\Plugin\migrate\source;
* elements, with values of 'user' and 'image', respectively.
*
* @MigrateSource(
* id = "empty"
* id = "empty",
* source_module = "migrate"
* )
*/
class EmptySource extends SourcePluginBase {
@@ -24,8 +24,11 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
* - target: (optional) The database target name. Defaults to 'default'.
* - batch_size: (optional) Number of records to fetch from the database during
* each batch. If omitted, all records are fetched in a single query.
* - ignore_map: (optional) Source data is joined to the map table by default.
* If set to TRUE, the map table will not be joined.
* - ignore_map: (optional) Source data is joined to the map table by default to
* improve migration performance. If set to TRUE, the map table will not be
* joined. Using expressions in the query may result in column aliases in the
* JOIN clause which would be invalid SQL. If you run into this, set
* ignore_map to TRUE.
*
* For other optional configuration keys inherited from the parent class, refer
* to \Drupal\migrate\Plugin\migrate\source\SourcePluginBase.