ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilDatabasePopulatedObjective.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
26
28{
29 public const MIN_NUMBER_OF_ILIAS_TABLES = 200; // educated guess
30
31 public function getHash(): string
32 {
33 return hash("sha256", implode("-", [
34 self::class,
35 $this->config->getHost(),
36 $this->config->getPort(),
37 $this->config->getDatabase()
38 ]));
39 }
40
41 public function getLabel(): string
42 {
43 return "The database is populated with ILIAS-tables.";
44 }
45
46 public function isNotable(): bool
47 {
48 return true;
49 }
50
54 public function getPreconditions(Environment $environment): array
55 {
56 if ($environment->hasConfigFor(InstallCommand::IMPORT)) {
58 new \ilDatabaseExistsObjective($this->config),
59 new ImportFileUnzippedFileObjective($environment->getConfigFor(InstallCommand::IMPORT))
60 )];
61 }
62 if ($environment->getResource(Environment::RESOURCE_DATABASE)) {
63 return [];
64 }
65 return [
66 new \ilDatabaseExistsObjective($this->config)
67 ];
68 }
69
70 public function achieve(Environment $environment): Environment
71 {
76 $db = $environment->getResource(Environment::RESOURCE_DATABASE);
77 $io = $environment->getResource(Environment::RESOURCE_ADMIN_INTERACTION);
78
79 // $this->setDefaultEngine($db); // maybe we could set the default?
80 $default = $this->getDefaultEngine($db);
81
82 $io->text("Default DB engine is $default");
83
84
85 switch ($default) {
86 case 'innodb':
87 $io->text("reading dump file, this may take a while...");
88 $this->readDumpFile($db);
89 break;
90
91 default:
92 throw new UnachievableException(
93 "Cannot determine database default engine, must be InnoDB, `$default` given."
94 );
95 }
96
97 return $environment;
98 }
99
103 public function isApplicable(Environment $environment): bool
104 {
105 if ($environment->hasConfigFor(InstallCommand::IMPORT)) {
106 return true;
107 }
108
109 $db = $environment->getResource(Environment::RESOURCE_DATABASE);
110
111 return !$this->isDatabasePopulated($db);
112 }
113
114 protected function isDatabasePopulated(ilDBInterface $db): bool
115 {
116 $probe_tables = ['usr_data', 'object_data', 'object_reference'];
117 $number_of_probe_tables = count($probe_tables);
118 $tables = $db->listTables();
119 $number_of_tables = count($tables);
120
121 return
122 $number_of_tables > self::MIN_NUMBER_OF_ILIAS_TABLES
123 && count(array_intersect($tables, $probe_tables)) === $number_of_probe_tables;
124 }
125
129 private function readDumpFile(ilDBInterface $db): void
130 {
131 $path_to_db_dump = $this->config->getPathToDBDump();
132 if (!is_file(realpath($path_to_db_dump) ?: '') ||
133 !is_readable(realpath($path_to_db_dump) ?: '')) {
134 throw new UnachievableException(
135 "Cannot read database dump file: $path_to_db_dump"
136 );
137 }
138 foreach ($this->queryReader(realpath($path_to_db_dump)) as $query) {
139 try {
140 $statement = $db->prepareManip($query);
141 $db->execute($statement);
142 } catch (Throwable $e) {
143 throw new UnachievableException(
144 "Cannot populate database with dump file: $path_to_db_dump. Query failed: $query wih message " . $e->getMessage(
145 )
146 );
147 }
148 }
149 }
150
151 private function queryReader(string $path_to_db_dump): Generator
152 {
153 $stack = '';
154 $handle = fopen($path_to_db_dump, "r");
155 while (($line = fgets($handle)) !== false) {
156 if (preg_match('/^--/', $line)) { // Skip comments
157 continue;
158 }
159 if (preg_match('/^\/\*/', $line)) { // Run Variables Assignments as single query
160 yield $line;
161 $stack = '';
162 continue;
163 }
164 if (!preg_match('/;$/', trim($line))) { // Break after ; character which indicates end of query
165 $stack .= $line;
166 } else {
167 $stack .= $line;
168 yield $stack;
169 $stack = '';
170 }
171 }
172
173 fclose($handle);
174 }
175
180 private function setDefaultEngine(ilDBInterface $db): void
181 {
182 switch ($db->getDBType()) {
183 case 'pdo-mysql-innodb':
187 $db->manipulate('SET default_storage_engine=InnoDB;');
188 break;
189 }
190 }
191
192 private function getDefaultEngine(ilDBInterface $db): string
193 {
194 try {
195 $r = $db->query('SHOW ENGINES ');
196
197 $default = '';
198 while ($d = $db->fetchObject($r)) {
199 if (strtoupper((string) $d->Support) === 'DEFAULT') {
200 $default = $d->Engine;
201 break;
202 }
203 }
204 return strtolower((string) $default);
205 } catch (Throwable) {
206 return 'unknown';
207 }
208 }
209}
A wrapper around an objective that adds some preconditions.
Signals that some goal won't be achievable by actions of the system ever.
isApplicable(Environment $environment)
@inheritDoc
getLabel()
Get a label that describes this objective.
isNotable()
Get to know if this is an interesting objective for a human.
An environment holds resources to be used in the setup process.
Definition: Environment.php:28
hasConfigFor(string $component)
getConfigFor(string $component)
getResource(string $id)
Consumers of this method should check if the result is what they expect, e.g.
achieve(Environment $environment)
Objectives can be achieved.
Interface ilDBInterface.
fetchObject(ilDBStatement $query_result)
prepareManip(string $a_query, ?array $a_types=null)
execute(ilDBStatement $stmt, array $data=[])
manipulate(string $query)
Run a (write) Query on the database.
getDBType()
Get DSN.
query(string $query)
Run a (read-only) Query on the database.