ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
class.ilResourceStorageMigrationHelper.php
Go to the documentation of this file.
1 <?php
2 
43 
49 {
50  protected string $client_data_dir;
57  protected Manager $manager;
58 
64  public function __construct(
65  ResourceStakeholder $stakeholder,
66  Environment $environment
67  ) {
68  $this->stakeholder = $stakeholder;
70  $db = $environment->getResource(Environment::RESOURCE_DATABASE);
71  $ilias_ini = $environment->getResource(Environment::RESOURCE_ILIAS_INI);
72  $client_id = $environment->getResource(Environment::RESOURCE_CLIENT_ID);
73  $data_dir = $ilias_ini->readVariable('clients', 'datadir');
74  $client_data_dir = "{$data_dir}/{$client_id}";
75  if (!defined("CLIENT_WEB_DIR")) {
76  define("CLIENT_WEB_DIR", dirname(__DIR__, 5) . "/public/data/" . $client_id);
77  }
78  if (!defined("ILIAS_WEB_DIR")) {
79  define("ILIAS_WEB_DIR", 'public/data');
80  }
81  if (!defined("CLIENT_ID")) {
82  define("CLIENT_ID", $client_id);
83  }
84  if (!defined("ILIAS_DATA_DIR")) {
85  define("ILIAS_DATA_DIR", $data_dir);
86  }
87  $this->client_data_dir = $client_data_dir;
88  $this->database = $db;
89 
90  if (!is_writable("{$data_dir}/{$client_id}/storage/fsv2")) {
91  throw new Exception('storage directory is not writable, abort...');
92  }
93 
94  // Build Container
95  $init = new InitResourceStorage();
96  $container = new Container();
97  $container['ilDB'] = $db;
98  $storageConfiguration = new LocalConfig($client_data_dir);
100  $container['filesystem.storage'] = $f->getLocal($storageConfiguration);
101 
102  $this->resource_builder = $init->getResourceBuilder($container);
103  $this->flavour_builder = $init->getFlavourBuilder($container);
104  $this->collection_builder = new CollectionBuilder(
105  new CollectionDBRepository($db),
106  new Subject()
107  );
108 
109  $this->repositories = $container[InitResourceStorage::D_REPOSITORIES];
110 
111  $this->manager = new Manager(
112  $this->resource_builder,
113  $this->collection_builder,
115  );
116  }
117 
121  public static function getPreconditions(): array
122  {
123  return [
130  ];
131  }
132 
133  public function getClientDataDir(): string
134  {
135  return $this->client_data_dir;
136  }
137 
138  public function getDatabase(): ilDBInterface
139  {
140  return $this->database;
141  }
142 
144  {
145  return $this->stakeholder;
146  }
147 
149  {
151  }
153  {
154  return $this->flavour_builder;
155  }
156 
158  {
160  }
161 
162  public function getManager(): Manager
163  {
164  return $this->manager;
165  }
166 
168  ResourceIdentification $resource_identification,
169  ResourceStakeholder $old_stakeholder,
170  ResourceStakeholder $new_stakeholder,
171  ?int $new_owner_id = null
172  ): void {
173  $resource = $this->manager->getResource($resource_identification);
174  $resource->removeStakeholder($old_stakeholder);
175  $this->repositories->getStakeholderRepository()->deregister($resource_identification, $old_stakeholder);
176  $resource->addStakeholder($new_stakeholder);
177  $this->repositories->getStakeholderRepository()->register($resource_identification, $new_stakeholder);
178 
179  if ($new_owner_id !== null) {
180  foreach ($resource->getAllRevisionsIncludingDraft() as $revision) {
181  $revision->setOwnerId($new_owner_id);
182  }
183  }
184 
185  $this->resource_builder->store($resource);
186  }
187 
188 
189  public function moveFilesOfPathToCollection(
190  string $absolute_path,
191  int $resource_owner_id,
192  int $collection_owner_user_id = ResourceCollection::NO_SPECIFIC_OWNER,
193  ?Closure $file_name_callback = null,
194  ?Closure $revision_name_callback = null
196  $collection = $this->getCollectionBuilder()->new($collection_owner_user_id);
198  foreach (new DirectoryIterator($absolute_path) as $file_info) {
199  if (!$file_info->isFile()) {
200  continue;
201  }
202  $resource_id = $this->movePathToStorage(
203  $file_info->getRealPath(),
204  $resource_owner_id,
205  $file_name_callback,
206  $revision_name_callback
207  );
208  if ($resource_id !== null) {
209  $collection->add($resource_id);
210  }
211  }
212 
213  if ($this->getCollectionBuilder()->store($collection)) {
214  return $collection->getIdentification();
215  }
216  return null;
217  }
218 
220  string $absolute_base_path,
221  string $pattern,
222  int $resource_owner_id,
223  int $collection_owner_user_id = ResourceCollection::NO_SPECIFIC_OWNER,
224  ?Closure $file_name_callback = null,
225  ?Closure $revision_name_callback = null
227  $collection = $this->getCollectionBuilder()->new($collection_owner_user_id);
228 
229  $regex_iterator = $this->buildRecursivePatternIterator($absolute_base_path, $pattern);
230 
231  foreach ($regex_iterator as $file_info) {
232  if (!$file_info->isFile()) {
233  continue;
234  }
235  $resource_id = $this->movePathToStorage(
236  $file_info->getRealPath(),
237  $resource_owner_id,
238  $file_name_callback,
239  $revision_name_callback
240  );
241  if ($resource_id !== null) {
242  $collection->add($resource_id);
243  }
244  }
245  if ($collection->count() === 0) {
246  return null;
247  }
248 
249  if ($this->getCollectionBuilder()->store($collection)) {
250  return $collection->getIdentification();
251  }
252  return null;
253  }
254 
256  string $absolute_base_path,
257  string $pattern,
258  int $resource_owner_id,
259  ?Closure $file_name_callback = null,
260  ?Closure $revision_name_callback = null
262  $regex_iterator = $this->buildRecursivePatternIterator($absolute_base_path, $pattern);
263 
264  foreach ($regex_iterator as $file_info) {
265  if (!$file_info->isFile()) {
266  continue;
267  }
268  $resource_id = $this->movePathToStorage(
269  $file_info->getRealPath(),
270  $resource_owner_id,
271  $file_name_callback,
272  $revision_name_callback
273  );
274  if ($resource_id !== null) {
275  return $resource_id; // stop after first file
276  }
277  }
278 
279  return null;
280  }
281 
282  public function movePathToStorage(
283  string $absolute_path,
284  int $owner_user_id,
285  ?Closure $file_name_callback = null,
286  ?Closure $revision_name_callback = null,
287  ?bool $copy_instead_of_move = false
289  try {
290  // in some cases fopen throws a warning instead of returning false
291  $open_path = fopen($absolute_path, 'rb');
292  } catch (Throwable $e) {
293  return null;
294  }
295 
296  if ($open_path === false) {
297  return null;
298  }
299  $stream = Streams::ofResource($open_path);
300 
301  // create new resource from legacy files stream
302  $revision_title = $revision_name_callback !== null
303  ? $revision_name_callback(basename($absolute_path))
304  : basename($absolute_path);
305 
306  $file_name = $file_name_callback !== null
307  ? $file_name_callback(basename($absolute_path))
308  : null;
309 
310  $resource = $this->resource_builder->newFromStream(
311  $stream,
312  new StreamInfoResolver(
313  $stream,
314  1,
315  $owner_user_id,
316  $revision_title,
317  $file_name
318  ),
319  $copy_instead_of_move ?? false
320  );
321 
322  // add stakeholder and store resource
323  $resource->addStakeholder($this->stakeholder);
324  $this->resource_builder->store($resource);
325 
326  return $resource->getIdentification();
327  }
328 
330  string $absolute_path_to_directory,
331  int $owner_user_id,
333  // check if directory exists
334  if (!is_dir($absolute_path_to_directory)) {
335  return null;
336  }
337 
338  $zip = new Zip(
339  (new ZipOptions())->withDirectoryHandling(ZipDirectoryHandling::KEEP_STRUCTURE)
340  );
341  $zip->addDirectory($absolute_path_to_directory);
342  try {
343  $zip_stream = $zip->get();
344  } catch (Throwable $e) {
345  $zip->destroy();
346  return null; // could not create zip
347  }
348 
349  $resource = $this->resource_builder->newFromStream(
350  $zip_stream,
351  new StreamInfoResolver(
352  $zip_stream,
353  1,
354  $owner_user_id,
355  basename($absolute_path_to_directory),
356  basename($absolute_path_to_directory)
357  ),
358  true,
360  );
361 
362  // add stakeholder and store resource
363  $resource->addStakeholder($this->stakeholder);
364  $this->resource_builder->store($resource);
365 
366  // ZIP archive is not needed anymore
367  $zip->destroy();
368 
369  return $resource->getIdentification();
370  }
371 
372  protected function buildRecursivePatternIterator(
373  string $absolute_base_path,
374  string $pattern = '.*'
375  ): RecursiveRegexIterator {
376  return new RecursiveRegexIterator(
377  new RecursiveDirectoryIterator($absolute_base_path),
378  $pattern,
379  RecursiveRegexIterator::MATCH
380  );
381  }
382 }
buildRecursivePatternIterator(string $absolute_base_path, string $pattern='.*')
Class ilResourceStorageDB90.
Responsible for loading the Resource Storage into the dependency injection container of ILIAS...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
moveResourceToNewStakeholderAndOwner(ResourceIdentification $resource_identification, ResourceStakeholder $old_stakeholder, ResourceStakeholder $new_stakeholder, ?int $new_owner_id=null)
Customizing of pimple-DIC for ILIAS.
Definition: Container.php:35
$container
Definition: wac.php:13
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getResource(string $id)
Consumers of this method should check if the result is what they expect, e.g.
movePathToStorage(string $absolute_path, int $owner_user_id, ?Closure $file_name_callback=null, ?Closure $revision_name_callback=null, ?bool $copy_instead_of_move=false)
__construct(ResourceStakeholder $stakeholder, Environment $environment)
ilResourceStorageMigrationHelper constructor.
moveDirectoryToContainerResource(string $absolute_path_to_directory, int $owner_user_id,)
moveFirstFileOfPatternToStorage(string $absolute_base_path, string $pattern, int $resource_owner_id, ?Closure $file_name_callback=null, ?Closure $revision_name_callback=null)
An environment holds resources to be used in the setup process.
Definition: Environment.php:27
This class is used to configure the local filesystem adapter.
Definition: LocalConfig.php:29
$client_id
Definition: ltiauth.php:67
moveFilesOfPatternToCollection(string $absolute_base_path, string $pattern, int $resource_owner_id, int $collection_owner_user_id=ResourceCollection::NO_SPECIFIC_OWNER, ?Closure $file_name_callback=null, ?Closure $revision_name_callback=null)