ILIAS  trunk Revision v11.0_alpha-1723-g8e69f309bab
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
MigrateCommand.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
21 namespace ILIAS\Setup\CLI;
22 
33 
37 class MigrateCommand extends Command
38 {
39  use HasAgent;
40  use ObjectiveHelper;
41 
42  protected static $defaultName = "migrate";
43 
47  protected array $preconditions;
48 
52  public function __construct(AgentFinder $agent_finder, array $preconditions)
53  {
55  $this->agent_finder = $agent_finder;
56  $this->preconditions = $preconditions;
57  }
58 
59  protected function configure(): void
60  {
61  $this->setDescription("Starts and manages migrations needed after an update of ILIAS");
62  $this->addOption("yes", "y", InputOption::VALUE_NONE, "Confirm every message of the installation.");
63  $this->addOption("run", "R", InputOption::VALUE_REQUIRED, "Run the migration with the name given.");
64  $this->addOption(
65  "steps",
66  "S",
67  InputOption::VALUE_REQUIRED,
68  "Run the selected migration with X steps. Pass " . Migration::INFINITE . " for all remaining steps."
69  );
71  }
72 
73  protected function execute(InputInterface $input, OutputInterface $output): int
74  {
75  $io = new IOWrapper($input, $output);
76  $io->printLicenseMessage();
77  $io->title("Trigger migrations in ILIAS");
78 
79  // Dispatching further sub-commands
80  if ($input->hasOption('run') && !empty($input->getOption('run'))) {
81  $this->runMigration($input, $io);
82  } else {
83  $this->listMigrations($input, $io);
84  }
85 
86  return 0;
87  }
88 
89  protected function runMigration(InputInterface $input, IOWrapper $io): void
90  {
91  $agent = $this->getRelevantAgent($input);
92 
93  $migration_name = $input->getOption('run');
94  $migrations = $agent->getMigrations();
95  if (!isset($migrations[$migration_name]) || !($migrations[$migration_name] instanceof Migration)) {
96  $io->error("Aborting Migration, did not find $migration_name.");
97  return;
98  }
99  $migration = $migrations[$migration_name];
100 
101  $steps = (int) $input->getOption('steps');
102 
103  switch ($steps) {
104  case Migration::INFINITE:
105  $io->text("Determined infinite steps to run.");
106  break;
107  case 0:
108  $steps = $migration->getDefaultAmountOfStepsPerRun();
109  $io->text("no --steps option found, fallback to default amount of steps of migration. ($steps)");
110  break;
111  default:
112  $io->text("Determined $steps step(s) to run.");
113  break;
114  }
115  $objective = new Objective\MigrationObjective($migration, $steps);
116 
117  $env = new ArrayEnvironment([
119  ]);
120 
121  $preconditions = $migration->getPreconditions($env);
122  if ($preconditions !== []) {
123  $objective = new Objective\ObjectiveWithPreconditions(
124  $objective,
125  ...$preconditions
126  );
127  }
128  $steps_text = $steps === Migration::INFINITE ? 'all' : (string) $steps;
129  $io->inform("Preparing Environment for {$steps_text} steps in {$migration_name}");
130  try {
131  $this->achieveObjective($objective, $env, $io);
132  } catch (NoConfirmationException $e) {
133  $io->error("Aborting Migration, a necessary confirmation is missing:\n\n" . $e->getRequestedConfirmation());
134  }
135  }
136 
137  protected function listMigrations(InputInterface $input, IOWrapper $io): void
138  {
139  $agent = $this->getRelevantAgent($input);
140  $migrations = $agent->getMigrations();
141  $count = count($migrations);
142  if ($count === 0) {
143  $io->inform("There are currently no migrations to run.");
144  return;
145  }
146 
147  $env = new ArrayEnvironment([
149  ]);
150 
151  $io->inform("Found $count migrations:");
152  foreach ($migrations as $migration_key => $migration) {
153  $env = $this->prepareEnvironmentForMigration($env, $migration);
154  $migration->prepare($env);
155  $steps = $migration->getRemainingAmountOfSteps();
156  $status = $steps === 0 ? "[done]" : "[remaining steps: $steps]";
157  $io->text($migration_key . ": " . $migration->getLabel() . " " . $status);
158  }
159  $io->inform('Run them by passing --run <migration_id>, e.g. --run ' . $migration_key);
160  }
161 
162  protected function prepareEnvironmentForMigration(
163  Environment $environment,
164  Migration $migration
165  ): Environment {
166  $preconditions = $migration->getPreconditions($environment);
167  if ($preconditions !== []) {
168  $objective = new Objective\ObjectiveWithPreconditions(
169  new Objective\NullObjective(),
170  ...$preconditions
171  );
172 
173  $environment = $this->achieveObjective($objective, $environment);
174  }
175 
176  return $environment;
177  }
178 }
Wrapper around symfonies input and output facilities to provide just the functionality required for t...
Definition: IOWrapper.php:32
An objective is a desired state of the system that is supposed to be created by the setup...
Definition: Objective.php:30
A migration is a potentially long lasting operation that can be broken into discrete steps...
Definition: Migration.php:28
execute(InputInterface $input, OutputInterface $output)
__construct(AgentFinder $agent_finder, array $preconditions)
A non-objective, nothing to do to achieve it...
getRelevantAgent(InputInterface $input)
Definition: HasAgent.php:40
prepareEnvironmentForMigration(Environment $environment, Migration $migration)
runMigration(InputInterface $input, IOWrapper $io)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
An environment holds resources to be used in the setup process.
Definition: Environment.php:27
configureCommandForPlugins()
Definition: HasAgent.php:33
__construct(Container $dic, ilPlugin $plugin)
trait HasAgent
Add this to an Command that has an agent.
Definition: HasAgent.php:30
listMigrations(InputInterface $input, IOWrapper $io)
Signals that a necessary confirmation from the admin is missing.
inform(string $message)
Definition: IOWrapper.php:67
getPreconditions(Environment $environment)
Objectives the migration depend on.
array $preconditions
var Objective[]