ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilDatabasePopulatedObjective.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
21 use ILIAS\Setup;
22 
24 {
25  public const MIN_NUMBER_OF_ILIAS_TABLES = 200; // educated guess
26 
27  public function getHash(): string
28  {
29  return hash("sha256", implode("-", [
30  self::class,
31  $this->config->getHost(),
32  $this->config->getPort(),
33  $this->config->getDatabase()
34  ]));
35  }
36 
37  public function getLabel(): string
38  {
39  return "The database is populated with ILIAS-tables.";
40  }
41 
42  public function isNotable(): bool
43  {
44  return true;
45  }
46 
50  public function getPreconditions(Setup\Environment $environment): array
51  {
52  if ($environment->getResource(Setup\Environment::RESOURCE_DATABASE)) {
53  return [];
54  }
55  return [
56  new \ilDatabaseExistsObjective($this->config)
57  ];
58  }
59 
60  public function achieve(Setup\Environment $environment): Setup\Environment
61  {
66  $db = $environment->getResource(Setup\Environment::RESOURCE_DATABASE);
67  $io = $environment->getResource(Setup\Environment::RESOURCE_ADMIN_INTERACTION);
68 
69  // $this->setDefaultEngine($db); // maybe we could set the default?
70  $default = $this->getDefaultEngine($db);
71 
72  $io->text("Default DB engine is $default");
73 
74 
75  switch ($default) {
76  case 'innodb':
77  $io->text("reading dump file, this may take a while...");
78  $this->readDumpFile($db);
79  break;
80 
81  default:
82  throw new Setup\UnachievableException(
83  "Cannot determine database default engine, must be InnoDB, `$default` given."
84  );
85  }
86 
87  return $environment;
88  }
89 
93  public function isApplicable(Setup\Environment $environment): bool
94  {
95  $db = $environment->getResource(Setup\Environment::RESOURCE_DATABASE);
96 
97  return !$this->isDatabasePopulated($db);
98  }
99 
100  protected function isDatabasePopulated(ilDBInterface $db): bool
101  {
102  $probe_tables = ['usr_data', 'object_data', 'object_reference'];
103  $number_of_probe_tables = count($probe_tables);
104  $tables = $db->listTables();
105  $number_of_tables = count($tables);
106 
107  return
108  $number_of_tables > self::MIN_NUMBER_OF_ILIAS_TABLES
109  && count(array_intersect($tables, $probe_tables)) === $number_of_probe_tables;
110  }
111 
115  private function readDumpFile(ilDBInterface $db): void
116  {
117  $path_to_db_dump = $this->config->getPathToDBDump();
118  if (!is_file(realpath($path_to_db_dump)) ||
119  !is_readable(realpath($path_to_db_dump))) {
120  throw new Setup\UnachievableException(
121  "Cannot read database dump file: $path_to_db_dump"
122  );
123  }
124  foreach ($this->queryReader(realpath($path_to_db_dump)) as $query) {
125  try {
126  $statement = $db->prepareManip($query);
127  $db->execute($statement);
128  } catch (Throwable $e) {
129  throw new Setup\UnachievableException(
130  "Cannot populate database with dump file: $path_to_db_dump. Query failed: $query wih message " . $e->getMessage(
131  )
132  );
133  }
134  }
135  }
136 
137  private function queryReader(string $path_to_db_dump): Generator
138  {
139  $stack = '';
140  $handle = fopen($path_to_db_dump, "r");
141  while (($line = fgets($handle)) !== false) {
142  if (preg_match('/^--/', $line)) { // Skip comments
143  continue;
144  }
145  if (preg_match('/^\/\*/', $line)) { // Run Variables Assignments as single query
146  yield $line;
147  $stack = '';
148  continue;
149  }
150  if (!preg_match('/;$/', trim($line))) { // Break after ; character which indicates end of query
151  $stack .= $line;
152  } else {
153  $stack .= $line;
154  yield $stack;
155  $stack = '';
156  }
157  }
158 
159  fclose($handle);
160  }
161 
166  private function setDefaultEngine(ilDBInterface $db): void
167  {
168  switch ($db->getDBType()) {
169  case 'pdo-mysql-innodb':
173  $db->manipulate('SET default_storage_engine=InnoDB;');
174  break;
175  }
176  }
177 
178  private function getDefaultEngine(ilDBInterface $db): string
179  {
180  try {
181  $r = $db->query('SHOW ENGINES ');
182 
183  $default = '';
184  while ($d = $db->fetchObject($r)) {
185  if (strtoupper($d->Support) === 'DEFAULT') {
186  $default = $d->Engine;
187  break;
188  }
189  }
190  return strtolower($default);
191  } catch (Throwable $e) {
192  return 'unknown';
193  }
194  }
195 }
getPreconditions(Setup\Environment $environment)
execute(ilDBStatement $stmt, array $data=[])
fetchObject(ilDBStatement $query_result)
query(string $query)
Run a (read-only) Query on the database.
$query
getDBType()
Get DSN.
isApplicable(Setup\Environment $environment)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
prepareManip(string $a_query, ?array $a_types=null)
An environment holds resources to be used in the setup process.
Definition: Environment.php:27
manipulate(string $query)
Run a (write) Query on the database.
for($i=6; $i< 13; $i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296