ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
InstallCommand.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
21namespace ILIAS\Setup\CLI;
22
32use Symfony\Component\Console\Input\InputInterface;
33use Symfony\Component\Console\Output\OutputInterface;
34use Symfony\Component\Console\Input\InputArgument;
35use Symfony\Component\Console\Input\InputOption;
36
41{
42 use HasAgent;
44 use ObjectiveHelper;
45
46 public const IMPORT = "import";
47 protected const TMP_DIR = "tmp_dir";
48
49 protected static $defaultName = "install";
50
54 protected array $preconditions = [];
55
59 public function __construct(AgentFinder $agent_finder, ConfigReader $config_reader, array $preconditions)
60 {
62 $this->agent_finder = $agent_finder;
63 $this->config_reader = $config_reader;
64 $this->preconditions = $preconditions;
65 }
66
67 protected function configure(): void
68 {
69 $this->setDescription("Creates a fresh ILIAS installation based on the config");
70 $this->addArgument("config", InputArgument::OPTIONAL, "Configuration file for the installation");
71 $this->addOption("config", null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, "Define fields in the configuration file that should be overwritten, e.g. \"a.b.c=foo\"", []);
72 $this->addOption("yes", "y", InputOption::VALUE_NONE, "Confirm every message of the installation.");
73 $this->addOption("import-file", "i", InputOption::VALUE_REQUIRED, "Path to zip file to import from.");
75 }
76
77 protected function execute(InputInterface $input, OutputInterface $output): int
78 {
79 // ATTENTION: This is a hack to get around the usage of the echo/exit pattern in
80 // the setup for the command line version of the setup. Do not use this.
81 if (!defined("ILIAS_SETUP_IGNORE_DB_UPDATE_STEP_MESSAGES")) {
82 define("ILIAS_SETUP_IGNORE_DB_UPDATE_STEP_MESSAGES", true);
83 }
84
85 if ($input->hasOption('legacy-plugin') && $input->getOption('legacy-plugin') != "") {
86 list($objective, $environment, $io) = $this->preparePluginInstallation($input, $output);
87 } else {
88 list($objective, $environment, $io) = $this->prepareILIASInstallation($input, $output);
89 }
90 try {
91 $this->achieveObjective($objective, $environment, $io);
92 if ($input->hasOption("import-file") && $input->getOption("import-file") != "") {
93 $io->inform("Please ensure that all ILIAS directories (webdir/datadir/Customizing) have the right owner after import process.");
94 }
95 $io->success("Installation complete. Thanks and have fun!");
96 } catch (NoConfirmationException $e) {
97 $io->error("Aborting Installation, a necessary confirmation is missing:\n\n" . $e->getRequestedConfirmation());
98 }
99
100 return 0;
101 }
102
103 protected function prepareILIASInstallation(InputInterface $input, OutputInterface $output): array
104 {
105 $io = new IOWrapper($input, $output);
106 $io->printLicenseMessage();
107 $io->title("Install ILIAS");
108
109 $environment = new ArrayEnvironment([
111 ]);
112
113 if ($input->hasOption("import-file") && $input->getOption("import-file") != "") {
114 if ($input->getArgument("config") == "") {
115 throw new \InvalidArgumentException("Missing configuration file.");
116 }
117 $import_file = $input->getOption("import-file");
118 if (!is_file($import_file)) {
119 throw new \InvalidArgumentException("Can't find import file '$import_file'.");
120 }
121
122 if (pathinfo($import_file)["extension"] != "zip") {
123 throw new \InvalidArgumentException("Wrong file format for import file. 'zip' is expected.");
124 }
125
126 $tmp_dir = $this->createTempDir();
127 if (is_null($tmp_dir)) {
128 throw new \RuntimeException("Can't create temporary directory!");
129 }
130 $environment = $environment
131 ->withConfigFor(self::IMPORT, $input->getOption("import-file"))
132 ->withConfigFor(self::TMP_DIR, $tmp_dir)
133 ;
134 $dump_path = $tmp_dir . DIRECTORY_SEPARATOR . MysqlIfsnopDumper::FILE_NAME;
135 $input->setOption(
136 "config",
137 array_merge($input->getOption("config"), ["database.path_to_db_dump=$dump_path"])
138 );
139 }
140
141 $agent = $this->getRelevantAgent($input);
142
143 $config = $this->readAgentConfig($agent, $input);
144
145 $objective = new ObjectiveCollection(
146 "Install and Update ILIAS",
147 false,
148 $agent->getInstallObjective($config),
149 $agent->getUpdateObjective($config)
150 );
151 if ($this->preconditions !== []) {
152 $objective = new ObjectiveWithPreconditions(
153 $objective,
154 ...$this->preconditions
155 );
156 }
157
158 $environment = $this->addAgentConfigsToEnvironment($agent, $config, $environment);
159 // ATTENTION: This is bad because we strongly couple this generic command
160 // to something very specific here. This can go away once we have got rid of
161 // everything related to clients, since we do not need that client-id then.
162 // This will require some more work, though.
163 $common_config = $config->getConfig("common");
164 $environment = $environment->withResource(
166 $common_config->getClientId()
167 );
168
169 return [$objective, $environment, $io];
170 }
171
172 protected function preparePluginInstallation(InputInterface $input, OutputInterface $output): array
173 {
174 $io = new IOWrapper($input, $output);
175 $io->printLicenseMessage();
176 $io->title("Install ILIAS Plugin");
177
178 $agent = $this->getRelevantAgent($input);
179
180 $config = $this->readAgentConfig($agent, $input, $input->getOption("legacy-plugin"));
181
182 $objective = new ObjectiveCollection(
183 "Install and Update ILIAS Plugin",
184 false,
185 $agent->getInstallObjective($config),
186 $agent->getUpdateObjective($config)
187 );
188 if ($this->preconditions !== []) {
189 $objective = new ObjectiveWithPreconditions(
190 $objective,
191 ...$this->preconditions
192 );
193 }
194
195 $environment = new ArrayEnvironment([
197 ]);
198
199 if (!is_null($config)) {
200 $environment = $this->addAgentConfigsToEnvironment($agent, $config, $environment);
201 }
202
203 return [$objective, $environment, $io];
204 }
205
206 protected function createTempDir(): ?string
207 {
208 $path = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . mt_rand() . microtime(true);
209 if (mkdir($path)) {
210 return $path;
211 }
212 return null;
213 }
214}
Read a json-formatted config from a file and overwrite some fields.
Wrapper around symfonies input and output facilities to provide just the functionality required for t...
Definition: IOWrapper.php:33
__construct(AgentFinder $agent_finder, ConfigReader $config_reader, array $preconditions)
array $preconditions
var Objective[]
execute(InputInterface $input, OutputInterface $output)
preparePluginInstallation(InputInterface $input, OutputInterface $output)
prepareILIASInstallation(InputInterface $input, OutputInterface $output)
Signals that a necessary confirmation from the admin is missing.
A objective collection is a objective that is achieved once all subobjectives are achieved.
A wrapper around an objective that adds some preconditions.
An environment holds resources to be used in the setup process.
Definition: Environment.php:28
$path
Definition: ltiservices.php:30
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
addAgentConfigsToEnvironment(Agent $agent, Config $config, Environment $environment)
trait HasAgent
Add this to an Command that has an agent.
Definition: HasAgent.php:30
getRelevantAgent(InputInterface $input)
Definition: HasAgent.php:40
readAgentConfig(Agent $agent, InputInterface $input, ?string $use_config_field=null)
trait HasConfigReader
Add this to an Command that has an config reader.
configureCommandForPlugins()
Definition: HasAgent.php:33