/** * {@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\Entity\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; }
/** * Get config items such that each item comes before anything it depends on. * * @param \Drupal\features\ConfigurationItem[] $config_collection * A collection of configuration items. * * @return string[] * The names of configuration items, in dependency order. */ protected function dependencyOrder($config_collection) { // Populate a graph. $graph = []; foreach ($config_collection as $config) { $graph[$config->getName()] = []; foreach ($config->getDependents() as $dependent) { $graph[$config->getName()]['edges'][$dependent] = 1; } } $graph_object = new Graph($graph); $graph = $graph_object->searchAndSort(); // Order by inverse weight. $weights = array_column($graph, 'weight'); array_multisort($weights, SORT_DESC, $graph); return array_keys($graph); }
/** * Test depth-first-search features. */ public function testDepthFirstSearch() { // The sample graph used is: // 1 --> 2 --> 3 5 ---> 6 // | ^ ^ // | | | // | | | // +---> 4 <-- 7 8 ---> 9 $graph = $this->normalizeGraph(array(1 => array(2), 2 => array(3, 4), 3 => array(), 4 => array(3), 5 => array(6), 7 => array(4, 5), 8 => array(9), 9 => array())); $graph_object = new Graph($graph); $graph = $graph_object->searchAndSort(); $expected_paths = array(1 => array(2, 3, 4), 2 => array(3, 4), 3 => array(), 4 => array(3), 5 => array(6), 7 => array(4, 3, 5, 6), 8 => array(9), 9 => array()); $this->assertPaths($graph, $expected_paths); $expected_reverse_paths = array(1 => array(), 2 => array(1), 3 => array(2, 1, 4, 7), 4 => array(2, 1, 7), 5 => array(7), 7 => array(), 8 => array(), 9 => array(8)); $this->assertReversePaths($graph, $expected_reverse_paths); // Assert that DFS didn't created "missing" vertexes automatically. $this->assertFalse(isset($graph[6]), 'Vertex 6 has not been created'); $expected_components = array(array(1, 2, 3, 4, 5, 7), array(8, 9)); $this->assertComponents($graph, $expected_components); $expected_weights = array(array(1, 2, 3), array(2, 4, 3), array(7, 4, 3), array(7, 5), array(8, 9)); $this->assertWeights($graph, $expected_weights); }
/** * {@inheritdoc} */ public function buildModuleDependencies(array $modules) { foreach ($modules as $module) { $graph[$module->getName()]['edges'] = array(); if (isset($module->info['dependencies']) && is_array($module->info['dependencies'])) { foreach ($module->info['dependencies'] as $dependency) { $dependency_data = static::parseDependency($dependency); $graph[$module->getName()]['edges'][$dependency_data['name']] = $dependency_data; } } } $graph_object = new Graph($graph); $graph = $graph_object->searchAndSort(); foreach ($graph as $module_name => $data) { $modules[$module_name]->required_by = isset($data['reverse_paths']) ? $data['reverse_paths'] : array(); $modules[$module_name]->requires = isset($data['paths']) ? $data['paths'] : array(); $modules[$module_name]->sort = $data['weight']; } return $modules; }
/** * Gets the dependency graph of all the config entities. * * @return array * The dependency graph of all the config entities. */ protected function getGraph() { if (!isset($this->graph)) { $graph = array(); foreach ($this->data as $entity) { $graph_key = $entity->getConfigDependencyName(); $graph[$graph_key]['edges'] = array(); $dependencies = $entity->getDependencies('config'); if (!empty($dependencies)) { foreach ($dependencies as $dependency) { $graph[$graph_key]['edges'][$dependency] = TRUE; } } } $graph_object = new Graph($graph); $this->graph = $graph_object->searchAndSort(); } return $this->graph; }
/** * Gets the dependency graph of all the config entities. * * @return array * The dependency graph of all the config entities. */ protected function getGraph() { if (!isset($this->graph)) { $graph = array(); foreach ($this->data as $entity) { $graph_key = $entity->getConfigDependencyName(); if (!isset($graph[$graph_key])) { $graph[$graph_key] = ['edges' => [], 'name' => $graph_key]; } // Include all dependencies in the graph so that topographical sorting // works. foreach (array_merge($entity->getDependencies('config'), $entity->getDependencies('module'), $entity->getDependencies('theme')) as $dependency) { $graph[$dependency]['edges'][$graph_key] = TRUE; $graph[$dependency]['name'] = $dependency; } } // Ensure that order of the graph is consistent. krsort($graph); $graph_object = new Graph($graph); $this->graph = $graph_object->searchAndSort(); } return $this->graph; }
protected function sortTree(array $graph) { $graph_object = new Graph($graph); $sorted = $graph_object->searchAndSort(); uasort($sorted, 'Drupal\\Component\\Utility\\SortArray::sortByWeightElement'); return array_reverse($sorted); }