You are here

drupalmoduleupgrader.drush.inc in Drupal 7 to 8/9 Module Upgrader 8

Declarations for Drush.

File

drupalmoduleupgrader.drush.inc
View source
<?php

/**
 * @file
 * Declarations for Drush.
 */
use Drupal\drupalmoduleupgrader\Report;
use Drupal\drupalmoduleupgrader\Target;
use Symfony\Component\Filesystem\Filesystem;

/**
 * Implements hook_drush_command().
 */
function drupalmoduleupgrader_drush_command() {
  $items = [];
  $items['dmu-list'] = [
    'description' => 'Lists available plugins.',
    'arguments' => [
      'plugin_type' => 'The plugin type to query. Can be one of: indexer, analyzer, converter, cleaner.',
    ],
    'required-arguments' => TRUE,
    'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
  ];
  $items['dmu-index'] = [
    'description' => 'Indexes a target module.',
    'arguments' => [
      'module' => 'The name of a Drupal 7 module.',
    ],
    'required-arguments' => TRUE,
    'examples' => [
      'drush dmu-index pants' => 'Indexes the pants module.',
    ],
    'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
  ];
  $items['dmu-analyze'] = [
    'description' => "Analyzes a Drupal 7 module and reports the changes needed to port it to Drupal 8.",
    'arguments' => [
      'module' => 'The machine name of a Drupal 7 module.',
    ],
    'required-arguments' => TRUE,
    'options' => [
      'only' => [
        'description' => 'A comma-separated list of analyzers to run, excluding all others.',
        'example-value' => 'HookMenu,VariableAPI,BlockInfo',
      ],
      'skip' => [
        'description' => 'A comma-separated list of analyzers to skip.',
        'example-value' => 'HookInit,HookExit',
      ],
      'path' => [
        'description' => 'Optional path to the target module.',
        'example-value' => 'drupal/modules/foobaz',
      ],
      'output' => [
        'description' => 'Optional path to output the report.',
        'example-value' => 'path/to/module/analyze.html',
      ],
    ],
    'examples' => [
      'drush dmu-analyze pants' => 'Analyze what needs to be changed in order to port the pants module.',
    ],
    'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
  ];
  $items['dmu-upgrade'] = [
    'description' => "Upgrades a Drupal 7 module to Drupal 8.",
    'arguments' => [
      'module' => 'The machine name of a Drupal 7 module.',
    ],
    'required-arguments' => TRUE,
    'options' => [
      'backup' => [
        'description' => 'If set, creates a backup copy of the module before conversion.',
      ],
      'only' => [
        'description' => 'A comma-separated list of converters to run, excluding all others.',
        'example-value' => 'HookMenu,VariableAPI,BlockInfo',
      ],
      'skip' => [
        'description' => 'A comma-separated list of converters to skip.',
        'example-value' => 'HookInit,HookExit',
      ],
      'path' => [
        'description' => 'Optional path to the target module. Will be determined automatically if omitted.',
        'example-value' => 'drupal/modules/foobaz',
      ],
    ],
    'examples' => [
      'drush dmu-upgrade pants' => 'Upgrade whatever can be automatically upgraded in the pants module.',
    ],
    'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
  ];
  return $items;
}

/**
 * Returns a list of plugin IDs of a given type.
 *
 * Filtered by the --only and --skip options.
 *
 * @param string $plugin_type
 *   The plugin type. Can be one of indexer, analyzer, converter, cleaner.
 *
 * @return array
 *   Plugin ID's.
 */
function _dmu_plugin_list($plugin_type) {

  // Instantiate the plugin manager and get all available plugin IDs.
  $manager = \Drupal::service('plugin.manager.drupalmoduleupgrader.' . $plugin_type);
  $plugin_ids = array_keys($manager
    ->getDefinitions());

  // Filter by the --only and --skip options, if set.
  if ($only = drush_get_option('only', FALSE)) {
    $plugin_ids = array_intersect($plugin_ids, explode(',', $only));
  }
  elseif ($skip = drush_get_option('skip', FALSE)) {
    $plugin_ids = array_diff($plugin_ids, explode(',', $skip));
  }
  return $plugin_ids;
}

