Unverified Commit d4c3b727 authored by larowlan's avatar larowlan

Issue #3024682 by quietone, sokru, kim.pepper, benjifisher, webchick,...

Issue #3024682 by quietone, sokru, kim.pepper, benjifisher, webchick, mikelutz, xjm: Migrate UI - add human-friendly module names to the Review form
parent 287cbe29
......@@ -3,12 +3,14 @@
namespace Drupal\migrate_drupal_ui\Form;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\Exception\UnknownExtensionException;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\migrate_drupal_ui\Batch\MigrateUpgradeImportBatch;
use Drupal\migrate_drupal\MigrationState;
use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
use Drupal\migrate_drupal\MigrationState;
use Drupal\migrate_drupal_ui\Batch\MigrateUpgradeImportBatch;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -44,6 +46,20 @@ class ReviewForm extends MigrateUpgradeFormBase {
*/
protected $migrationState;
/**
* Module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Source system data set in buildForm().
*
* @var array
*/
protected $systemData;
/**
* ReviewForm constructor.
*
......@@ -57,10 +73,17 @@ class ReviewForm extends MigrateUpgradeFormBase {
* Migration state service.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory service.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler service.
*/
public function __construct(StateInterface $state, MigrationPluginManagerInterface $migration_plugin_manager, PrivateTempStoreFactory $tempstore_private, MigrationState $migrationState, ConfigFactoryInterface $config_factory) {
public function __construct(StateInterface $state, MigrationPluginManagerInterface $migration_plugin_manager, PrivateTempStoreFactory $tempstore_private, MigrationState $migrationState, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler = NULL) {
parent::__construct($config_factory, $migration_plugin_manager, $state, $tempstore_private);
$this->migrationState = $migrationState;
if (!$module_handler) {
@trigger_error('Calling ' . __METHOD__ . ' without the $module_handler argument is deprecated in drupal:9.1.0 and will be required in drupal:10.0.0. See https://www.drupal.org/node/3136769', E_USER_DEPRECATED);
$module_handler = \Drupal::service('module_handler');
}
$this->moduleHandler = $module_handler;
}
/**
......@@ -72,7 +95,8 @@ public static function create(ContainerInterface $container) {
$container->get('plugin.manager.migration'),
$container->get('tempstore.private'),
$container->get('migrate_drupal.migration_state'),
$container->get('config.factory')
$container->get('config.factory'),
$container->get('module_handler')
);
}
......@@ -91,10 +115,10 @@ public function buildForm(array $form, FormStateInterface $form_state) {
$version = $this->store->get('version');
$this->migrations = $this->store->get('migrations');
// Fetch the source system data at the first opportunity.
$system_data = $this->store->get('system_data');
$this->systemData = $this->store->get('system_data');
// If data is missing or this is the wrong step, start over.
if (!$version || !$this->migrations || !$system_data ||
if (!$version || !$this->migrations || !$this->systemData ||
($this->store->get('step') != 'review')) {
return $this->restartUpgradeForm();
}
......@@ -105,7 +129,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
$migrations = $this->migrationPluginManager->createInstances(array_keys($this->store->get('migrations')));
// Get the upgrade states for the source modules.
$display = $this->migrationState->getUpgradeStates($version, $system_data, $migrations);
$display = $this->migrationState->getUpgradeStates($version, $this->systemData, $migrations);
// Missing migrations.
$missing_module_list = [
......@@ -119,14 +143,16 @@ public function buildForm(array $form, FormStateInterface $form_state) {
$missing_module_list['module_list'] = [
'#type' => 'table',
'#header' => [
$this->t('Drupal @version', ['@version' => $version]),
$this->t('Drupal @version module name', ['@version' => $version]),
$this->t('Drupal @version machine name', ['@version' => $version]),
$this->t('Drupal @version', ['@version' => $this->destinationSiteVersion]),
],
];
$missing_count = 0;
if (isset($display[MigrationState::NOT_FINISHED])) {
foreach ($display[MigrationState::NOT_FINISHED] as $source_module => $destination_modules) {
$output = $this->prepareOutput($display[MigrationState::NOT_FINISHED]);
foreach ($output as $data) {
$missing_count++;
// Get the migration status for this $source_module, if a module of the
// same name exists on the destination site.
......@@ -134,7 +160,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
'source_module' => [
'#type' => 'html_tag',
'#tag' => 'span',
'#value' => $source_module,
'#value' => $data['source_module_name'],
'#attributes' => [
'class' => [
'upgrade-analysis-report__status-icon',
......@@ -142,8 +168,11 @@ public function buildForm(array $form, FormStateInterface $form_state) {
],
],
],
'source_machine_name' => [
'#plain_text' => $data['source_machine_name'],
],
'destination_module' => [
'#plain_text' => $destination_modules,
'#plain_text' => $data['destination'],
],
];
}
......@@ -160,20 +189,22 @@ public function buildForm(array $form, FormStateInterface $form_state) {
$available_module_list['module_list'] = [
'#type' => 'table',
'#header' => [
$this->t('Drupal @version', ['@version' => $version]),
$this->t('Drupal @version module name', ['@version' => $version]),
$this->t('Drupal @version machine name', ['@version' => $version]),
$this->t('Drupal @version', ['@version' => $this->destinationSiteVersion]),
],
];
$available_count = 0;
if (isset($display[MigrationState::FINISHED])) {
foreach ($display[MigrationState::FINISHED] as $source_module => $destination_modules) {
$output = $this->prepareOutput($display[MigrationState::FINISHED]);
foreach ($output as $data) {
$available_count++;
$available_module_list['module_list'][] = [
'source_module' => [
'#type' => 'html_tag',
'#tag' => 'span',
'#value' => $source_module,
'#value' => $data['source_module_name'],
'#attributes' => [
'class' => [
'upgrade-analysis-report__status-icon',
......@@ -181,8 +212,11 @@ public function buildForm(array $form, FormStateInterface $form_state) {
],
],
],
'source_machine_name' => [
'#plain_text' => $data['source_machine_name'],
],
'destination_module' => [
'#plain_text' => $destination_modules,
'#plain_text' => $data['destination'],
],
];
}
......@@ -254,4 +288,58 @@ public function getConfirmText() {
return $this->t('Perform upgrade');
}
/**
* Prepare the migration state data for output.
*
* Each source and destination module_name is changed to the human-readable
* name, the destination modules are put into a CSV format, and everything is
* sorted.
*
* @param string[] $migration_state
* An array where the keys are machine names of modules on
* the source site. Values are lists of machine names of modules on the
* destination site, in CSV format.
*
* @return string[][]
* An indexed array of arrays that contain module data, sorted by the source
* module name. Each sub-array contains the source module name, the source
* module machine name, and the the destination module names in a sorted CSV
* format.
*/
protected function prepareOutput(array $migration_state) {
$output = [];
foreach ($migration_state as $source_machine_name => $destination_modules) {
$data = unserialize($this->systemData['module'][$source_machine_name]['info']);
$source_module_name = $data['name'] ?? $source_machine_name;
// Get the names of all the destination modules.
$destination_module_names = [];
if (!empty($destination_modules)) {
$destination_modules = explode(', ', $destination_modules);
foreach ($destination_modules as $destination_module) {
if ($destination_module === 'core') {
$destination_module_names[] = 'Core';
}
else {
try {
$destination_module_names[] = $this->moduleHandler->getName($destination_module);
}
catch (UnknownExtensionException $e) {
$destination_module_names[] = $destination_module;
}
}
}
}
sort($destination_module_names);
$output[$source_machine_name] = [
'source_module_name' => $source_module_name,
'source_machine_name' => $source_machine_name,
'destination' => implode(', ', $destination_module_names),
];
}
usort($output, function ($a, $b) {
return strcmp($a['source_module_name'], $b['source_module_name']);
});
return $output;
}
}
......@@ -72,6 +72,7 @@ public function testMigrateUpgradeReviewPage() {
// does not need any. Test with a module that is was in both Drupal 6 and
// Drupal 7 core.
$module = 'help';
$module_name = 'Help';
$query = $this->sourceDatabase->delete('system');
$query->condition('type', 'module');
$query->condition('name', $module);
......@@ -86,7 +87,7 @@ public function testMigrateUpgradeReviewPage() {
// Test the upgrade paths. First remove the module from the available paths
// list.
$available_paths = $this->getAvailablePaths();
$available_paths = array_diff($available_paths, [$module]);
$available_paths = array_diff($available_paths, [$module_name]);
$missing_paths = $this->getMissingPaths();
$this->assertUpgradePaths($session, $available_paths, $missing_paths);
}
......
......@@ -56,83 +56,82 @@ protected function getSourceBasePath() {
*/
protected function getAvailablePaths() {
return [
// Aggregator is set not_finished in migrate_sate_not_finished_test.
'aggregator',
'blog',
'blogapi',
'book',
'calendarsignup',
'color',
'comment',
'contact',
'content',
'content_copy',
'content_multigroup',
'content_permissions',
'date',
'date_api',
'date_locale',
'date_php4',
'date_popup',
'date_repeat',
'date_timezone',
'date_tools',
'datepicker',
'dblog',
'ddblock',
'email',
'event',
'fieldgroup',
'filefield',
'filefield_meta',
'filter',
'forum',
'help',
'i18nblocks',
'i18ncontent',
'i18nmenu',
'i18npoll',
'i18nprofile',
'i18nsync',
'imageapi',
'imageapi_gd',
'imageapi_imagemagick',
'imagecache',
'imagecache_ui',
'imagefield',
'jquery_ui',
'link',
'menu',
'node',
'nodeaccess',
'nodereference',
'number',
'openid',
'optionwidgets',
'path',
'phone',
'php',
'ping',
'poll',
'profile',
'search',
'statistics',
'syslog',
'system',
'taxonomy',
'text',
'throttle',
'tracker',
'translation',
'trigger',
'update',
'upload',
'user',
'userreference',
'variable',
'variable_admin',
'views_export',
'views_ui',
'Aggregator',
'Block translation',
'Blog',
'Blog API',
'Book',
'Calendar Signup',
'Color',
'Comment',
'Contact',
'Content',
'Content Copy',
'Content Multigroup',
'Content Permissions',
'Content translation',
'Content type translation',
'Database logging',
'Date',
'Date API',
'Date Locale',
'Date PHP4',
'Date Picker',
'Date Popup',
'Date Repeat API',
'Date Timezone',
'Date Tools',
'Dynamic display block',
'Email',
'Event',
'Fieldgroup',
'FileField',
'FileField Meta',
'Filter',
'Forum',
'Help',
'ImageAPI',
'ImageAPI GD2',
'ImageAPI ImageMagick',
'ImageCache',
'ImageCache UI',
'ImageField',
'Link',
'Menu',
'Menu translation',
'Node',
'Node Reference',
'Nodeaccess',
'Number',
'OpenID',
'Option Widgets',
'PHP filter',
'Path',
'Phone - CCK',
'Ping',
'Poll',
'Poll aggregate',
'Profile',
'Profile translation',
'Search',
'Statistics',
'Synchronize translations',
'Syslog',
'System',
'Taxonomy',
'Text',
'Throttle',
'Tracker',
'Trigger',
'Update status',
'Upload',
'User',
'User Reference',
'Variable API',
'Variable admin',
'Views UI',
'Views exporter',
'jQuery UI',
];
}
......@@ -141,19 +140,19 @@ protected function getAvailablePaths() {
*/
protected function getMissingPaths() {
return [
// Block is set not_finished in migrate_sate_not_finished_test.
'block',
'devel',
'devel_generate',
'devel_node_access',
'i18n',
'i18ncck',
'i18nstrings',
'i18ntaxonomy',
'i18nviews',
'locale',
// Block is set not_finished in migrate_state_not_finished_test.
'Block',
'CCK translation',
'Devel',
'Devel generate',
'Devel node access',
'Internationalization',
'Locale',
'String translation',
'Taxonomy translation',
'Views',
'Views translation',
'migrate_status_active_test',
'views',
];
}
......
......@@ -53,77 +53,77 @@ protected function getSourceBasePath() {
*/
protected function getAvailablePaths() {
return [
'aggregator',
'blog',
'blogapi',
'book',
'calendarsignup',
'color',
'comment',
'contact',
'content',
'content_copy',
'content_multigroup',
'content_permissions',
'date',
'date_api',
'date_locale',
'date_php4',
'date_popup',
'date_repeat',
'date_timezone',
'date_tools',
'datepicker',
'dblog',
'ddblock',
'email',
'event',
'fieldgroup',
'filefield',
'filefield_meta',
'filter',
'forum',
'help',
'imageapi',
'imageapi_gd',
'imageapi_imagemagick',
'imagecache',
'imagecache_ui',
'imagefield',
'jquery_ui',
'link',
'locale',
'menu',
'node',
'nodeaccess',
'nodereference',
'number',
'openid',
'optionwidgets',
'path',
'phone',
'php',
'ping',
'poll',
'profile',
'search',
'statistics',
'syslog',
'system',
'taxonomy',
'text',
'throttle',
'tracker',
'translation',
'trigger',
'update',
'upload',
'user',
'userreference',
'variable',
'variable_admin',
'views_export',
'views_ui',
'Aggregator',
'Blog',
'Blog API',
'Book',
'Calendar Signup',
'Color',
'Comment',
'Contact',
'Content',
'Content Copy',
'Content Multigroup',
'Content Permissions',
'Content translation',
'Database logging',
'Date',
'Date API',
'Date Locale',
'Date PHP4',
'Date Picker',
'Date Popup',
'Date Repeat API',
'Date Timezone',
'Date Tools',
'Dynamic display block',
'Email',
'Event',
'Fieldgroup',
'FileField',
'FileField Meta',
'Filter',
'Forum',
'Help',
'ImageAPI',
'ImageAPI GD2',
'ImageAPI ImageMagick',
'ImageCache',
'ImageCache UI',
'ImageField',
'Link',
'Locale',
'Menu',
'Node',
'Nodeaccess',
'Node Reference',
'Number',
'OpenID',
'Option Widgets',
'PHP filter',
'Path',
'Phone - CCK',
'Ping',
'Poll',
'Profile',
'Search',
'Statistics',
'Syslog',
'System',
'Taxonomy',
'Text',
'Throttle',
'Tracker',
'Trigger',
'Update status',
'Upload',
'User',
'User Reference',
'Variable API',
'Variable admin',
'Views UI',
'Views exporter',
'jQuery UI',
];
}
......@@ -140,23 +140,23 @@ protected function getIncompletePaths() {
protected function getMissingPaths() {
return [
// Block is set not_finished in migrate_state_not_finished_test.
'block',
'devel',
'devel_generate',
'devel_node_access',
'i18n',
'i18nblocks',
'i18ncck',
'i18ncontent',
'i18nmenu',