ILIAS  release_7 Revision v7.30-3-g800a261c036
ResourceBuilder.php
Go to the documentation of this file.
1<?php declare(strict_types=1);
2
4
5use Generator;
27use ILIAS\ResourceStorage\Preloader\SecureString;
28
35{
36 use SecureString;
64 protected $resource_cache = [];
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,
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,
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) {
415 yield $this->populateNakedResourceWithRevisionsAndStakeholders($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}
$result
An exception for terminatinating execution or to throw for unit testing.
append(StorableResource $resource, UploadResult $result, InfoResolver $info_resolver)
populateRevisionInfo(Revision $revision, InfoResolver $info_resolver)
appendFromStream(StorableResource $resource, FileStream $stream, InfoResolver $info_resolver, bool $keep_original=false)
appendFromRevision(StorableResource $resource, int $revision_number)
newFromStream(FileStream $stream, InfoResolver $info_resolver, bool $keep_original=false)
populateNakedResourceWithRevisionsAndStakeholders(StorableResource $resource)
replaceWithStream(StorableResource $resource, FileStream $stream, InfoResolver $info_resolver, bool $keep_original=false)
__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.
has(ResourceIdentification $identification)
deleteRevision(StorableResource $resource, Revision $revision)
replaceWithUpload(StorableResource $resource, UploadResult $result, InfoResolver $info_resolver)
@inheritDoc
removeRevision(StorableResource $resource, int $revision_number)
storeRevision(Revision $revision)
@description Store one Revision
Interface FileStream The base interface for all filesystem streams.
Definition: FileStream.php:18
setRevisions(RevisionCollection $collection)
setInformation(Information $information)