ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
ResourceBuilder.php
Go to the documentation of this file.
1 <?php declare(strict_types=1);
2 
4 
5 use Generator;
28 
35 {
36  use SecureString;
60  private $lock_handler;
64  protected $resource_cache = [];
68  protected $file_name_policy;
73 
84  public function __construct(
92  ) {
93  $this->storage_handler_factory = $storage_handler_factory;
94  $this->primary_storage_handler = $storage_handler_factory->getPrimary();
95  $this->revision_repository = $revision_repository;
96  $this->resource_repository = $resource_repository;
97  $this->information_repository = $information_repository;
98  $this->stakeholder_repository = $stakeholder_repository;
99  $this->lock_handler = $lock_handler;
100  $this->file_name_policy = $file_name_policy ?? new NoneFileNamePolicy();
101  }
102 
103  //
104  // Methods to create new Resources (from an Upload, a Stream od just a blank one)
105  //
109  public function new(
111  InfoResolver $info_resolver
112  ) : StorableResource {
113  $resource = $this->resource_repository->blank($this->primary_storage_handler->getIdentificationGenerator()->getUniqueResourceIdentification());
114 
115  return $this->append($resource, $result, $info_resolver);
116  }
117 
118  public function newFromStream(
119  FileStream $stream,
120  InfoResolver $info_resolver,
121  bool $keep_original = false
122  ) : StorableResource {
123  $resource = $this->resource_repository->blank($this->primary_storage_handler->getIdentificationGenerator()->getUniqueResourceIdentification());
124 
125  return $this->appendFromStream($resource, $stream, $info_resolver, $keep_original);
126  }
127 
128  public function newBlank() : StorableResource
129  {
130  $resource = $this->resource_repository->blank($this->primary_storage_handler->getIdentificationGenerator()->getUniqueResourceIdentification());
131  $resource->setStorageID($this->primary_storage_handler->getID());
132 
133  return $resource;
134  }
135 
136  //
137  // Methods to append something to an existing resource
138  //
139 
140  public function append(
141  StorableResource $resource,
142  UploadResult $result,
143  InfoResolver $info_resolver
144  ) : StorableResource {
145  $revision = $this->revision_repository->blankFromUpload($info_resolver, $resource, $result);
146  $revision = $this->populateRevisionInfo($revision, $info_resolver);
147 
148  $resource->addRevision($revision);
149  $resource->setStorageID($resource->getStorageID() === '' ? $this->primary_storage_handler->getID() : $resource->getStorageID());
150 
151  return $resource;
152  }
153 
157  public function replaceWithUpload(
158  StorableResource $resource,
159  UploadResult $result,
160  InfoResolver $info_resolver
161  ) : StorableResource {
162  $revision = $this->revision_repository->blankFromUpload($info_resolver, $resource, $result);
163  $revision = $this->populateRevisionInfo($revision, $info_resolver);
164 
165  foreach ($resource->getAllRevisions() as $existing_revision) {
166  $this->deleteRevision($resource, $existing_revision);
167  }
168 
169  $resource->addRevision($revision);
170  $resource->setStorageID($resource->getStorageID() === '' ? $this->primary_storage_handler->getID() : $resource->getStorageID());
171 
172  return $resource;
173  }
174 
175  public function appendFromStream(
176  StorableResource $resource,
177  FileStream $stream,
178  InfoResolver $info_resolver,
179  bool $keep_original = false
180  ) : StorableResource {
181  $revision = $this->revision_repository->blankFromStream($info_resolver, $resource, $stream, $keep_original);
182  $revision = $this->populateRevisionInfo($revision, $info_resolver);
183 
184  $resource->addRevision($revision);
185  $resource->setStorageID($resource->getStorageID() === '' ? $this->primary_storage_handler->getID() : $resource->getStorageID());
186 
187  return $resource;
188  }
189 
190  public function replaceWithStream(
191  StorableResource $resource,
192  FileStream $stream,
193  InfoResolver $info_resolver,
194  bool $keep_original = false
195  ) : StorableResource {
196  $revision = $this->revision_repository->blankFromStream($info_resolver, $resource, $stream, $keep_original);
197  $revision = $this->populateRevisionInfo($revision, $info_resolver);
198 
199  foreach ($resource->getAllRevisions() as $existing_revision) {
200  $this->deleteRevision($resource, $existing_revision);
201  }
202 
203  $resource->addRevision($revision);
204  $resource->setStorageID($resource->getStorageID() === '' ? $this->primary_storage_handler->getID() : $resource->getStorageID());
205 
206  return $resource;
207  }
208 
209  public function appendFromRevision(
210  StorableResource $resource,
211  int $revision_number
212  ) : StorableResource {
213  $existing_revision = $resource->getSpecificRevision($revision_number);
214  if ($existing_revision instanceof FileRevision) {
215  $info_resolver = new ClonedRevisionInfoResolver(
216  $resource->getMaxRevision() + 1,
217  $existing_revision
218  );
219 
220  $cloned_revision = $this->revision_repository->blankFromClone(
221  $info_resolver,
222  $resource,
223  $existing_revision
224  );
225 
226  $this->populateRevisionInfo($cloned_revision, $info_resolver);
227 
228  $resource->addRevision($cloned_revision);
229  $resource->setStorageID($resource->getStorageID() === '' ? $this->primary_storage_handler->getID() : $resource->getStorageID());
230  return $resource;
231  }
232  return $resource;
233 
234  }
235 
241  public function has(ResourceIdentification $identification) : bool
242  {
243  return $this->resource_repository->has($identification);
244  }
245 
251  public function store(StorableResource $resource) : void
252  {
253  foreach ($resource->getAllRevisions() as $revision) {
254  $this->file_name_policy->check($revision->getInformation()->getSuffix());
255  }
256 
257  $r = $this->lock_handler->lockTables(array_merge(
258  $this->resource_repository->getNamesForLocking(),
259  $this->revision_repository->getNamesForLocking(),
260  $this->information_repository->getNamesForLocking(),
261  $this->stakeholder_repository->getNamesForLocking(),
262 
263  ), function () use ($resource) {
264  $this->resource_repository->store($resource);
265 
266  foreach ($resource->getAllRevisions() as $revision) {
267  $this->storeRevision($revision);
268  }
269 
270  foreach ($resource->getStakeholders() as $stakeholder) {
271  $this->stakeholder_repository->register($resource->getIdentification(), $stakeholder);
272  }
273  });
274 
275  $r->runAndUnlock();
276  }
277 
283  public function clone(StorableResource $resource) : StorableResource
284  {
285  $new_resource = $this->newBlank();
286  foreach ($resource->getStakeholders() as $stakeholder) {
287  $stakeholder = clone $stakeholder;
288  $new_resource->addStakeholder($stakeholder);
289  }
290 
291  foreach ($resource->getAllRevisions() as $existing_revision) {
292  if (!$existing_revision instanceof FileRevision) {
293  continue;
294  }
295  $info_resolver = new ClonedRevisionInfoResolver(
296  $existing_revision->getVersionNumber(),
297  $existing_revision
298  );
299 
300  $stream = new FileStreamConsumer($resource, $this->storage_handler_factory->getHandlerForResource($resource));
301  $stream->setRevisionNumber($existing_revision->getVersionNumber());
302 
303  $cloned_revision = new FileStreamRevision($new_resource->getIdentification(), $stream->getStream(), true);
304  $this->populateRevisionInfo($cloned_revision, $info_resolver);
305  $cloned_revision->setVersionNumber($existing_revision->getVersionNumber());
306 
307  $new_resource->addRevision($cloned_revision);
308  }
309  $this->store($new_resource);
310  return $new_resource;
311 
312  }
313 
319  public function storeRevision(Revision $revision) : void
320  {
321  if ($revision instanceof UploadedFileRevision) {
322  // check policies
323  $this->file_name_policy->check($revision->getInformation()->getSuffix());
324  $this->primary_storage_handler->storeUpload($revision);
325  }
326  if ($revision instanceof FileStreamRevision) {
327  $this->primary_storage_handler->storeStream($revision);
328  }
329  if ($revision instanceof CloneRevision) {
330  $this->primary_storage_handler->cloneRevision($revision);
331  }
332  $this->revision_repository->store($revision);
333  $this->information_repository->store($revision->getInformation(), $revision);
334  }
335 
342  public function get(ResourceIdentification $identification) : StorableResource
343  {
344  if (isset($this->resource_cache[$identification->serialize()])) {
345  return $this->resource_cache[$identification->serialize()];
346  }
347  $resource = $this->resource_repository->get($identification);
348 
349  $this->resource_cache[$identification->serialize()] = $this->populateNakedResourceWithRevisionsAndStakeholders($resource);
350 
351  return $this->resource_cache[$identification->serialize()];
352  }
353 
360  public function remove(StorableResource $resource, ResourceStakeholder $stakeholder = null) : bool
361  {
362  $sucessful = true;
363  if ($stakeholder instanceof ResourceStakeholder) {
364  $this->stakeholder_repository->deregister($resource->getIdentification(), $stakeholder);
365  $sucessful = $sucessful && $stakeholder->resourceHasBeenDeleted($resource->getIdentification());
366  $resource->removeStakeholder($stakeholder);
367  if (count($resource->getStakeholders()) > 0) {
368  return $sucessful;
369  }
370  }
371  foreach ($resource->getStakeholders() as $s) {
372  $sucessful = $sucessful && $s->resourceHasBeenDeleted($resource->getIdentification());
373  }
374 
375  foreach ($resource->getAllRevisions() as $revision) {
376  $this->deleteRevision($resource, $revision);
377  }
378 
379  $this->storage_handler_factory->getHandlerForResource($resource)->deleteResource($resource);
380  $this->resource_repository->delete($resource);
381 
382  return $sucessful;
383  }
384 
385  public function removeRevision(StorableResource $resource, int $revision_number) : void
386  {
387  $reveision_to_delete = $resource->getSpecificRevision($revision_number);
388  if ($reveision_to_delete) {
389  $this->deleteRevision($resource, $reveision_to_delete);
390  }
391  $this->store($resource);
392  }
393 
394  private function deleteRevision(StorableResource $resource, Revision $revision) : void
395  {
396  try {
397  $this->storage_handler_factory->getHandlerForResource($resource)->deleteRevision($revision);
398  } catch (\Throwable $t) {
399  }
400 
401  $this->information_repository->delete($revision->getInformation(), $revision);
402  $this->revision_repository->delete($revision);
403  $resource->removeRevision($revision);
404  }
405 
409  public function getAll() : Generator
410  {
414  foreach ($this->resource_repository->getAll() as $resource) {
416  }
417  }
418 
424  {
425  $revisions = $this->revision_repository->get($resource);
426  $resource->setRevisions($revisions);
427 
428  foreach ($resource->getAllRevisions() as $revision) {
429  $information = $this->information_repository->get($revision);
430  $revision->setInformation($information);
431  }
432 
433  foreach ($this->stakeholder_repository->getStakeholders($resource->getIdentification()) as $s) {
434  $resource->addStakeholder($s);
435  }
436 
437  return $resource;
438  }
439 
440  private function populateRevisionInfo(Revision $revision, InfoResolver $info_resolver) : Revision
441  {
442  $info = $revision->getInformation();
443 
444  $info->setTitle($this->secure($info_resolver->getFileName()));
445  $info->setMimeType($info_resolver->getMimeType());
446  $info->setSuffix($this->secure($info_resolver->getSuffix()));
447  $info->setSize($info_resolver->getSize());
448  $info->setCreationDate($info_resolver->getCreationDate());
449 
450  $revision->setInformation($info);
451  $revision->setTitle($this->secure($info_resolver->getRevisionTitle()));
452  $revision->setOwnerId($info_resolver->getOwnerId());
453 
454  return $revision;
455  }
456 }
populateRevisionInfo(Revision $revision, InfoResolver $info_resolver)
appendFromStream(StorableResource $resource, FileStream $stream, InfoResolver $info_resolver, bool $keep_original=false)
newFromStream(FileStream $stream, InfoResolver $info_resolver, bool $keep_original=false)
removeRevision(StorableResource $resource, int $revision_number)
replaceWithUpload(StorableResource $resource, UploadResult $result, InfoResolver $info_resolver)
$result
append(StorableResource $resource, UploadResult $result, InfoResolver $info_resolver)
setRevisions(RevisionCollection $collection)
__construct(StorageHandlerFactory $storage_handler_factory, RevisionRepository $revision_repository, ResourceRepository $resource_repository, InformationRepository $information_repository, StakeholderRepository $stakeholder_repository, LockHandler $lock_handler, FileNamePolicy $file_name_policy=null)
ResourceBuilder constructor.
setInformation(Information $information)
deleteRevision(StorableResource $resource, Revision $revision)
populateNakedResourceWithRevisionsAndStakeholders(StorableResource $resource)
replaceWithStream(StorableResource $resource, FileStream $stream, InfoResolver $info_resolver, bool $keep_original=false)
storeRevision(Revision $revision)
Store one Revision
has(ResourceIdentification $identification)
appendFromRevision(StorableResource $resource, int $revision_number)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Interface FileStream The base interface for all filesystem streams.
Definition: FileStream.php:17