3 use Drupal\drupalmoduleupgrader\Report;
4 use Drupal\drupalmoduleupgrader\Target;
5 use Symfony\Component\Filesystem\Filesystem;
8 * Implements hook_drush_command().
10 function drupalmoduleupgrader_drush_command() {
13 $items['dmu-list'] = [
14 'description' => 'Lists available plugins.',
16 'plugin_type' => 'The plugin type to query. Can be one of: indexer, analyzer, converter, cleaner.',
18 'required-arguments' => TRUE,
19 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
22 $items['dmu-index'] = [
23 'description' => 'Indexes a target module.',
25 'module' => 'The name of a Drupal 7 module.',
27 'required-arguments' => TRUE,
29 'drush dmu-index pants' => 'Indexes the pants module.',
31 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
34 $items['dmu-analyze'] = [
35 'description' => "Analyzes a Drupal 7 module and reports the changes needed to port it to Drupal 8.",
37 'module' => 'The machine name of a Drupal 7 module.',
39 'required-arguments' => TRUE,
42 'description' => 'A comma-separated list of analyzers to run, excluding all others.',
43 'example-value' => 'HookMenu,VariableAPI,BlockInfo',
46 'description' => 'A comma-separated list of analyzers to skip.',
47 'example-value' => 'HookInit,HookExit',
50 'description' => 'Optional path to the target module.',
51 'example-value' => 'drupal/modules/foobaz',
54 'description' => 'Optional path to output the report.',
55 'example-value' => 'path/to/module/analyze.html',
59 'drush dmu-analyze pants' => 'Analyze what needs to be changed in order to port the pants module.',
61 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
64 $items['dmu-upgrade'] = [
65 'description' => "Upgrades a Drupal 7 module to Drupal 8.",
67 'module' => 'The machine name of a Drupal 7 module.',
69 'required-arguments' => TRUE,
72 'description' => 'If set, creates a backup copy of the module before conversion.',
75 'description' => 'A comma-separated list of converters to run, excluding all others.',
76 'example-value' => 'HookMenu,VariableAPI,BlockInfo',
79 'description' => 'A comma-separated list of converters to skip.',
80 'example-value' => 'HookInit,HookExit',
83 'description' => 'Optional path to the target module. Will be determined automatically if omitted.',
84 'example-value' => 'drupal/modules/foobaz',
88 'drush dmu-upgrade pants' => 'Upgrade whatever can be automatically upgraded in the pants module.',
90 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
97 * Returns a list of plugin IDs of a given type, filtered by the --only
100 * @param string $plugin_type
101 * The plugin type. Can be one of indexer, analyzer, converter, cleaner.
105 function _dmu_plugin_list($plugin_type) {
106 // Instantiate the plugin manager and get all available plugin IDs.
107 $manager = \Drupal::service('plugin.manager.drupalmoduleupgrader.' . $plugin_type);
108 $plugin_IDs = array_keys($manager->getDefinitions());
110 // Filter by the --only and --skip options, if set.
111 if ($only = drush_get_option('only', FALSE)) {
112 $plugin_IDs = array_intersect($plugin_IDs, explode(',', $only));
114 elseif ($skip = drush_get_option('skip', FALSE)) {
115 $plugin_IDs = array_diff($plugin_IDs, explode(',', $skip));
122 * Checks for autoload.php, and includes it if it exists or sets an error
125 function _dmu_ensure_autoload() {
127 __DIR__ . '/vendor/autoload.php',
128 './vendor/autoload.php',
130 foreach ($locations as $location) {
131 if (file_exists($location)) {
132 require_once $location;
137 drush_set_error('no_autoload', 'autoload.php not found! Did you remember to run composer install from the drupalmoduleupgrader directory?');
141 * Determines the path to a module.
143 * @param string $module
144 * The module's machine name.
146 * @return string|NULL
148 function _dmu_get_directory($module) {
149 if ($path = drush_get_option('path', NULL)) {
153 $search_directories = [
154 DRUPAL_ROOT . '/modules/' . $module,
155 __DIR__ . '/'. $module,
158 $directories = array_filter($search_directories, 'is_dir');
160 return reset($directories);
166 * Checks possible locations of a target module, and ensures that at least
167 * one exists. If none do, sets an error.
169 * @param string $module
170 * The target module's machine name.
172 function _dmu_ensure_directory($module) {
173 $directory = _dmu_get_directory($module);
175 if (empty($directory)) {
176 if ($path = drush_get_option('path', NULL)) {
177 drush_set_error('invalid_dir', 'Invalid path: ' . $path);
180 drush_set_error('no_directory', "Cannot determine base directory of module $module. Try passing --path=modules/foobar");
186 * Validates any of the DMU commands.
188 function _dmu_validate_command($module) {
189 _dmu_ensure_autoload();
190 _dmu_ensure_directory($module);
193 function _dmu_build_target($module) {
194 $target = new Target(_dmu_get_directory($module), \Drupal::getContainer());
196 drush_print(\Drupal::translation()->translate('Indexing...'), 0, NULL, FALSE);
197 $target->buildIndex();
198 drush_print(\Drupal::translation()->translate('done.'));
204 * ----- dmu-list -----
208 * Lists all the available module-wide plugins.
210 function drush_drupalmoduleupgrader_dmu_list($plugin_type) {
211 $manager = \Drupal::service('plugin.manager.drupalmoduleupgrader.' . $plugin_type);
214 foreach ($manager->getDefinitions() as $id => $definition) {
215 $list[$id] = $definition['description'];
217 drush_print_table(drush_key_value_to_array_table($list));
221 * ----- dmu-index -----
224 function drush_drupalmoduleupgrader_dmu_index_validate($module) {
225 _dmu_validate_command($module);
229 * ----- dmu-analyze -----
232 function drush_drupalmoduleupgrader_dmu_analyze_validate($module) {
233 _dmu_validate_command($module);
237 * Analyzes what needs changing in a module to port it to Drupal 8.
239 * @param string $module
240 * The machine name of the module to analyze.
242 function drush_drupalmoduleupgrader_dmu_analyze($module) {
243 $target = _dmu_build_target($module);
246 $report = new Report();
248 $analyzers = \Drupal::service('plugin.manager.drupalmoduleupgrader.analyzer');
249 foreach (_dmu_plugin_list('analyzer') as $id) {
250 drush_log(\Drupal::translation()->translate('Executing plugin: @plugin_id', ['@plugin_id' => $id]), 'notice');
251 $issues = $analyzers->createInstance($id)->analyze($target);
254 if (! is_array($issues)) {
255 $issues = array($issues);
257 foreach ($issues as $issue) {
258 $report->addIssue($issue);
260 $total_issues += sizeof($issues);
266 '#theme' => 'dmu_report',
267 '#report' => $report,
268 '#group_by' => 'category',
271 $destination = drush_get_option('output', $target->getPath('upgrade-info.html'));
272 $output = \Drupal::service('renderer')->renderRoot($render);
273 file_put_contents($destination, $output);
274 drush_log(\Drupal::translation()->translate('Generated a report at @path', ['@path' => $destination]), 'success');
277 drush_log(\Drupal::translation()->translate('Wow...no issues found! You get a cookie :)', 'success'));
282 * ----- dmu-upgrade -----
285 function drush_drupalmoduleupgrader_dmu_upgrade_validate($module) {
286 _dmu_validate_command($module);
290 * Tries to automatically convert a Drupal 7 module to Drupal 8.
292 * @param string $module
293 * The module to upgrade.
295 function drush_drupalmoduleupgrader_dmu_upgrade($module) {
296 $target = _dmu_build_target($module);
298 if (drush_get_option('backup', FALSE)) {
299 $fs = new Filesystem();
300 $backup_at = $target->getBasePath() . '.bak';
301 $fs->mirror($target->getBasePath(), $backup_at);
302 drush_log(\Drupal::translation()->translate('Created backup at @path', [ '@path' => $backup_at ]), 'success');
305 $converters = \Drupal::service('plugin.manager.drupalmoduleupgrader.converter');
306 foreach (_dmu_plugin_list('converter') as $id) {
307 /** @var \Drupal\drupalmoduleupgrader\ConverterInterface $converter */
308 $converter = $converters->createInstance($id);
310 if ($converter->isExecutable($target)) {
311 drush_log(\Drupal::translation()->translate('Executing plugin: @plugin_id', ['@plugin_id' => $id]), 'notice');
313 $converter->convert($target);
315 catch (Exception $e) {
316 drush_log($e->getMessage(), 'error');
317 // Being a notice, the stack trace will only appear in verbose mode.
318 drush_log($e->getTraceAsString(), 'notice');