updated core

This commit is contained in:
Bachir Soussi Chiadmi
2018-01-24 13:36:32 +01:00
parent cd7dea45a9
commit f9374cf96d
1997 changed files with 5175 additions and 127715 deletions
@@ -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();
}