Update to Drupal 8.2.2. For more information, see https://www.drupal.org/project/drupal/releases/8.2.2
This commit is contained in:
parent
23ffed3665
commit
507b45a0ed
378 changed files with 11434 additions and 5542 deletions
|
@ -66,13 +66,6 @@ class MigrateExecutable implements MigrateExecutableInterface {
|
|||
*/
|
||||
protected $counts = array();
|
||||
|
||||
/**
|
||||
* The object currently being constructed.
|
||||
*
|
||||
* @var \stdClass
|
||||
*/
|
||||
protected $destinationValues;
|
||||
|
||||
/**
|
||||
* The source.
|
||||
*
|
||||
|
@ -80,13 +73,6 @@ class MigrateExecutable implements MigrateExecutableInterface {
|
|||
*/
|
||||
protected $source;
|
||||
|
||||
/**
|
||||
* The current data row retrieved from the source.
|
||||
*
|
||||
* @var \stdClass
|
||||
*/
|
||||
protected $sourceValues;
|
||||
|
||||
/**
|
||||
* The event dispatcher.
|
||||
*
|
||||
|
@ -94,6 +80,15 @@ class MigrateExecutable implements MigrateExecutableInterface {
|
|||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
* Migration message service.
|
||||
*
|
||||
* @todo https://www.drupal.org/node/2822663 Make this protected.
|
||||
*
|
||||
* @var \Drupal\migrate\MigrateMessageInterface
|
||||
*/
|
||||
public $message;
|
||||
|
||||
/**
|
||||
* Constructs a MigrateExecutable and verifies and sets the memory limit.
|
||||
*
|
||||
|
@ -229,7 +224,12 @@ class MigrateExecutable implements MigrateExecutableInterface {
|
|||
$save = FALSE;
|
||||
}
|
||||
catch (MigrateSkipRowException $e) {
|
||||
$id_map->saveIdMapping($row, array(), MigrateIdMapInterface::STATUS_IGNORED);
|
||||
if ($e->getSaveToMap()) {
|
||||
$id_map->saveIdMapping($row, [], MigrateIdMapInterface::STATUS_IGNORED);
|
||||
}
|
||||
if ($message = trim($e->getMessage())) {
|
||||
$this->saveMessage($message, MigrationInterface::MESSAGE_INFORMATIONAL);
|
||||
}
|
||||
$save = FALSE;
|
||||
}
|
||||
|
||||
|
@ -263,8 +263,6 @@ class MigrateExecutable implements MigrateExecutableInterface {
|
|||
}
|
||||
}
|
||||
|
||||
// Reset row properties.
|
||||
unset($sourceValues, $destinationValues);
|
||||
$this->sourceRowStatus = MigrateIdMapInterface::STATUS_IMPORTED;
|
||||
|
||||
// Check for memory exhaustion.
|
||||
|
|
|
@ -21,15 +21,59 @@ use Drupal\migrate\Row;
|
|||
interface MigrateDestinationInterface extends PluginInspectionInterface {
|
||||
|
||||
/**
|
||||
* Get the destination IDs.
|
||||
* Gets the destination IDs.
|
||||
*
|
||||
* To support MigrateIdMap maps, derived destination classes should return
|
||||
* schema field definition(s) corresponding to the primary key of the
|
||||
* destination being implemented. These are used to construct the destination
|
||||
* key fields of the map table for a migration using this destination.
|
||||
* field definition(s) corresponding to the primary key of the destination
|
||||
* being implemented. These are used to construct the destination key fields
|
||||
* of the map table for a migration using this destination.
|
||||
*
|
||||
* @return array
|
||||
* An array of IDs.
|
||||
* @return array[]
|
||||
* An associative array of field definitions keyed by field ID. Values are
|
||||
* associative arrays with a structure that contains the field type ('type'
|
||||
* key). The other keys are the field storage settings as they are returned
|
||||
* by FieldStorageDefinitionInterface::getSettings(). As an example, for a
|
||||
* composite destination primary key that is defined by an integer and a
|
||||
* string, the returned value might look like:
|
||||
* @code
|
||||
* return [
|
||||
* 'id' => [
|
||||
* 'type' => 'integer',
|
||||
* 'unsigned' => FALSE,
|
||||
* 'size' => 'big',
|
||||
* ],
|
||||
* 'version' => [
|
||||
* 'type' => 'string',
|
||||
* 'max_length' => 64,
|
||||
* 'is_ascii' => TRUE,
|
||||
* ],
|
||||
* ];
|
||||
* @endcode
|
||||
* If 'type' points to a field plugin with multiple columns and needs to
|
||||
* refer to a column different than 'value', the key of that column will be
|
||||
* appended as a suffix to the plugin name, separated by dot ('.'). Example:
|
||||
* @code
|
||||
* return [
|
||||
* 'format' => [
|
||||
* 'type' => 'text.format',
|
||||
* ],
|
||||
* ];
|
||||
* @endcode
|
||||
* Additional custom keys/values, that are not part of field storage
|
||||
* definition, can be passed in definitions:
|
||||
* @code
|
||||
* return [
|
||||
* 'nid' => [
|
||||
* 'type' => 'integer',
|
||||
* 'custom_setting' => 'some_value',
|
||||
* ],
|
||||
* ];
|
||||
* @endcode
|
||||
*
|
||||
* @see \Drupal\Core\Field\FieldStorageDefinitionInterface::getSettings()
|
||||
* @see \Drupal\Core\Field\Plugin\Field\FieldType\IntegerItem
|
||||
* @see \Drupal\Core\Field\Plugin\Field\FieldType\StringItem
|
||||
* @see \Drupal\text\Plugin\Field\FieldType\TextItem
|
||||
*/
|
||||
public function getIds();
|
||||
|
||||
|
|
|
@ -41,8 +41,7 @@ class MigratePluginManager extends DefaultPluginManager implements MigratePlugin
|
|||
* 'Drupal\Component\Annotation\PluginID'.
|
||||
*/
|
||||
public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, $annotation = 'Drupal\Component\Annotation\PluginID') {
|
||||
$plugin_interface = isset($plugin_interface_map[$type]) ? $plugin_interface_map[$type] : NULL;
|
||||
parent::__construct("Plugin/migrate/$type", $namespaces, $module_handler, $plugin_interface, $annotation);
|
||||
parent::__construct("Plugin/migrate/$type", $namespaces, $module_handler, NULL, $annotation);
|
||||
$this->alterInfo('migrate_' . $type . '_info');
|
||||
$this->setCacheBackend($cache_backend, 'migrate_plugins_' . $type);
|
||||
}
|
||||
|
|
|
@ -49,9 +49,54 @@ interface MigrateSourceInterface extends \Countable, \Iterator, PluginInspection
|
|||
* prepareRow() or hook_migrate_prepare_row() to rewrite NULL values to
|
||||
* appropriate empty values (such as '' or 0).
|
||||
*
|
||||
* @return array
|
||||
* Array keyed by source field name, with values being a schema array
|
||||
* describing the field (such as ['type' => 'string]).
|
||||
* @return array[]
|
||||
* An associative array of field definitions keyed by field ID. Values are
|
||||
* associative arrays with a structure that contains the field type ('type'
|
||||
* key). The other keys are the field storage settings as they are returned
|
||||
* by FieldStorageDefinitionInterface::getSettings(). As an example, for a
|
||||
* composite source primary key that is defined by an integer and a
|
||||
* string, the returned value might look like:
|
||||
* @code
|
||||
* return [
|
||||
* 'id' => [
|
||||
* 'type' => 'integer',
|
||||
* 'unsigned' => FALSE,
|
||||
* 'size' => 'big',
|
||||
* ],
|
||||
* 'version' => [
|
||||
* 'type' => 'string',
|
||||
* 'max_length' => 64,
|
||||
* 'is_ascii' => TRUE,
|
||||
* ],
|
||||
* ];
|
||||
* @endcode
|
||||
* If 'type' points to a field plugin with multiple columns and needs to
|
||||
* refer to a column different than 'value', the key of that column will be
|
||||
* appended as a suffix to the plugin name, separated by dot ('.'). Example:
|
||||
* @code
|
||||
* return [
|
||||
* 'format' => [
|
||||
* 'type' => 'text.format',
|
||||
* ],
|
||||
* ];
|
||||
* @endcode
|
||||
* Additional custom keys/values, that are not part of field storage
|
||||
* definition, can be passed in definitions. The most common setting, passed
|
||||
* along the ID definition, is 'alias' used by SqlBase source plugin:
|
||||
* @code
|
||||
* return [
|
||||
* 'nid' => [
|
||||
* 'type' => 'integer',
|
||||
* 'alias' => 'n',
|
||||
* ],
|
||||
* ];
|
||||
* @endcode
|
||||
*
|
||||
* @see \Drupal\Core\Field\FieldStorageDefinitionInterface::getSettings()
|
||||
* @see \Drupal\Core\Field\Plugin\Field\FieldType\IntegerItem
|
||||
* @see \Drupal\Core\Field\Plugin\Field\FieldType\StringItem
|
||||
* @see \Drupal\text\Plugin\Field\FieldType\TextItem
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SqlBase
|
||||
*/
|
||||
public function getIds();
|
||||
|
||||
|
|
|
@ -125,15 +125,13 @@ class EntityContentBase extends Entity {
|
|||
*/
|
||||
public function getIds() {
|
||||
$id_key = $this->getKey('id');
|
||||
$ids[$id_key]['type'] = 'integer';
|
||||
$ids[$id_key] = $this->getDefinitionFromEntity($id_key);
|
||||
|
||||
if ($this->isTranslationDestination()) {
|
||||
if ($key = $this->getKey('langcode')) {
|
||||
$ids[$key]['type'] = 'string';
|
||||
}
|
||||
else {
|
||||
if (!$langcode_key = $this->getKey('langcode')) {
|
||||
throw new MigrateException('This entity type does not support translation.');
|
||||
}
|
||||
$ids[$langcode_key] = $this->getDefinitionFromEntity($langcode_key);
|
||||
}
|
||||
|
||||
return $ids;
|
||||
|
@ -263,4 +261,32 @@ class EntityContentBase extends Entity {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field definition from a specific entity base field.
|
||||
*
|
||||
* The method takes the field ID as an argument and returns the field storage
|
||||
* definition to be used in getIds() by querying the destination entity base
|
||||
* field definition.
|
||||
*
|
||||
* @param string $key
|
||||
* The field ID key.
|
||||
*
|
||||
* @return array
|
||||
* An associative array with a structure that contains the field type, keyed
|
||||
* as 'type', together with field storage settings as they are returned by
|
||||
* FieldStorageDefinitionInterface::getSettings().
|
||||
*
|
||||
* @see \Drupal\Core\Field\FieldStorageDefinitionInterface::getSettings()
|
||||
*/
|
||||
protected function getDefinitionFromEntity($key) {
|
||||
$entity_type_id = static::getEntityTypeId($this->getPluginId());
|
||||
/** @var \Drupal\Core\Field\FieldStorageDefinitionInterface[] $definitions */
|
||||
$definitions = $this->entityManager->getBaseFieldDefinitions($entity_type_id);
|
||||
$field_definition = $definitions[$key];
|
||||
|
||||
return [
|
||||
'type' => $field_definition->getType(),
|
||||
] + $field_definition->getSettings();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -73,8 +73,7 @@ class EntityRevision extends EntityContentBase {
|
|||
*/
|
||||
public function getIds() {
|
||||
if ($key = $this->getKey('revision')) {
|
||||
$ids[$key]['type'] = 'integer';
|
||||
return $ids;
|
||||
return [$key => $this->getDefinitionFromEntity($key)];
|
||||
}
|
||||
throw new MigrateException('This entity type does not support revisions.');
|
||||
}
|
||||
|
|
|
@ -441,20 +441,40 @@ class Sql extends PluginBase implements MigrateIdMapInterface, ContainerFactoryP
|
|||
* Creates schema from an ID definition.
|
||||
*
|
||||
* @param array $id_definition
|
||||
* A field schema definition. Can be SQL schema or a type data
|
||||
* based schema. In the latter case, the value of type needs to be
|
||||
* $typed_data_type.$column.
|
||||
* The definition of the field having the structure as the items returned by
|
||||
* MigrateSourceInterface or MigrateDestinationInterface::getIds().
|
||||
*
|
||||
* @return array
|
||||
* The schema definition.
|
||||
* The database schema definition.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\MigrateSourceInterface::getIds()
|
||||
* @see \Drupal\migrate\Plugin\MigrateDestinationInterface::getIds()
|
||||
*/
|
||||
protected function getFieldSchema(array $id_definition) {
|
||||
$type_parts = explode('.', $id_definition['type']);
|
||||
if (count($type_parts) == 1) {
|
||||
$type_parts[] = 'value';
|
||||
}
|
||||
$schema = BaseFieldDefinition::create($type_parts[0])->getColumns();
|
||||
return $schema[$type_parts[1]];
|
||||
unset($id_definition['type']);
|
||||
|
||||
// Get the field storage definition.
|
||||
$definition = BaseFieldDefinition::create($type_parts[0]);
|
||||
|
||||
// Get a list of setting keys belonging strictly to the field definition.
|
||||
$default_field_settings = $definition->getSettings();
|
||||
// Separate field definition settings from custom settings. Custom settings
|
||||
// are settings passed in $id_definition that are not part of field storage
|
||||
// definition settings.
|
||||
$field_settings = array_intersect_key($id_definition, $default_field_settings);
|
||||
$custom_settings = array_diff_key($id_definition, $default_field_settings);
|
||||
|
||||
// Resolve schema from field storage definition settings.
|
||||
$schema = $definition
|
||||
->setSettings($field_settings)
|
||||
->getColumns()[$type_parts[1]];
|
||||
|
||||
// Merge back custom settings.
|
||||
return $schema + $custom_settings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
117
core/modules/migrate/src/Plugin/migrate/process/Download.php
Normal file
117
core/modules/migrate/src/Plugin/migrate/process/Download.php
Normal file
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\migrate\Plugin\migrate\process;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Downloads a file from a remote location into the local file system.
|
||||
*
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "download"
|
||||
* )
|
||||
*/
|
||||
class Download extends ProcessPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The file system service.
|
||||
*
|
||||
* @var \Drupal\Core\File\FileSystemInterface
|
||||
*/
|
||||
protected $fileSystem;
|
||||
|
||||
/**
|
||||
* The Guzzle HTTP Client service.
|
||||
*
|
||||
* @var \GuzzleHttp\Client
|
||||
*/
|
||||
protected $httpClient;
|
||||
|
||||
/**
|
||||
* Constructs a download process plugin.
|
||||
*
|
||||
* @param array $configuration
|
||||
* The plugin configuration.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin definition.
|
||||
* @param \Drupal\Core\File\FileSystemInterface $file_system
|
||||
* The file system service.
|
||||
* @param \GuzzleHttp\Client $http_client
|
||||
* The HTTP client.
|
||||
*/
|
||||
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);
|
||||
$this->fileSystem = $file_system;
|
||||
$this->httpClient = $http_client;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('file_system'),
|
||||
$container->get('http_client')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
// If we're stubbing a file entity, return a uri of NULL so it will get
|
||||
// stubbed by the general process.
|
||||
if ($row->isStub()) {
|
||||
return NULL;
|
||||
}
|
||||
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);
|
||||
|
||||
// Try opening the file first, to avoid calling file_prepare_directory()
|
||||
// unnecessarily. We're suppressing fopen() errors because we want to try
|
||||
// to prepare the directory before we give up and fail.
|
||||
$destination_stream = @fopen($final_destination, 'w');
|
||||
if (!$destination_stream) {
|
||||
// If fopen didn't work, make sure there's a writable directory in place.
|
||||
$dir = $this->fileSystem->dirname($final_destination);
|
||||
if (!file_prepare_directory($dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
|
||||
throw new MigrateException("Could not create or write to directory '$dir'");
|
||||
}
|
||||
// Let's try that fopen again.
|
||||
$destination_stream = @fopen($final_destination, 'w');
|
||||
if (!$destination_stream) {
|
||||
throw new MigrateException("Could not write to file '$final_destination'");
|
||||
}
|
||||
}
|
||||
|
||||
// Stream the request body directly to the final destination stream.
|
||||
$this->configuration['guzzle_options']['sink'] = $destination_stream;
|
||||
|
||||
// Make the request. Guzzle throws an exception for anything other than 200.
|
||||
$this->httpClient->get($source, $this->configuration['guzzle_options']);
|
||||
|
||||
return $final_destination;
|
||||
}
|
||||
|
||||
}
|
|
@ -14,7 +14,8 @@ use Drupal\migrate\Row;
|
|||
* @link https://www.drupal.org/node/2152731 Online handbook documentation for extract process plugin @endlink
|
||||
*
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "extract"
|
||||
* id = "extract",
|
||||
* handle_multiples = TRUE
|
||||
* )
|
||||
*/
|
||||
class Extract extends ProcessPluginBase {
|
||||
|
|
|
@ -8,6 +8,7 @@ use Drupal\Core\StreamWrapper\LocalStream;
|
|||
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;
|
||||
|
@ -35,6 +36,13 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf
|
|||
*/
|
||||
protected $fileSystem;
|
||||
|
||||
/**
|
||||
* An instance of the download process plugin.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrateProcessInterface
|
||||
*/
|
||||
protected $downloadPlugin;
|
||||
|
||||
/**
|
||||
* Constructs a file_copy process plugin.
|
||||
*
|
||||
|
@ -48,8 +56,10 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf
|
|||
* The stream wrapper manager service.
|
||||
* @param \Drupal\Core\File\FileSystemInterface $file_system
|
||||
* The file system service.
|
||||
* @param \Drupal\migrate\Plugin\MigrateProcessInterface $download_plugin
|
||||
* An instance of the download plugin for handling remote URIs.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, array $plugin_definition, StreamWrapperManagerInterface $stream_wrappers, FileSystemInterface $file_system) {
|
||||
public function __construct(array $configuration, $plugin_id, array $plugin_definition, StreamWrapperManagerInterface $stream_wrappers, FileSystemInterface $file_system, MigrateProcessInterface $download_plugin) {
|
||||
$configuration += array(
|
||||
'move' => FALSE,
|
||||
'rename' => FALSE,
|
||||
|
@ -58,6 +68,7 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf
|
|||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->streamWrapperManager = $stream_wrappers;
|
||||
$this->fileSystem = $file_system;
|
||||
$this->downloadPlugin = $download_plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,7 +80,8 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf
|
|||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('stream_wrapper_manager'),
|
||||
$container->get('file_system')
|
||||
$container->get('file_system'),
|
||||
$container->get('plugin.manager.migrate.process')->createInstance('download')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -84,8 +96,14 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf
|
|||
}
|
||||
list($source, $destination) = $value;
|
||||
|
||||
// If the source path or URI represents a remote resource, delegate to the
|
||||
// download plugin.
|
||||
if (!$this->isLocalUri($source)) {
|
||||
return $this->downloadPlugin->transform($value, $migrate_executable, $row, $destination_property);
|
||||
}
|
||||
|
||||
// Ensure the source file exists, if it's a local URI or path.
|
||||
if ($this->isLocalUri($source) && !file_exists($source)) {
|
||||
if (!file_exists($source)) {
|
||||
throw new MigrateException("File '$source' does not exist");
|
||||
}
|
||||
|
||||
|
@ -128,20 +146,14 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf
|
|||
* File destination on success, FALSE on failure.
|
||||
*/
|
||||
protected function writeFile($source, $destination, $replace = FILE_EXISTS_REPLACE) {
|
||||
if ($this->configuration['move']) {
|
||||
return file_unmanaged_move($source, $destination, $replace);
|
||||
}
|
||||
// Check if there is a destination available for copying. If there isn't,
|
||||
// it already exists at the destination and the replace flag tells us to not
|
||||
// replace it. In that case, return the original destination.
|
||||
if (!($final_destination = file_destination($destination, $replace))) {
|
||||
return $destination;
|
||||
}
|
||||
// We can't use file_unmanaged_copy because it will break with remote Urls.
|
||||
if (@copy($source, $final_destination)) {
|
||||
return $final_destination;
|
||||
}
|
||||
return FALSE;
|
||||
$function = 'file_unmanaged_' . ($this->configuration['move'] ? 'move' : 'copy');
|
||||
return $function($source, $destination, $replace);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,8 +199,6 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf
|
|||
/**
|
||||
* Determines if the source and destination URIs represent identical paths.
|
||||
*
|
||||
* If either URI is a remote stream, will return FALSE.
|
||||
*
|
||||
* @param string $source
|
||||
* The source URI.
|
||||
* @param string $destination
|
||||
|
@ -199,10 +209,7 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf
|
|||
* otherwise FALSE.
|
||||
*/
|
||||
protected function isLocationUnchanged($source, $destination) {
|
||||
if ($this->isLocalUri($source) && $this->isLocalUri($destination)) {
|
||||
return $this->fileSystem->realpath($source) === $this->fileSystem->realpath($destination);
|
||||
}
|
||||
return FALSE;
|
||||
return $this->fileSystem->realpath($source) === $this->fileSystem->realpath($destination);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -219,6 +226,13 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf
|
|||
*/
|
||||
protected function isLocalUri($uri) {
|
||||
$scheme = $this->fileSystem->uriScheme($uri);
|
||||
|
||||
// The vfs scheme is vfsStream, which is used in testing. vfsStream is a
|
||||
// simulated file system that exists only in memory, but should be treated
|
||||
// as a local resource.
|
||||
if ($scheme == 'vfs') {
|
||||
$scheme = FALSE;
|
||||
}
|
||||
return $scheme === FALSE || $this->streamWrapperManager->getViaScheme($scheme) instanceof LocalStream;
|
||||
}
|
||||
|
||||
|
|
|
@ -207,6 +207,9 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter
|
|||
catch (MigrateSkipRowException $e) {
|
||||
$skip = TRUE;
|
||||
$save_to_map = $e->getSaveToMap();
|
||||
if ($message = trim($e->getMessage())) {
|
||||
$this->idMap->saveMessage($row->getSourceIdValues(), $message, MigrationInterface::MESSAGE_INFORMATIONAL);
|
||||
}
|
||||
}
|
||||
|
||||
// We're explicitly skipping this row - keep track in the map table.
|
||||
|
|
|
@ -91,7 +91,7 @@ class Row {
|
|||
* @throws \InvalidArgumentException
|
||||
* Thrown when a source ID property does not exist.
|
||||
*/
|
||||
public function __construct(array $values, array $source_ids, $is_stub = FALSE) {
|
||||
public function __construct(array $values = [], array $source_ids = [], $is_stub = FALSE) {
|
||||
$this->source = $values;
|
||||
$this->sourceIds = $source_ids;
|
||||
$this->isStub = $is_stub;
|
||||
|
|
Reference in a new issue