ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilObjectTileImageMigration.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
21 namespace ILIAS\Object\Setup;
22 
29 
34 {
35  private \ilResourceStorageMigrationHelper $helper;
39 
40  public function getLabel(): string
41  {
42  return "Migration of Tile Images to the Resource Storage Service.";
43  }
44 
46  {
47  return 10000;
48  }
49 
50  public function getPreconditions(Environment $environment): array
51  {
52  return \ilResourceStorageMigrationHelper::getPreconditions();
53  }
54 
55  public function prepare(Environment $environment): void
56  {
57  $this->helper = new \ilResourceStorageMigrationHelper(
59  $environment
60  );
61  $this->admin_interaction = $environment->getResource(Environment::RESOURCE_ADMIN_INTERACTION);
62  $this->flavour_builder = $this->helper->getFlavourBuilder();
63  $this->flavour_definition = new ilObjectTileImageFlavourDefinition();
64  }
65 
66  public function step(Environment $environment): void
67  {
68  $query_select = $this->helper->getDatabase()->query('
69  SELECT
70  cs.id,
71  cs.value AS extension,
72  o.owner
73  FROM container_settings AS cs
74  INNER JOIN object_data AS o
75  ON cs.id = o.obj_id
76  WHERE cs.keyword = "tile_image"
77  ORDER BY cs.id
78  LIMIT 1;
79  ');
80  $next_record = $this->helper->getDatabase()->fetchObject($query_select);
81 
82  if ($next_record === null) {
84  return;
85  }
86 
87  $path = $this->getFullPath($next_record->id, $next_record->extension);
88 
89  if (is_readable(dirname(dirname($path)))
90  && (!file_exists(dirname($path))
91  || is_readable(dirname($path)) && !file_exists($path))) {
92  $this->deleteTileImageInfoFromContainerSettings($next_record->id);
93  $this->admin_interaction->inform(
94  "The tile image for the object with the id {$next_record->id} and the path {$path} "
95  . 'could not be migrated. The entry linking the image to the object '
96  . 'was removed, the path to the image has been left on the system.'
97  );
98  return;
99  }
100 
101  $rid = $this->helper->movePathToStorage(
102  $path,
103  $next_record->owner
104  );
105 
106  if ($rid === null) {
107  $this->deleteTileImageInfoFromContainerSettings($next_record->id);
108  $this->admin_interaction->inform(
109  "The tile image for the object with the id {$next_record->id} and the path {$path} "
110  . 'could not be migrated. The database entry linking the image to the object '
111  . 'was removed, the path to the image has been left on the system.'
112  );
113  return;
114  }
115  $this->flavour_builder->get($rid, $this->flavour_definition, true);
116 
117  $this->helper->getDatabase()->update(
118  'object_data',
119  ['tile_image_rid' => ['text', $rid->serialize()]],
120  ['obj_id' => ['integer', $next_record->id],]
121  );
122 
123  $this->removeDirectoryOrInform(\dirname($path), $next_record);
124  $this->deleteTileImageInfoFromContainerSettings($next_record->id);
125  }
126 
127  private function removeDirectoryOrInform(string $directory, \stdClass $record): void
128  {
129  if (!is_dir($directory)) {
130  return;
131  }
132 
133  $files = array_diff(scandir($directory), ['.', '..']);
134  if (empty($files)) {
135  rmdir($directory);
136  } else {
137  $file_list = implode(', ', $files);
138  $this->admin_interaction->inform(
139  "The tile image for the object with the id $record->id was probably migrated successfully. "
140  . "However, the directory $directory could not be removed because it is not empty. "
141  . "Remaining files: $file_list. "
142  . 'You may want to verify that the tile image is visible for the object, and remove '
143  . 'the remaining files manually if they are not needed.'
144  );
145  }
146  }
147 
148  private function getFullPath(int $object_id, ?string $extension): string
149  {
150  return implode(
151  DIRECTORY_SEPARATOR,
152  [
154  'obj_data',
155  'tile_image',
156  'tile_image_' . $object_id,
157  'tile_image.' . $extension
158  ]
159  );
160  }
161 
163  {
164  $select_next_id = $this->helper->getDatabase()->query('
165  SELECT
166  id,
167  value AS extension
168  FROM container_settings
169  WHERE keyword = "tile_image"
170  ORDER BY id
171  LIMIT 1;
172  ');
173  $next_record = $this->helper->getDatabase()->fetchObject($select_next_id);
174 
175  if ($next_record === null) {
176  return;
177  }
178 
179  $check_object_query = $this->helper->getDatabase()->queryF(
180  'SELECT
181  count(obj_id) AS objs
182  FROM object_data
183  WHERE obj_id = %s;
184  ',
185  ['integer'],
186  [$next_record->id]
187  );
188  $has_objects = $this->helper->getDatabase()->fetchObject($check_object_query);
189  $path = $this->getFullPath($next_record->id, $next_record->extension);
190 
191  if ($has_objects->objs > 0) {
192  return;
193  }
194 
195  if (is_file($path)) {
196  unlink($path);
197  }
198 
199  $this->removeDirectoryOrInform(\dirname($path), $next_record);
200  $this->deleteTileImageInfoFromContainerSettings($next_record->id);
201  }
202 
203  private function deleteTileImageInfoFromContainerSettings(int $id): void
204  {
205  $query_delete = $this->helper->getDatabase()->queryF('
206  DELETE FROM container_settings
207  WHERE keyword = "tile_image" AND id = %s
208  ', ['integer'], [$id]);
209  $this->helper->getDatabase()->execute($query_delete);
210  }
211 
212  public function getRemainingAmountOfSteps(): int
213  {
214  $query = $this->helper->getDatabase()->query('
215  SELECT
216  count(container_settings.id) AS amount
217  FROM container_settings
218  WHERE container_settings.keyword = "tile_image"
219  ');
220  $r = $this->helper->getDatabase()->fetchObject($query);
221 
222  return (int) $r->amount;
223  }
224 }
A migration is a potentially long lasting operation that can be broken into discrete steps...
Definition: Migration.php:28
$path
Definition: ltiservices.php:32
This defines ways in which objectives may interact with admins during the setup.
const CLIENT_WEB_DIR
Definition: constants.php:47
getResource(string $id)
Consumers of this method should check if the result is what they expect, e.g.
prepare(Environment $environment)
Prepare the migration by means of some environment.
getDefaultAmountOfStepsPerRun()
Tell the default amount of steps to be executed for one run of the migration.
getPreconditions(Environment $environment)
Objectives the migration depend on.
step(Environment $environment)
Run one step of the migration.
getRemainingAmountOfSteps()
Count up how many "things" need to be migrated.
An environment holds resources to be used in the setup process.
Definition: Environment.php:27
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
removeDirectoryOrInform(string $directory, \stdClass $record)
$r