function RecipeCommand::execute

Same name and namespace in other branches
  1. 11.x core/lib/Drupal/Core/Recipe/RecipeCommand.php \Drupal\Core\Recipe\RecipeCommand::execute()

File

core/lib/Drupal/Core/Recipe/RecipeCommand.php, line 62

Class

RecipeCommand
Applies recipe.

Namespace

Drupal\Core\Recipe

Code

protected function execute(InputInterface $input, OutputInterface $output) : int {
  $io = new SymfonyStyle($input, $output);
  $recipe_path = $input->getArgument('path');
  if (!is_string($recipe_path) || !is_dir($recipe_path)) {
    $io->error(sprintf('The supplied path %s is not a directory', $recipe_path));
    return 1;
  }
  // Recipes can only be applied to an already-installed site.
  $container = $this->boot()
    ->getContainer();
  /** @var \Drupal\Core\Config\Checkpoint\CheckpointStorageInterface $checkpoint_storage */
  $checkpoint_storage = $container->get('config.storage.checkpoint');
  $recipe = Recipe::createFromDirectory($recipe_path);
  if ($checkpoint_storage instanceof LoggerAwareInterface) {
    $logger = new ConsoleLogger($output, [
      // The checkpoint storage logs a notice if it decides to not create a
      // checkpoint, and we want to be sure those notices are seen even
      // without additional verbosity.
LogLevel::NOTICE => OutputInterface::VERBOSITY_NORMAL,
    ]);
    $checkpoint_storage->setLogger($logger);
  }
  $backup_checkpoint = $checkpoint_storage->checkpoint("Backup before the '{$recipe->name}' recipe.");
  try {
    $steps = RecipeRunner::toBatchOperations($recipe);
    $progress_bar = $io->createProgressBar();
    $progress_bar->setFormat("%current%/%max% [%bar%]\n%message%\n");
    $progress_bar->setMessage($this->toPlainString(t('Applying recipe')));
    $progress_bar->start(count($steps));
    /** @var array{message?: \Stringable|string, results: array{module?: string[], theme?: string[], content?: string[], recipe?: string[]}} $context */
    $context = [
      'results' => [],
    ];
    foreach ($steps as $step) {
      call_user_func_array($step[0], array_merge($step[1], [
        &$context,
      ]));
      if (isset($context['message'])) {
        $progress_bar->setMessage($this->toPlainString($context['message']));
      }
      unset($context['message']);
      $progress_bar->advance();
    }
    if ($io->isVerbose()) {
      if (!empty($context['results']['module'])) {
        $io->section($this->toPlainString(t('Modules installed')));
        $modules = array_map(fn($module) => \Drupal::service('extension.list.module')->getName($module), $context['results']['module']);
        sort($modules, SORT_NATURAL);
        $io->listing($modules);
      }
      if (!empty($context['results']['theme'])) {
        $io->section($this->toPlainString(t('Themes installed')));
        $themes = array_map(fn($theme) => \Drupal::service('extension.list.theme')->getName($theme), $context['results']['theme']);
        sort($themes, SORT_NATURAL);
        $io->listing($themes);
      }
      if (!empty($context['results']['content'])) {
        $io->section($this->toPlainString(t('Content created for recipes')));
        $io->listing($context['results']['content']);
      }
      if (!empty($context['results']['recipe'])) {
        $io->section($this->toPlainString(t('Recipes applied')));
        $io->listing($context['results']['recipe']);
      }
    }
    $io->success($this->toPlainString(t('%recipe applied successfully', [
      '%recipe' => $recipe->name,
    ])));
    return 0;
  } catch (\Throwable $e) {
    try {
      $this->rollBackToCheckpoint($backup_checkpoint);
    } catch (ConfigImporterException $importer_exception) {
      $io->error($importer_exception->getMessage());
    }
    throw $e;
  }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.