/**
 * Checks for autoload.php and try to include it.
 */
function _dmu_ensure_autoload() {
  $locations = [
    __DIR__ . '/vendor/autoload.php',
    './vendor/autoload.php',
  ];
  foreach ($locations as $location) {
    if (file_exists($location)) {
      require_once $location;
      return;
    }
  }
  drush_set_error('no_autoload', 'autoload.php not found! Did you remember to run composer install from the drupalmoduleupgrader directory?');
}

/**
 * Determines the path to a module.
 *
 * @param string $module
 *   The module's machine name.
 *
 * @return string|null
 *   Directories.
 */
function _dmu_get_directory($module) {
  if ($path = drush_get_option('path', NULL)) {
    return $path;
  }
  else {
    $search_directories = [
      DRUPAL_ROOT . '/modules/' . $module,
      __DIR__ . '/' . $module,
    ];
    $directories = array_filter($search_directories, 'is_dir');
    if ($directories) {
      return reset($directories);
    }
  }
}

/**
 * Determines if user is re running drupal module upgrade.
 *
 * @param string $module
 *   The module's machine name.
 */
function _dmu_ensure_info_present($module) {
  $directory = _dmu_get_directory($module);
  if (file_exists($directory . '/' . $module . '.info.yml')) {
    drush_set_error('invalid_dir', 'You have already run dmu upgrade command for this module.');
  }
}

/**
 * Checks possible locations of a target module.
 *
 * Ensures that at least one exists. If none do, sets an error.
 *
 * @param string $module
 *   The target module's machine name.
 */
function _dmu_ensure_directory($module) {
  $directory = _dmu_get_directory($module);
  if (empty($directory)) {
    if ($path = drush_get_option('path', NULL)) {
      drush_set_error('invalid_dir', 'Invalid path: ' . $path);
    }
    else {
      drush_set_error('no_directory', 'Cannot determine base directory of module ' . $module . '. Try passing --path=modules/foobar');
    }
  }
}

/**
 * Validates any of the DMU commands.
 *
 * @param string $module
 *   Module name.
 */
function _dmu_validate_command($module) {
  _dmu_ensure_info_present($module);
  _dmu_ensure_autoload();
  _dmu_ensure_directory($module);
}

/**
 * Build our target.
 *
 * @param string $module
 *   Module name.
 *
 * @return \Drupal\drupalmoduleupgrader\Target
 *   The target.
 */
function _dmu_build_target($module) {
  $target = new Target(_dmu_get_directory($module), \Drupal::getContainer());
  drush_print(\Drupal::translation()
    ->translate('Indexing...'), 0, NULL, FALSE);
  $target
    ->buildIndex();
  drush_print(\Drupal::translation()
    ->translate('done.'));
  return $target;
}

/**
 * Lists all the available module-wide plugins.
 *
 * @param string $plugin_type
 *   Plugin type.
 */
function drush_drupalmoduleupgrader_dmu_list($plugin_type) {
  $manager = \Drupal::service('plugin.manager.drupalmoduleupgrader.' . $plugin_type);
  $list = [];
  foreach ($manager
    ->getDefinitions() as $id => $definition) {
    $list[$id] = $definition['description'];
  }
  drush_print_table(drush_key_value_to_array_table($list));
}

/**
 * DMU index validation.
 *
 * @param string $module
 *   Module name.
 */
function drush_drupalmoduleupgrader_dmu_index_validate($module) {
  _dmu_validate_command($module);
}

/**
 * DMU analyze validation.
 *
 * @param string $module
 *   Module name.
 */
function drush_drupalmoduleupgrader_dmu_analyze_validate($module) {
  _dmu_validate_command($module);
}

/**
 * Analyzes what needs changing in a module to port it to Drupal 8.
 *
 * @param string $module
 *   The machine name of the module to analyze.
 */
