updated core
This commit is contained in:
@@ -36,7 +36,7 @@ class MigrateProcessPlugin extends Plugin {
|
||||
* Whether the plugin handles multiples itself.
|
||||
*
|
||||
* Typically these plugins will expect an array as input and iterate over it
|
||||
* themselves, changing the whole array. For example the 'iterator' and the
|
||||
* themselves, changing the whole array. For example the 'sub_process' and the
|
||||
* 'flatten' plugins. If the plugin only need to change a single value it
|
||||
* can skip setting this attribute and let
|
||||
* \Drupal\migrate\MigrateExecutable::processRow() handle the iteration.
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate;
|
||||
|
||||
use Drupal\Component\Graph\Graph;
|
||||
use Drupal\Component\Uuid\UuidInterface;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityStorage;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\Query\QueryFactoryInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Storage for migration entities.
|
||||
*/
|
||||
class MigrationStorage extends ConfigEntityStorage implements MigrateBuildDependencyInterface {
|
||||
|
||||
/**
|
||||
* The entity query factory service.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\Query\QueryFactoryInterface
|
||||
*/
|
||||
protected $queryFactory;
|
||||
|
||||
/**
|
||||
* Constructs a MigrationStorage object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* An entity type definition.
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The config factory service.
|
||||
* @param \Drupal\Component\Uuid\UuidInterface $uuid_service
|
||||
* The UUID service.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Entity\Query\QueryFactoryInterface $query_factory
|
||||
* The entity query factory service.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, QueryFactoryInterface $query_factory) {
|
||||
parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager);
|
||||
$this->queryFactory = $query_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static(
|
||||
$entity_type,
|
||||
$container->get('config.factory'),
|
||||
$container->get('uuid'),
|
||||
$container->get('language_manager'),
|
||||
$container->get('entity.query.config')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadMultiple(array $ids = NULL) {
|
||||
if ($ids) {
|
||||
$ids = $this->getVariantIds($ids);
|
||||
}
|
||||
/** @var \Drupal\migrate\Plugin\MigrationInterface[] $migrations */
|
||||
$migrations = parent::loadMultiple($ids);
|
||||
|
||||
foreach ($migrations as $migration) {
|
||||
$dependencies = array_map([$this, 'getVariantIds'], $migration->getMigrationDependencies());
|
||||
$migration->set('migration_dependencies', $dependencies);
|
||||
}
|
||||
|
||||
// Build an array of dependencies and set the order of the migrations.
|
||||
return $this->buildDependencyMigration($migrations, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Splices variant IDs into a list of migration IDs.
|
||||
*
|
||||
* IDs which match the template_id:* pattern are shorthand for every variant
|
||||
* of template_id. This method queries for those variant IDs and splices them
|
||||
* into the original list.
|
||||
*
|
||||
* @param string[] $ids
|
||||
* A set of migration IDs.
|
||||
*
|
||||
* @return string[]
|
||||
* The expanded list of IDs.
|
||||
*/
|
||||
public function getVariantIds(array $ids) {
|
||||
// Re-index the array numerically, since we need to limit the loop by size.
|
||||
$ids = array_values($ids);
|
||||
|
||||
$index = 0;
|
||||
while ($index < count($ids)) {
|
||||
if (substr($ids[$index], -2) == ':*') {
|
||||
$template_id = substr($ids[$index], 0, -2);
|
||||
$variants = $this->queryFactory->get($this->entityType, 'OR')
|
||||
->condition('id', $template_id)
|
||||
->condition('template', $template_id)
|
||||
->execute();
|
||||
array_splice($ids, $index, 1, $variants);
|
||||
$index += count($variants);
|
||||
}
|
||||
else {
|
||||
$index++;
|
||||
}
|
||||
}
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildDependencyMigration(array $migrations, array $dynamic_ids) {
|
||||
// Migration dependencies defined in the migration storage can be
|
||||
// optional or required. If an optional dependency does not run, the current
|
||||
// migration is still OK to go. Both optional and required dependencies
|
||||
// (if run at all) must run before the current migration.
|
||||
$dependency_graph = array();
|
||||
$requirement_graph = array();
|
||||
$different = FALSE;
|
||||
foreach ($migrations as $migration) {
|
||||
/** @var \Drupal\migrate\Plugin\MigrationInterface $migration */
|
||||
$id = $migration->id();
|
||||
$requirements[$id] = array();
|
||||
$dependency_graph[$id]['edges'] = array();
|
||||
$migration_dependencies = $migration->getMigrationDependencies();
|
||||
|
||||
if (isset($migration_dependencies['required'])) {
|
||||
foreach ($migration_dependencies['required'] as $dependency) {
|
||||
if (!isset($dynamic_ids[$dependency])) {
|
||||
$this->addDependency($requirement_graph, $id, $dependency, $dynamic_ids);
|
||||
}
|
||||
$this->addDependency($dependency_graph, $id, $dependency, $dynamic_ids);
|
||||
}
|
||||
}
|
||||
if (isset($migration_dependencies['optional'])) {
|
||||
foreach ($migration_dependencies['optional'] as $dependency) {
|
||||
$different = TRUE;
|
||||
$this->addDependency($dependency_graph, $id, $dependency, $dynamic_ids);
|
||||
}
|
||||
}
|
||||
}
|
||||
$graph_object = new Graph($dependency_graph);
|
||||
$dependency_graph = $graph_object->searchAndSort();
|
||||
if ($different) {
|
||||
$graph_object = new Graph($requirement_graph);
|
||||
$requirement_graph = $graph_object->searchAndSort();
|
||||
}
|
||||
else {
|
||||
$requirement_graph = $dependency_graph;
|
||||
}
|
||||
$weights = array();
|
||||
foreach ($migrations as $migration_id => $migration) {
|
||||
// Populate a weights array to use with array_multisort later.
|
||||
$weights[] = $dependency_graph[$migration_id]['weight'];
|
||||
if (!empty($requirement_graph[$migration_id]['paths'])) {
|
||||
$migration->set('requirements', $requirement_graph[$migration_id]['paths']);
|
||||
}
|
||||
}
|
||||
array_multisort($weights, SORT_DESC, SORT_NUMERIC, $migrations);
|
||||
|
||||
return $migrations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one or more dependencies to a graph.
|
||||
*
|
||||
* @param array $graph
|
||||
* The graph so far, passed by reference.
|
||||
* @param int $id
|
||||
* The migration ID.
|
||||
* @param string $dependency
|
||||
* The dependency string.
|
||||
* @param array $dynamic_ids
|
||||
* The dynamic ID mapping.
|
||||
*/
|
||||
protected function addDependency(array &$graph, $id, $dependency, $dynamic_ids) {
|
||||
$dependencies = isset($dynamic_ids[$dependency]) ? $dynamic_ids[$dependency] : array($dependency);
|
||||
if (!isset($graph[$id]['edges'])) {
|
||||
$graph[$id]['edges'] = array();
|
||||
}
|
||||
$graph[$id]['edges'] += array_combine($dependencies, $dependencies);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -53,9 +53,12 @@ interface MigrateSourceInterface extends \Countable, \Iterator, PluginInspection
|
||||
* 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:
|
||||
* by FieldStorageDefinitionInterface::getSettings().
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* A composite source primary key that is defined by an integer and a string
|
||||
* might look like this:
|
||||
* @code
|
||||
* return [
|
||||
* 'id' => [
|
||||
@@ -70,6 +73,7 @@ interface MigrateSourceInterface extends \Countable, \Iterator, PluginInspection
|
||||
* ],
|
||||
* ];
|
||||
* @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:
|
||||
@@ -80,9 +84,13 @@ interface MigrateSourceInterface extends \Countable, \Iterator, PluginInspection
|
||||
* ],
|
||||
* ];
|
||||
* @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:
|
||||
*
|
||||
* 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.
|
||||
* @code
|
||||
* return [
|
||||
* 'nid' => [
|
||||
|
||||
@@ -621,7 +621,7 @@ class Migration extends PluginBase implements MigrationInterface, RequirementsIn
|
||||
if ($plugin_configuration['plugin'] == 'migration') {
|
||||
$return = array_merge($return, (array) $plugin_configuration['migration']);
|
||||
}
|
||||
if ($plugin_configuration['plugin'] == 'iterator') {
|
||||
if ($plugin_configuration['plugin'] == 'sub_process') {
|
||||
$return = array_merge($return, $this->findMigrationDependencies($plugin_configuration['process']));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,9 +45,9 @@ abstract class Entity extends DestinationBase implements ContainerFactoryPluginI
|
||||
* The plugin_id for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param MigrationInterface $migration
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration.
|
||||
* @param EntityStorageInterface $storage
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
|
||||
* The storage for this entity type.
|
||||
* @param array $bundles
|
||||
* The list of bundles this entity type has.
|
||||
|
||||
@@ -3,7 +3,43 @@
|
||||
namespace Drupal\migrate\Plugin\migrate\destination;
|
||||
|
||||
/**
|
||||
* Provides entity field instance plugin.
|
||||
* Provides destination plugin for field_config configuration entities.
|
||||
*
|
||||
* The Field API defines two primary data structures, FieldStorage and Field.
|
||||
* A FieldStorage defines a particular type of data that can be attached to
|
||||
* entities as a Field instance.
|
||||
*
|
||||
* The example below adds an instance of 'field_text_example' to 'article'
|
||||
* bundle (node content type). The example uses the EmptySource source plugin
|
||||
* and constant source values for the sake of simplicity. For an example on how
|
||||
* the FieldStorage 'field_text_example' can be migrated, refer to
|
||||
* \Drupal\migrate\Plugin\migrate\destination\EntityFieldStorageConfig.
|
||||
* @code
|
||||
* id: field_instance_example
|
||||
* label: Field instance example
|
||||
* source:
|
||||
* plugin: empty
|
||||
* constants:
|
||||
* entity_type: node
|
||||
* field_name: field_text_example
|
||||
* bundle: article
|
||||
* label: Text field example
|
||||
* translatable: true
|
||||
* process:
|
||||
* entity_type: constants/entity_type
|
||||
* field_name: constants/field_name
|
||||
* bundle: constants/bundle
|
||||
* label: constants/label
|
||||
* translatable: constants/translatable
|
||||
* destination:
|
||||
* plugin: entity:field_config
|
||||
* migration_dependencies:
|
||||
* required:
|
||||
* - field_storage_example
|
||||
* @endcode
|
||||
*
|
||||
* @see \Drupal\field\Entity\FieldConfig
|
||||
* @see \Drupal\field\Entity\FieldConfigBase
|
||||
*
|
||||
* @MigrateDestination(
|
||||
* id = "entity:field_config"
|
||||
|
||||
@@ -3,7 +3,48 @@
|
||||
namespace Drupal\migrate\Plugin\migrate\destination;
|
||||
|
||||
/**
|
||||
* Provides entity field storage configuration plugin.
|
||||
* Provides destination plugin for field_storage_config configuration entities.
|
||||
*
|
||||
* The Field API defines two primary data structures, FieldStorage and Field.
|
||||
* A FieldStorage defines a particular type of data that can be attached to
|
||||
* entities as a Field instance.
|
||||
*
|
||||
* The example below creates a storage for a simple text field. The example uses
|
||||
* the EmptySource source plugin and constant source values for the sake of
|
||||
* simplicity.
|
||||
* @code
|
||||
* id: field_storage_example
|
||||
* label: Field storage example
|
||||
* source:
|
||||
* plugin: empty
|
||||
* constants:
|
||||
* entity_type: node
|
||||
* id: node.field_text_example
|
||||
* field_name: field_text_example
|
||||
* type: string
|
||||
* cardinality: 1
|
||||
* settings:
|
||||
* max_length: 10
|
||||
* langcode: en
|
||||
* translatable: true
|
||||
* process:
|
||||
* entity_type: constants/entity_type
|
||||
* id: constants/id
|
||||
* field_name: constants/field_name
|
||||
* type: constants/type
|
||||
* cardinality: constants/cardinality
|
||||
* settings: constants/settings
|
||||
* langcode: constants/langcode
|
||||
* translatable: constants/translatable
|
||||
* destination:
|
||||
* plugin: entity:field_storage_config
|
||||
* @endcode
|
||||
*
|
||||
* For a full list of the properties of a FieldStorage configuration entity,
|
||||
* refer to \Drupal\field\Entity\FieldStorageConfig.
|
||||
*
|
||||
* For an example on how to migrate a Field instance of this FieldStorage,
|
||||
* refer to \Drupal\migrate\Plugin\migrate\destination\EntityFieldInstance.
|
||||
*
|
||||
* @MigrateDestination(
|
||||
* id = "entity:field_storage_config"
|
||||
|
||||
@@ -94,7 +94,7 @@ use Drupal\migrate\Row;
|
||||
*
|
||||
* process:
|
||||
* filters:
|
||||
* plugin: iterator
|
||||
* plugin: sub_process
|
||||
* source: filters
|
||||
* key: "@id"
|
||||
* process:
|
||||
|
||||
@@ -27,7 +27,7 @@ trait DummyQueryTrait {
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function count() {
|
||||
public function count($refresh = FALSE) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,20 @@
|
||||
namespace Drupal\migrate\Plugin\migrate\source;
|
||||
|
||||
/**
|
||||
* Source returning an empty row.
|
||||
* Source returning a row based on the constants provided.
|
||||
*
|
||||
* This is generally useful when needing to create a field using a migration..
|
||||
* Example:
|
||||
*
|
||||
* @code
|
||||
* source:
|
||||
* plugin: empty
|
||||
* constants:
|
||||
* entity_type: user
|
||||
* field_name: image
|
||||
* @endcode
|
||||
*
|
||||
* This will return a single row containing 'entity_type' and 'field_name'
|
||||
* elements, with values of 'user' and 'image', respectively.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "empty"
|
||||
|
||||
@@ -436,7 +436,10 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter
|
||||
* Returns -1 if the source is not countable.
|
||||
*
|
||||
* @param bool $refresh
|
||||
* (optional) Whether or not to refresh the count. Defaults to FALSE.
|
||||
* (optional) Whether or not to refresh the count. Defaults to FALSE. Not
|
||||
* all implementations support the reset flag. In such instances this
|
||||
* parameter is ignored and the result of calling the method will always be
|
||||
* up to date.
|
||||
*
|
||||
* @return int
|
||||
* The count.
|
||||
|
||||
@@ -17,35 +17,48 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
/**
|
||||
* Sources whose data may be fetched via a database connection.
|
||||
*
|
||||
* Database configuration, which may appear either within the source plugin
|
||||
* configuration or in state, is structured as follows:
|
||||
* Available configuration keys:
|
||||
* - database_state_key: (optional) Name of the state key which contains an
|
||||
* array with database connection information.
|
||||
* - key: (optional) The database key name. Defaults to 'migrate'.
|
||||
* - 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.
|
||||
*
|
||||
* 'key' - The database key name (defaults to 'migrate').
|
||||
* 'target' - The database target name (defaults to 'default').
|
||||
* 'database' - Database connection information as accepted by
|
||||
* Database::addConnectionInfo(). If not present, the key/target is assumed
|
||||
* to already be defined (e.g., in settings.php).
|
||||
* For other optional configuration keys inherited from the parent class, refer
|
||||
* to \Drupal\migrate\Plugin\migrate\source\SourcePluginBase.
|
||||
*
|
||||
* This configuration info is obtained in the following order:
|
||||
* About the source database determination:
|
||||
* - If the source plugin configuration contains 'database_state_key', its value
|
||||
* is taken as the name of a state key which contains an array with the
|
||||
* database configuration.
|
||||
* - Otherwise, if the source plugin configuration contains 'key', the database
|
||||
* configuration with that name is used.
|
||||
* - If both 'database_state_key' and 'key' are omitted in the source plugin
|
||||
* configuration, the database connection named 'migrate' is used by default.
|
||||
* - If all of the above steps fail, RequirementsException is thrown.
|
||||
*
|
||||
* 1. If the source plugin configuration contains a key 'database_state_key',
|
||||
* its value is taken as the name of a state key which contains an array
|
||||
* with the above database configuration.
|
||||
* 2. Otherwise, if the source plugin configuration contains 'key', the above
|
||||
* database configuration is obtained directly from the plugin configuration.
|
||||
* 3. Otherwise, if the state 'migrate.fallback_state_key' exists, its value is
|
||||
* taken as the name of a state key which contains an array with the above
|
||||
* database configuration.
|
||||
* 4. Otherwise, if a connection named 'migrate' exists, that is used as the
|
||||
* database connection.
|
||||
* 5. Otherwise, RequirementsException is thrown.
|
||||
* Drupal Database API supports multiple database connections. The connection
|
||||
* parameters are defined in $databases array in settings.php or
|
||||
* settings.local.php. It is also possible to modify the $databases array in
|
||||
* runtime. For example, Migrate Drupal, which provides the migrations from
|
||||
* Drupal 6 / 7, asks for the source database connection parameters in the UI
|
||||
* and then adds the $databases['migrate'] connection in runtime before the
|
||||
* migrations are executed.
|
||||
*
|
||||
* It is strongly recommended that database connections be explicitly defined
|
||||
* via 'database_state_key' or in the source plugin configuration. Defining
|
||||
* migrate.fallback_state_key or a 'migrate' connection affects not only any
|
||||
* migrations intended to use that particular connection, but all
|
||||
* SqlBase-derived source plugins which do not have explicit database
|
||||
* configuration.
|
||||
* As described above, the default source database is $databases['migrate']. If
|
||||
* the source plugin needs another source connection, the database connection
|
||||
* parameters should be added to the $databases array as, for instance,
|
||||
* $databases['foo']. The source plugin can then use this connection by setting
|
||||
* 'key' to 'foo' in its configuration.
|
||||
*
|
||||
* For a complete example on migrating data from an SQL source, refer to
|
||||
* https://www.drupal.org/docs/8/api/migrate-api/migrating-data-from-sql-source
|
||||
*
|
||||
* @see https://www.drupal.org/docs/8/api/database-api
|
||||
* @see \Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase
|
||||
*/
|
||||
abstract class SqlBase extends SourcePluginBase implements ContainerFactoryPluginInterface, RequirementsInterface {
|
||||
|
||||
@@ -365,7 +378,7 @@ abstract class SqlBase extends SourcePluginBase implements ContainerFactoryPlugi
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function count() {
|
||||
public function count($refresh = FALSE) {
|
||||
return $this->query()->countQuery()->execute()->fetchField();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user