View source
<?php
namespace Drupal\migrate\Plugin;
use Drupal\Component\Graph\Graph;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
use Drupal\migrate\Plugin\Discovery\ProviderFilterDecorator;
use Drupal\Core\Plugin\Discovery\YamlDirectoryDiscovery;
use Drupal\Core\Plugin\Factory\ContainerFactory;
use Drupal\migrate\MigrateBuildDependencyInterface;
class MigrationPluginManager extends DefaultPluginManager implements MigrationPluginManagerInterface, MigrateBuildDependencyInterface {
protected $defaults = [
'class' => '\\Drupal\\migrate\\Plugin\\Migration',
];
protected $pluginInterface = 'Drupal\\migrate\\Plugin\\MigrationInterface';
protected $moduleHandler;
public function __construct(ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, LanguageManagerInterface $language_manager) {
$this->factory = new ContainerFactory($this, $this->pluginInterface);
$this
->alterInfo('migration_plugins');
$this
->setCacheBackend($cache_backend, 'migration_plugins', [
'migration_plugins',
]);
$this->moduleHandler = $module_handler;
}
protected function getDiscovery() {
if (!isset($this->discovery)) {
$directories = array_map(function ($directory) {
return [
$directory . '/migrations',
];
}, $this->moduleHandler
->getModuleDirectories());
$yaml_discovery = new YamlDirectoryDiscovery($directories, 'migrate');
$only_with_source_discovery = new NoSourcePluginDecorator($yaml_discovery);
$filtered_discovery = new ProviderFilterDecorator($only_with_source_discovery, [
$this->moduleHandler,
'moduleExists',
]);
$this->discovery = new ContainerDerivativeDiscoveryDecorator($filtered_discovery);
}
return $this->discovery;
}
public function createInstance($plugin_id, array $configuration = []) {
$instances = $this
->createInstances([
$plugin_id,
], [
$plugin_id => $configuration,
]);
return reset($instances);
}
public function createInstances($migration_id, array $configuration = []) {
if (empty($migration_id)) {
$migration_id = array_keys($this
->getDefinitions());
}
$factory = $this
->getFactory();
$migration_ids = (array) $migration_id;
$plugin_ids = $this
->expandPluginIds($migration_ids);
$instances = [];
foreach ($plugin_ids as $plugin_id) {
$instances[$plugin_id] = $factory
->createInstance($plugin_id, isset($configuration[$plugin_id]) ? $configuration[$plugin_id] : []);
}
foreach ($instances as $migration) {
$migration
->set('migration_dependencies', array_map([
$this,
'expandPluginIds',
], $migration
->getMigrationDependencies()));
}
return $this
->buildDependencyMigration($instances, []);
}
public function createInstancesByTag($tag) {
$migrations = array_filter($this
->getDefinitions(), function ($migration) use ($tag) {
return !empty($migration['migration_tags']) && in_array($tag, $migration['migration_tags']);
});
return $migrations ? $this
->createInstances(array_keys($migrations)) : [];
}
protected function expandPluginIds(array $migration_ids) {
$plugin_ids = [];
foreach ($migration_ids as $id) {
$plugin_ids += preg_grep('/^' . preg_quote($id, '/') . PluginBase::DERIVATIVE_SEPARATOR . '/', array_keys($this
->getDefinitions()));
if ($this
->hasDefinition($id)) {
$plugin_ids[] = $id;
}
}
return $plugin_ids;
}
public function buildDependencyMigration(array $migrations, array $dynamic_ids) {
$dependency_graph = [];
$required_dependency_graph = [];
$have_optional = FALSE;
foreach ($migrations as $migration) {
$id = $migration
->id();
$requirements[$id] = [];
$dependency_graph[$id]['edges'] = [];
$migration_dependencies = $migration
->getMigrationDependencies();
if (isset($migration_dependencies['required'])) {
foreach ($migration_dependencies['required'] as $dependency) {
if (!isset($dynamic_ids[$dependency])) {
$this
->addDependency($required_dependency_graph, $id, $dependency, $dynamic_ids);
}
$this
->addDependency($dependency_graph, $id, $dependency, $dynamic_ids);
}
}
if (!empty($migration_dependencies['optional'])) {
foreach ($migration_dependencies['optional'] as $dependency) {
$this
->addDependency($dependency_graph, $id, $dependency, $dynamic_ids);
}
$have_optional = TRUE;
}
}
$dependency_graph = (new Graph($dependency_graph))
->searchAndSort();
if ($have_optional) {
$required_dependency_graph = (new Graph($required_dependency_graph))
->searchAndSort();
}
else {
$required_dependency_graph = $dependency_graph;
}
$weights = [];
foreach ($migrations as $migration_id => $migration) {
$weights[] = $dependency_graph[$migration_id]['weight'];
if (!empty($required_dependency_graph[$migration_id]['paths'])) {
$migration
->set('requirements', $required_dependency_graph[$migration_id]['paths']);
}
}
array_multisort($weights, SORT_DESC, SORT_NUMERIC, array_keys($migrations), SORT_ASC, SORT_NATURAL, $migrations);
return $migrations;
}
protected function addDependency(array &$graph, $id, $dependency, $dynamic_ids) {
$dependencies = isset($dynamic_ids[$dependency]) ? $dynamic_ids[$dependency] : [
$dependency,
];
if (!isset($graph[$id]['edges'])) {
$graph[$id]['edges'] = [];
}
$graph[$id]['edges'] += array_combine($dependencies, $dependencies);
}
public function createStubMigration(array $definition) {
$id = isset($definition['id']) ? $definition['id'] : uniqid();
return Migration::create(\Drupal::getContainer(), [], $id, $definition);
}
protected function findDefinitions() {
$definitions = $this
->getDiscovery()
->getDefinitions();
foreach ($definitions as $plugin_id => &$definition) {
$this
->processDefinition($definition, $plugin_id);
}
$this
->alterDefinitions($definitions);
return ProviderFilterDecorator::filterDefinitions($definitions, function ($provider) {
return $this
->providerExists($provider);
});
}
}