ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
CertificateIRSSMigration.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
23 use ilDBConstants;
24 use ilDBInterface;
25 use ReflectionClass;
34 
36 {
37  public const NUMBER_OF_STEPS = 10;
38  public const NUMBER_OF_PATHS_PER_STEP = 10;
39  public const TABLE_TEMPLATE_CERTIFICATES = 'il_cert_template';
40  public const TABLE_USER_CERTIFICATES = 'il_cert_user_cert';
42  private ilDBInterface $db;
43  private ilCertificateTemplateStakeholder $stakeholder;
44  private ?IOWrapper $io = null;
45 
46  public function getLabel(): string
47  {
48  return (new ReflectionClass($this))->getShortName();
49  }
50 
52  {
53  return self::NUMBER_OF_STEPS;
54  }
55 
56  public function getPreconditions(Environment $environment): array
57  {
58  return [
60  ];
61  }
62 
63  public function prepare(Environment $environment): void
64  {
65  $this->db = $environment->getResource(Environment::RESOURCE_DATABASE);
66  $this->helper = new ilResourceStorageMigrationHelper(new ilCertificateTemplateStakeholder(), $environment);
67  $this->stakeholder = new ilCertificateTemplateStakeholder();
69  if ($io instanceof IOWrapper) {
70  $this->io = $io;
71  }
72  }
73 
77  public function step(Environment $environment): void
78  {
80  $remaining_paths = $this->stepCertificates(self::NUMBER_OF_PATHS_PER_STEP, self::TABLE_TEMPLATE_CERTIFICATES);
81  if ($remaining_paths > 0) {
82  $this->stepCertificates($remaining_paths, self::TABLE_USER_CERTIFICATES);
83  }
84  }
85 
86  public function stepCertificates(int $remaining_paths, string $table): int
87  {
88  $this->db->setLimit($remaining_paths);
89  $query = '
90  SELECT path
91  FROM (
92  SELECT id, background_image_path AS path FROM ' . $this->db->quoteIdentifier($table) . '
93  WHERE background_image_ident IS NULL OR background_image_ident = \'\'
94  UNION ALL
95  SELECT id, thumbnail_image_path AS path FROM ' . $this->db->quoteIdentifier($table) . '
96  WHERE thumbnail_image_ident IS NULL OR thumbnail_image_ident = \'\'
97  ) AS t
98  GROUP BY path
99  HAVING path IS NOT NULL AND path != \'\'
100  ';
101  $result = $this->db->query($query);
102  $paths = $this->db->numRows($result);
103  if ($paths > 0) {
104  while ($row = $this->db->fetchAssoc($result)) {
105  $this->updateCertificatePathFromTable($row['path'] ?? '', $table);
106  }
107  $remaining_paths -= self::NUMBER_OF_PATHS_PER_STEP - $paths;
108  }
109 
110  return $remaining_paths;
111  }
112 
113  public function migrateGlobalCertificateBackgroundImage(bool $hotrun = false): int
114  {
115  $result = $this->db->queryF(
116  'SELECT value FROM settings WHERE module = %s AND keyword = %s',
118  ['certificate', 'cert_bg_image']
119  );
120  $row = $this->db->fetchAssoc($result);
121 
122  if (!isset($row['value']) || $row['value'] === '') {
123  return 0;
124  }
125 
126  $path_to_file = ILIAS_ABSOLUTE_PATH . '/' . ILIAS_WEB_DIR . '/' . CLIENT_ID . '/certificates/default/' . $row['value'];
127  if (!is_file($path_to_file)) {
128  return 0;
129  }
130 
131  if (!$hotrun) {
132  return 1;
133  }
134 
135  $this->inform("Migrating global default certificate background image: $path_to_file");
136  $resource_id = $this->helper->movePathToStorage(
137  $path_to_file,
138  $this->stakeholder->getOwnerOfNewResources(),
139  null,
140  null,
141  true
142  );
143 
144  $image_ident = '-';
145  if ($resource_id instanceof ResourceIdentification) {
146  $image_ident = $resource_id->serialize();
147  $this->inform(
148  "IRSS identification for global default certificate background image: $image_ident",
149  true
150  );
151  } else {
152  $this->error(
153  'IRSS returned NULL as identification when trying to move global default background image ' .
154  "file $path_to_file to the storage service."
155  );
156  }
157 
159  '/certificates/default/' . $row['value'],
160  $image_ident
161  );
162 
163  $query = '
164  UPDATE settings
165  SET value = %s
166  WHERE module = %s AND keyword = %s';
167  $this->db->manipulateF(
168  $query,
170  [$image_ident, 'certificate', 'cert_bg_image']
171  );
172 
173  return 0;
174  }
175 
176  public function updateCertificatePathFromTable(string $filepath, string $table): void
177  {
178  if (!$filepath) {
179  return;
180  }
181 
182  $sanitized_filepath = ltrim($filepath);
183  if (str_starts_with($filepath, '/')) {
184  $sanitized_filepath = substr($sanitized_filepath, 1);
185  }
186  $full_path = ILIAS_ABSOLUTE_PATH . '/' . ILIAS_WEB_DIR . '/' . CLIENT_ID . '/' . $sanitized_filepath;
187 
188  $resource_id = $this->helper->movePathToStorage(
189  $full_path,
190  $this->stakeholder->getOwnerOfNewResources(),
191  null,
192  null,
193  true
194  );
195 
196  $image_ident = '-';
197  if ($resource_id instanceof ResourceIdentification) {
198  $image_ident = $resource_id->serialize();
199  $this->inform(
200  "IRSS identification for image path $full_path when migrating table $table: $image_ident" .
201  ($table === self::TABLE_TEMPLATE_CERTIFICATES ? "\n" . self::TABLE_USER_CERTIFICATES . ": $image_ident" : ''),
202  true
203  );
204  } else {
205  $this->error(
206  'IRSS returned NULL as identification when trying to move ' .
207  "file $full_path to the storage service for table $table." .
208  ($table === self::TABLE_TEMPLATE_CERTIFICATES ? "\n" . self::TABLE_USER_CERTIFICATES . ": $image_ident" : '')
209  );
210  }
211 
212  $query = "
213  UPDATE {$this->db->quoteIdentifier($table)}
214  SET background_image_ident = %s WHERE background_image_path = %s;";
215  $this->db->manipulateF(
216  $query,
218  [$image_ident, $filepath]
219  );
220  $query = "
221  UPDATE {$this->db->quoteIdentifier($table)}
222  SET thumbnail_image_ident = %s WHERE thumbnail_image_path = %s;";
223  $this->db->manipulateF(
224  $query,
226  [$image_ident, $filepath]
227  );
228  if ($table === self::TABLE_TEMPLATE_CERTIFICATES) {
229  $query = "
230  UPDATE {$this->db->quoteIdentifier(self::TABLE_USER_CERTIFICATES)}
231  SET background_image_ident = %s WHERE background_image_path = %s;";
232  $this->db->manipulateF(
233  $query,
235  [$image_ident, $filepath]
236  );
237  $query = "
238  UPDATE {$this->db->quoteIdentifier(self::TABLE_USER_CERTIFICATES)}
239  SET thumbnail_image_ident = %s WHERE thumbnail_image_path = %s;";
240  $this->db->manipulateF(
241  $query,
243  [$image_ident, $filepath]
244  );
245  }
246 
247  if ($image_ident !== '-') {
248  $query = "
249  UPDATE {$this->db->quoteIdentifier($table)}
250  SET background_image_path = NULL WHERE background_image_path = %s;";
251  $this->db->manipulateF(
252  $query,
254  [$filepath]
255  );
256  $query = "
257  UPDATE {$this->db->quoteIdentifier($table)}
258  SET thumbnail_image_path = NULL WHERE thumbnail_image_path = %s;";
259  $this->db->manipulateF(
260  $query,
262  [$filepath]
263  );
264  if ($table === self::TABLE_TEMPLATE_CERTIFICATES) {
265  $query = "
266  UPDATE {$this->db->quoteIdentifier(self::TABLE_USER_CERTIFICATES)}
267  SET background_image_path = NULL WHERE background_image_path = %s;";
268  $this->db->manipulateF(
269  $query,
271  [$filepath]
272  );
273  $query = "
274  UPDATE {$this->db->quoteIdentifier(self::TABLE_USER_CERTIFICATES)}
275  SET thumbnail_image_path = NULL WHERE thumbnail_image_path = %s;";
276  $this->db->manipulateF(
277  $query,
279  [$filepath]
280  );
281  }
282  }
283  }
284 
285  public function getRemainingAmountOfSteps(): int
286  {
287  $paths = $this->migrateGlobalCertificateBackgroundImage(false);
288 
289  $result = $this->db->query(
290  '
291  SELECT COUNT(*) AS count
292  FROM (
293  SELECT path
294  FROM (
295  SELECT background_image_path AS path FROM il_cert_user_cert
296  WHERE background_image_ident IS NULL OR background_image_ident = \'\'
297  UNION ALL
298  SELECT thumbnail_image_path AS path FROM il_cert_user_cert
299  WHERE thumbnail_image_ident IS NULL OR thumbnail_image_ident = \'\'
300  UNION ALL
301  SELECT background_image_path AS path FROM il_cert_template
302  WHERE background_image_ident IS NULL OR background_image_ident = \'\'
303  UNION ALL
304  SELECT thumbnail_image_path AS path FROM il_cert_template
305  WHERE thumbnail_image_ident IS NULL OR thumbnail_image_ident = \'\'
306  ) AS t
307  GROUP BY path
308  HAVING path IS NOT NULL AND path != \'\'
309  ) AS t;
310  '
311  );
312  $row = $this->db->fetchAssoc($result);
313 
314  $paths += (int) ($row['count'] ?? 0);
315  $num_steps = (int) ceil($paths / self::NUMBER_OF_STEPS);
316 
317  $this->inform(
318  "Remaining certificate background image/tile image paths: $paths / Number of steps: $num_steps",
319  true
320  );
321 
322  return $num_steps;
323  }
324 
325  public function updateDefaultBackgroundImagePaths(string $old_relative_path, string $new_rid): void
326  {
327  $this->db->manipulateF(
328  '
329  UPDATE il_cert_template SET background_image_ident = %s
330  WHERE currently_active = 1 AND (background_image_path = %s OR background_image_path = %s )
331  AND background_image_ident IS NULL OR background_image_ident = \'\'',
332  [
336  ],
337  [
338  $new_rid,
339  $old_relative_path,
340  '/certificates/default/background.jpg'
341  ]
342  );
343 
344  $this->db->manipulateF(
345  '
346  UPDATE il_cert_user_cert SET background_image_ident = %s
347  WHERE currently_active = 1 AND (background_image_path = %s OR background_image_path = %s )
348  AND background_image_ident IS NULL OR background_image_ident = \'\'',
349  [
353  ],
354  [
355  $new_rid,
356  $old_relative_path,
357  '/certificates/default/background.jpg'
358  ]
359  );
360  }
361 
362  private function inform(string $text, bool $force = false): void
363  {
364  if ($this->io === null || (!$force && !$this->io->isVerbose())) {
365  return;
366  }
367 
368  $this->io->inform($text);
369  }
370 
371  private function error(string $text): void
372  {
373  if ($this->io === null) {
374  return;
375  }
376 
377  $this->io->error($text);
378  }
379 }
updateDefaultBackgroundImagePaths(string $old_relative_path, string $new_rid)
A migration is a potentially long lasting operation that can be broken into discrete steps...
Definition: Migration.php:28
getRemainingAmountOfSteps()
Count up how many "things" need to be migrated.
getDefaultAmountOfStepsPerRun()
Tell the default amount of steps to be executed for one run of the migration.
updateCertificatePathFromTable(string $filepath, string $table)
getPreconditions(Environment $environment)
Objectives the migration depend on.
$text
Definition: xapiexit.php:21
const CLIENT_ID
Definition: constants.php:41
getResource(string $id)
Consumers of this method should check if the result is what they expect, e.g.
An environment holds resources to be used in the setup process.
Definition: Environment.php:27
prepare(Environment $environment)
Prepare the migration by means of some environment.
stepCertificates(int $remaining_paths, string $table)
const ILIAS_WEB_DIR
Definition: constants.php:45