You are here

public function MarkdownCommands::versionHash in Markdown 8.2

Run the markdown:version-hash hook.

@command markdown:version-hash @option force Flag indicating whether to force generate even if it exits.

Parameters

string $package: The composer package to generate version hashes for.

Return value

false|void An error message or nothing if successful.

Deprecated

in markdown:8.x-2.0 and is removed from markdown:3.0.0. No replacement.

See also

https://www.drupal.org/project/markdown/issues/3103679

File

src/Commands/MarkdownCommands.php, line 188

Class

MarkdownCommands
Markdown commands for Drush 9+.

Namespace

Drupal\markdown\Commands

Code

public function versionHash($package = NULL, array $options = [
  'force' => FALSE,
]) {
  $force = !empty($options['force']);
  if (!($tempDir = $this
    ->createTempDir())) {
    return drush_set_error('MARKDOWN_FILE_SYSTEM', $this
      ->t('Unable to create temporary directory.'));
  }

  // Change CWD to the temp directory.
  chdir($tempDir);

  // Initialize a composer project (silence warning).
  $this
    ->exec("composer -n init 2>&1", $exitStatus);
  if ($exitStatus) {
    return drush_set_error('MARKDOWN_COMPOSER_FAILURE', $this
      ->t('Unable to initialize temporary Composer project. Make sure you have "composer" defined in your environment paths.'));
  }
  $versionHashFile = __DIR__ . '/../../' . Composer::VERSION_HASH_FILE_NAME;
  $versionHashJson = file_exists($versionHashFile) ? Json::decode(file_get_contents($versionHashFile)) : [];
  $packages = $package ? array_map('trim', explode(',', $package)) : static::$versionHashPackages;
  natsort($packages);

  // Validate provided packages are supported.
  foreach ($packages as $package) {
    if (!in_array($package, static::$versionHashPackages, TRUE)) {
      return drush_set_error('MARKDOWN_UNSUPPORTED_PACKAGE', $this
        ->t('Package not supported: @package', [
        '@package' => $package,
      ]));
    }
  }

  // Iterate over packages.
  foreach ($packages as $package) {
    $constraints = isset(static::$versionHashPackageConstraints[$package]) ? static::$versionHashPackageConstraints[$package] : NULL;
    $variables = [
      '@constraints' => Markup::create($constraints),
      '@package' => $package,
    ];
    $label = $constraints ? '[@package:@constraints]' : '[@package]';
    $this
      ->logger()
      ->log('status', $this
      ->t("{$label} Checking latest version information", $variables));
    $output = $this
      ->exec("composer -n --no-ansi --format=json show {$package} -a 2>&1", $exitStatus);
    if ($exitStatus) {
      return drush_set_error('MARKDOWN_COMPOSER_FAILURE', $this
        ->t('Unable to determine versions for package: @package', $variables));
    }
    $composerJson = Json::decode($output);
    if (!$composerJson) {
      return drush_set_error('MARKDOWN_COMPOSER_FAILURE', $this
        ->t('Unable to JSON decode composer output. Ensure you have the latest version of Composer installed.'));
    }
    $composerJson += [
      'versions' => [],
    ];
    $versions = Semver::sort(array_filter($composerJson['versions'], function ($version) use ($package, $constraints) {
      return strpos($version, 'dev') === FALSE && (!isset($constraints) || Semver::satisfies($version, $constraints));
    }));
    $variables['@version_count'] = count($versions);
    $variables['@missing_version_count'] = count(array_filter($versions, function ($version) use ($versionHashJson, $package) {
      return !isset($versionHashJson[$package][$version]);
    }));
    $this
      ->logger()
      ->log('status', $this
      ->t("{$label} @version_count versions found (@missing_version_count missing generated hashes)", $variables));
    foreach ($versions as $version) {
      $variables['@current_version'] = $version;
      if (!$force && isset($versionHashJson[$package][$version])) {
        $variables['@current_hash'] = $versionHashJson[$package][$version];
        $this
          ->logger()
          ->log('status', $this
          ->t("[@package:@current_version] @current_hash", $variables));
        continue;
      }
      if (!($packageVersionTempDir = $this
        ->createTempDir())) {
        return drush_set_error('MARKDOWN_FILE_SYSTEM', $this
          ->t('Unable to create temporary directory.'));
      }

      // Change CWD to the temp directory.
      chdir($packageVersionTempDir);
      $output = $this
        ->exec("composer init -n; composer -n --no-ansi require {$package}:{$version} --ignore-platform-reqs 2>&1", $exitStatus);
      if ($exitStatus) {
        return drush_set_error('MARKDOWN_COMPOSER_FAILURE', $output);
      }
      $packageVendorDir = "{$packageVersionTempDir}/vendor/{$package}";
      if (!is_dir($packageVendorDir)) {
        return drush_set_error('MARKDOWN_COMPOSER_FAILURE', $this
          ->t('Unable to install @package:@current_version', $variables));
      }

      // Change CWD to the package vendor dir.
      chdir($packageVendorDir);
      if (!Composer::getJson($packageVendorDir, $name)) {
        return drush_set_error('MARKDOWN_COMPOSER_FAILURE', $this
          ->t('Unable to read composer.json for @package:@current_version', $variables));
      }
      if (!($hash = Composer::generateHash($packageVendorDir))) {
        return drush_set_error('MARKDOWN_COMPOSER_FAILURE', $this
          ->t('Unable to generate hash for @package:@current_version', $variables));
      }
      $versionHashJson[$package][$version] = $variables['@current_hash'] = $hash;

      // In the event that the actual name of the package is different from
      // the current one, save a copy of that previous package name as well.
      // This can occur for older versions where a namespace change occurred.
      if ($name !== $package) {
        $versionHashJson[$name][$version] = $hash;
      }

      // Save file after each version, just in case it gets interrupted.
      file_put_contents($versionHashFile, $this
        ->jsonEncodePrettyPrint($versionHashJson));
      $this
        ->logger()
        ->log('status', $this
        ->t("[@package:@current_version] @current_hash", $variables));
    }
  }

  // Finally, save the file one last time to ensure everything was written
  // and the entire JSON array is properly sorted.
  ksort($versionHashJson);
  foreach ($versionHashJson as $package => &$hashes) {
    Semver::ksort($hashes);
  }
  file_put_contents($versionHashFile, $this
    ->jsonEncodePrettyPrint($versionHashJson));
}