function drush_drupalmoduleupgrader_dmu_analyze($module) {
  $target = _dmu_build_target($module);
  $total_issues = 0;
  $report = new Report();
  $analyzers = \Drupal::service('plugin.manager.drupalmoduleupgrader.analyzer');
  foreach (_dmu_plugin_list('analyzer') as $id) {
    drush_log(\Drupal::translation()
      ->translate('Executing plugin: @plugin_id', [
      '@plugin_id' => $id,
    ]), 'notice');
    $issues = $analyzers
      ->createInstance($id)
      ->analyze($target);
    if ($issues) {
      if (!is_array($issues)) {
        $issues = [
          $issues,
        ];
      }
      foreach ($issues as $issue) {
        $report
          ->addIssue($issue);
      }
      $total_issues += count($issues);
    }
  }
  if ($total_issues) {
    $render = [
      '#theme' => 'dmu_report',
      '#report' => $report,
      '#group_by' => 'category',
    ];
    $destination = drush_get_option('output', $target
      ->getPath('upgrade-info.html'));
    $output = \Drupal::service('renderer')
      ->renderRoot($render);
    file_put_contents($destination, $output);
    drush_log(\Drupal::translation()
      ->translate('Generated a report at @path', [
      '@path' => $destination,
    ]), 'success');
  }
  else {
    drush_log(\Drupal::translation()
      ->translate('Wow...no issues found! You get a cookie :)', 'success'));
  }
}

/**
 * DMU Upgrade validation.
 *
 * @param string $module
 *   Module name.
 */
function drush_drupalmoduleupgrader_dmu_upgrade_validate($module) {
  _dmu_validate_command($module);
}

/**
 * Tries to automatically convert a Drupal 7 module to Drupal 8.
 *
 * @param string $module
 *   The module to upgrade.
 */
function drush_drupalmoduleupgrader_dmu_upgrade($module) {
  $target = _dmu_build_target($module);
  if (drush_get_option('backup', FALSE)) {
    $fs = new Filesystem();
    $backup_at = $target
      ->getBasePath() . '.bak';
    $fs
      ->mirror($target
      ->getBasePath(), $backup_at);
    drush_log(\Drupal::translation()
      ->translate('Created backup at @path', [
      '@path' => $backup_at,
    ]), 'success');
  }
  $converters = \Drupal::service('plugin.manager.drupalmoduleupgrader.converter');
  foreach (_dmu_plugin_list('converter') as $id) {

    /** @var \Drupal\drupalmoduleupgrader\ConverterInterface $converter */
    $converter = $converters
      ->createInstance($id);
    if ($converter
      ->isExecutable($target)) {
      drush_log(\Drupal::translation()
        ->translate('Executing plugin: @plugin_id', [
        '@plugin_id' => $id,
      ]), 'notice');
      try {
        $converter
          ->convert($target);
      } catch (Exception $e) {
        drush_log($e
          ->getMessage(), 'error');

        // Being a notice, the stack trace will only appear in verbose mode.
        drush_log($e
          ->getTraceAsString(), 'notice');
      }
    }
  }
}

Functions

Namesort descending Description
drupalmoduleupgrader_drush_command Implements hook_drush_command().
drush_drupalmoduleupgrader_dmu_analyze Analyzes what needs changing in a module to port it to Drupal 8.
drush_drupalmoduleupgrader_dmu_analyze_validate DMU analyze validation.
drush_drupalmoduleupgrader_dmu_index_validate DMU index validation.
drush_drupalmoduleupgrader_dmu_list Lists all the available module-wide plugins.
drush_drupalmoduleupgrader_dmu_upgrade Tries to automatically convert a Drupal 7 module to Drupal 8.
drush_drupalmoduleupgrader_dmu_upgrade_validate DMU Upgrade validation.
_dmu_build_target Build our target.
_dmu_ensure_autoload Checks for autoload.php and try to include it.
_dmu_ensure_directory Checks possible locations of a target module.
_dmu_ensure_info_present Determines if user is re running drupal module upgrade.
_dmu_get_directory Determines the path to a module.
_dmu_plugin_list Returns a list of plugin IDs of a given type.
_dmu_validate_command Validates any of the DMU commands.