ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
ResourceBuilder.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
37use ILIAS\ResourceStorage\Preloader\SecureString;
51
58{
59 use SecureString;
60
77
81 protected array $resource_cache = [];
83 private bool $auto_migrate = true;
84
89 public function __construct(
90 private StorageHandlerFactory $storage_handler_factory,
91 Repositories $repositories,
92 private LockHandler $lock_handler,
93 private StreamAccess $stream_access,
94 protected FileNamePolicy $file_name_policy = new NoneFileNamePolicy()
95 ) {
96 $this->primary_storage_handler = $this->storage_handler_factory->getPrimary();
97 $this->revision_repository = $repositories->getRevisionRepository();
98 $this->resource_repository = $repositories->getResourceRepository();
99 $this->information_repository = $repositories->getInformationRepository();
100 $this->stakeholder_repository = $repositories->getStakeholderRepository();
101 }
102
103 //
104 // Methods to create new Resources (from an Upload, a Stream od just a blank one)
105 //
106
110 public function new(
111 UploadResult $result,
112 InfoResolver $info_resolver,
113 ResourceType $type = ResourceType::SINGLE_FILE
115 $resource = $this->resource_repository->blank(
116 $this->primary_storage_handler->getIdentificationGenerator()->getUniqueResourceIdentification(),
117 $type
118 );
119
120 return $this->append($resource, $result, $info_resolver, RevisionStatus::PUBLISHED);
121 }
122
123 public function newFromStream(
124 FileStream $stream,
125 InfoResolver $info_resolver,
126 bool $keep_original = false,
127 ResourceType $type = ResourceType::SINGLE_FILE
129 $resource = $this->resource_repository->blank(
130 $this->primary_storage_handler->getIdentificationGenerator()->getUniqueResourceIdentification(),
131 $type
132 );
133
134 return $this->appendFromStream(
135 $resource,
136 $stream,
137 $info_resolver,
138 RevisionStatus::PUBLISHED,
139 $keep_original
140 );
141 }
142
143 public function newBlank(ResourceType $type = ResourceType::SINGLE_FILE): StorableResource
144 {
145 $resource = $this->resource_repository->blank(
146 $this->primary_storage_handler->getIdentificationGenerator()->getUniqueResourceIdentification(),
147 $type
148 );
149 $resource->setStorageID($this->primary_storage_handler->getID());
150
151 return $resource;
152 }
153
154 //
155 // Methods to append something to an existing resource
156 //
157
158 public function append(
159 StorableResource $resource,
160 UploadResult $result,
161 InfoResolver $info_resolver,
162 RevisionStatus $status
164 if (
165 $status !== RevisionStatus::DRAFT
166 && $resource->getCurrentRevisionIncludingDraft()->getStatus() === RevisionStatus::DRAFT) {
167 throw new \LogicException(
168 'You can not replace a draft revision with a published, you must publish the current revision first'
169 );
170 }
171
172 $new_revision = $this->revision_repository->blankFromUpload($info_resolver, $resource, $result, $status);
173
174 if ($resource->getCurrentRevisionIncludingDraft()->getStatus() === RevisionStatus::DRAFT) {
175 $clone_revision = $this->buildDraftReplacementRevision($resource, $new_revision, $info_resolver);
176 $resource->replaceRevision($clone_revision);
177 } else {
178 $new_revision = $this->populateRevisionInfo($new_revision, $info_resolver);
179 $resource->addRevision($new_revision);
180 }
181
182 $resource->setStorageID(
183 $resource->getStorageID() === '' ? $this->primary_storage_handler->getID() : $resource->getStorageID()
184 );
185
186 return $resource;
187 }
188
192 public function replaceWithUpload(
193 StorableResource $resource,
194 UploadResult $result,
195 InfoResolver $info_resolver
197 if ($resource->getCurrentRevisionIncludingDraft()->getStatus() === RevisionStatus::DRAFT) {
198 throw new \LogicException('You can not replace a draft revision, you must publish it first');
199 }
200 $revision = $this->revision_repository->blankFromUpload(
201 $info_resolver,
202 $resource,
203 $result,
204 RevisionStatus::PUBLISHED
205 );
206 $revision = $this->populateRevisionInfo($revision, $info_resolver);
207
208 foreach ($resource->getAllRevisionsIncludingDraft() as $existing_revision) {
209 $this->deleteRevision($resource, $existing_revision);
210 }
211
212 $resource->addRevision($revision);
213 $resource->setStorageID(
214 $resource->getStorageID() === '' ? $this->primary_storage_handler->getID() : $resource->getStorageID()
215 );
216
217 return $resource;
218 }
219
220 public function appendFromStream(
221 StorableResource $resource,
222 FileStream $stream,
223 InfoResolver $info_resolver,
224 RevisionStatus $status,
225 bool $keep_original = false,
227 if (
228 $status !== RevisionStatus::DRAFT
229 && $resource->getCurrentRevisionIncludingDraft()->getStatus() === RevisionStatus::DRAFT) {
230 throw new \LogicException(
231 'You can not replace a draft revision with a published, you must publish the current revision first'
232 );
233 }
234
235 $new_revision = $this->revision_repository->blankFromStream(
236 $info_resolver,
237 $resource,
238 $stream,
239 $status,
240 $keep_original
241 );
242
243 if ($resource->getCurrentRevisionIncludingDraft()->getStatus() === RevisionStatus::DRAFT) {
244 $clone_revision = $this->buildDraftReplacementRevision($resource, $new_revision, $info_resolver);
245 $resource->replaceRevision($clone_revision);
246 } else {
247 $new_revision = $this->populateRevisionInfo($new_revision, $info_resolver);
248 $resource->addRevision($new_revision);
249 }
250
251 $resource->setStorageID(
252 $resource->getStorageID() === '' ? $this->primary_storage_handler->getID() : $resource->getStorageID()
253 );
254
255 return $resource;
256 }
257
258 public function replaceWithStream(
259 StorableResource $resource,
260 FileStream $stream,
261 InfoResolver $info_resolver,
262 bool $keep_original = false,
264 if ($resource->getCurrentRevisionIncludingDraft()->getStatus() === RevisionStatus::DRAFT) {
265 throw new \LogicException('You can not replace a draft revision, you must publish it first');
266 }
267 $revision = $this->revision_repository->blankFromStream(
268 $info_resolver,
269 $resource,
270 $stream,
271 RevisionStatus::PUBLISHED,
272 $keep_original
273 );
274 $revision = $this->populateRevisionInfo($revision, $info_resolver);
275
276 foreach ($resource->getAllRevisionsIncludingDraft() as $existing_revision) {
277 $this->deleteRevision($resource, $existing_revision);
278 }
279
280 $resource->addRevision($revision);
281 $resource->setStorageID(
282 $resource->getStorageID() === '' ? $this->primary_storage_handler->getID() : $resource->getStorageID()
283 );
284
285 return $resource;
286 }
287
288 public function appendFromRevision(
289 StorableResource $resource,
290 int $revision_number
292 if ($resource->getCurrentRevisionIncludingDraft()->getStatus() === RevisionStatus::DRAFT) {
293 throw new \LogicException('You can not replace a draft revision, you must publish it first');
294 }
295 $existing_revision = $resource->getSpecificRevision($revision_number);
296 if ($existing_revision instanceof FileRevision) {
297 $info_resolver = new ClonedRevisionInfoResolver(
298 $resource->getMaxRevision(false) + 1,
299 $existing_revision
300 );
301
302 $cloned_revision = $this->revision_repository->blankFromClone(
303 $info_resolver,
304 $resource,
305 $existing_revision
306 );
307
308 $this->populateRevisionInfo($cloned_revision, $info_resolver);
309
310 $resource->addRevision($cloned_revision);
311 $resource->setStorageID(
312 $resource->getStorageID() === '' ? $this->primary_storage_handler->getID() : $resource->getStorageID()
313 );
314 return $resource;
315 }
316 return $resource;
317 }
318
320 StorableResource $resource,
321 Revision $new_revision,
322 InfoResolver $info_resolver
323 ): Revision {
324 $current_revision = $resource->getCurrentRevisionIncludingDraft();
325 $stream_replacement = new StreamReplacementRevision(
326 $resource->getIdentification(),
327 $this->extractStream($new_revision)
328 );
329 $stream_replacement = $this->populateRevisionInfo($stream_replacement, $info_resolver);
330 $stream_replacement->setVersionNumber($current_revision->getVersionNumber());
331 $stream_replacement->setStatus(RevisionStatus::DRAFT);
332
333 return $stream_replacement;
334 }
335
339 public function has(ResourceIdentification $identification): bool
340 {
341 return $this->resource_repository->has($identification);
342 }
343
348 public function store(StorableResource $resource): void
349 {
350 foreach ($resource->getAllRevisionsIncludingDraft() as $revision) {
351 $this->file_name_policy->check($revision->getInformation()->getSuffix());
352 }
353
354 $r = $this->lock_handler->lockTables(
355 array_merge(
356 $this->resource_repository->getNamesForLocking(),
357 $this->revision_repository->getNamesForLocking(),
358 $this->information_repository->getNamesForLocking(),
359 $this->stakeholder_repository->getNamesForLocking()
360 ),
361 function () use ($resource): void {
362 $this->resource_repository->store($resource);
363
364 foreach ($resource->getAllRevisionsIncludingDraft() as $revision) {
365 $this->storeRevision($revision, $resource);
366 }
367
368 foreach ($resource->getStakeholders() as $stakeholder) {
369 $this->stakeholder_repository->register($resource->getIdentification(), $stakeholder);
370 }
371 }
372 );
373
374 $r->runAndUnlock();
375 }
376
380 public function clone(StorableResource $resource): StorableResource
381 {
382 $new_resource = $this->newBlank($resource->getType());
383 foreach ($resource->getStakeholders() as $stakeholder) {
384 $stakeholder = clone $stakeholder;
385 $new_resource->addStakeholder($stakeholder);
386 }
387
388 foreach ($resource->getAllRevisionsIncludingDraft() as $existing_revision) {
389 if (!$existing_revision instanceof FileRevision) {
390 continue;
391 }
392 $info_resolver = new ClonedRevisionInfoResolver(
393 $existing_revision->getVersionNumber(),
394 $existing_revision
395 );
396
397 $existing_revision = $this->stream_access->populateRevision($existing_revision);
398
399 $cloned_revision = new FileStreamRevision(
400 $new_resource->getIdentification(),
401 $existing_revision->maybeStreamResolver()->getStream(),
402 true
403 );
404
405 $this->populateRevisionInfo($cloned_revision, $info_resolver);
406 $cloned_revision->setVersionNumber($existing_revision->getVersionNumber());
407
408 $new_resource->addRevision($cloned_revision);
409 }
410 $this->store($new_resource);
411 return $new_resource;
412 }
413
418 public function storeRevision(Revision $revision, ?StorableResource $resource = null): void
419 {
420 $storage_handler = empty($revision->getStorageID())
421 ? $this->primary_storage_handler
422 : $this->storage_handler_factory->getHandlerForRevision($revision);
423
424 if ($revision instanceof UploadedFileRevision) {
425 // check policies
426 $this->file_name_policy->check($revision->getInformation()->getSuffix());
427 $storage_handler->storeUpload($revision);
428 }
429 if ($revision instanceof FileStreamRevision) {
430 $storage_handler->storeStream($revision);
431 }
432 if ($revision instanceof CloneRevision) {
433 $storage_handler->cloneRevision($revision);
434 }
435 if ($revision instanceof StreamReplacementRevision) {
436 $storage_handler->streamReplacement($revision);
437 }
438 $this->revision_repository->store($revision);
439 $this->information_repository->store($revision->getInformation(), $revision);
440
441 // we replace the revision with the populated one
442 if ($resource !== null) {
443 $replace_revision = new FileRevision($revision->getIdentification());
444 $replace_revision->setVersionNumber($revision->getVersionNumber());
445 $replace_revision->setOwnerId($revision->getOwnerId());
446 $replace_revision->setTitle($revision->getTitle());
447 $replace_revision->setStatus($revision->getStatus());
448 $replace_revision->setInformation($revision->getInformation());
449 $replace_revision->setStorageID($revision->getStorageID());
450
451 $resource->replaceRevision($replace_revision);
452 }
453 }
454
459 public function get(ResourceIdentification $identification): StorableResource
460 {
461 if (isset($this->resource_cache[$identification->serialize()])) {
462 return $this->resource_cache[$identification->serialize()];
463 }
464 $resource = $this->resource_repository->get($identification);
465
466 if ($this->auto_migrate && $resource->getStorageID() !== $this->primary_storage_handler->getID()) {
467 global $DIC;
470 $migrator->migrate($resource, $this->primary_storage_handler->getID());
471 $resource->setStorageID($this->primary_storage_handler->getID());
472 }
473
474 $this->resource_cache[$identification->serialize()] = $this->populateNakedResourceWithRevisionsAndStakeholders(
475 $resource
476 );
477
478 return $this->resource_cache[$identification->serialize()];
479 }
480
481 public function publish(StorableResource $resource): bool
482 {
483 $revision = $resource->getCurrentRevisionIncludingDraft();
484 if ($revision->getStatus() === RevisionStatus::PUBLISHED) {
485 return false;
486 }
487 $revision->setStatus(RevisionStatus::PUBLISHED);
488 $this->store($resource);
489 return true;
490 }
491
492 public function unpublish(StorableResource $resource): bool
493 {
494 $revision = $resource->getCurrentRevisionIncludingDraft();
495 if ($revision->getStatus() === RevisionStatus::DRAFT) {
496 return false;
497 }
498 $revision->setStatus(RevisionStatus::DRAFT);
499 $this->store($resource);
500 return true;
501 }
502
503 public function extractStream(Revision $revision): FileStream
504 {
505 switch (true) {
506 case $revision instanceof FileStreamRevision:
507 return Streams::ofReattachableResource($revision->getStream()->detach());
508 case $revision instanceof UploadedFileRevision:
509 return Streams::ofReattachableResource(fopen($revision->getUpload()->getPath(), 'rb'));
510 case $revision instanceof CloneRevision:
511 return $revision->getRevisionToClone()->getStream();
512 case $revision instanceof FileRevision:
513 if ($revision->getStorageID() !== '') {
514 return $this->storage_handler_factory->getHandlerForRevision(
515 $revision
516 )->getStream($revision);
517 }
518
519 return $this->storage_handler_factory->getHandlerForResource(
520 $this->get($revision->getIdentification())
521 )->getStream($revision);
522 default:
523 throw new \LogicException('This revision type is not supported');
524 }
525 }
526
532 public function remove(StorableResource $resource, ?ResourceStakeholder $stakeholder = null): bool
533 {
534 $sucessful = true;
535 if ($stakeholder instanceof ResourceStakeholder) {
536 $this->stakeholder_repository->deregister($resource->getIdentification(), $stakeholder);
537 $sucessful = $stakeholder->resourceHasBeenDeleted($resource->getIdentification());
538 $resource->removeStakeholder($stakeholder);
539 if ($resource->getStakeholders() !== []) {
540 return $sucessful;
541 }
542 }
543 foreach ($resource->getStakeholders() as $s) {
544 $sucessful = $s->resourceHasBeenDeleted($resource->getIdentification()) && $sucessful;
545 }
546
547 foreach ($resource->getAllRevisionsIncludingDraft() as $revision) {
548 $this->deleteRevision($resource, $revision);
549 }
550
551 $this->storage_handler_factory->getHandlerForResource($resource)->deleteResource($resource);
552 $this->resource_repository->delete($resource);
553
554 return $sucessful;
555 }
556
557 public function removeRevision(StorableResource $resource, int $revision_number): void
558 {
559 $reveision_to_delete = $resource->getSpecificRevision($revision_number);
560 if ($reveision_to_delete !== null) {
561 $this->deleteRevision($resource, $reveision_to_delete);
562 }
563 $this->store($resource);
564 }
565
566 // Container Actions
569 string $path_inside_container,
570 ): bool {
571 $revision = $container->getCurrentRevisionIncludingDraft();
572 $stream = $this->extractStream($revision);
573
574 // create directory inside ZipArchive
575 try {
576 $zip = new \ZipArchive();
577 $zip->open($stream->getMetadata()['uri']);
578 $path_inside_container = $this->ensurePathInZIP($zip, $path_inside_container, false);
579 $zip->close();
580
581 // cleanup revision and flavours
582 $this->storage_handler_factory->getHandlerForRevision($revision)->clearFlavours($revision);
583 $revision->getInformation()->setSize(filesize($stream->getMetadata()['uri']));
584 $this->storeRevision($revision);
585
586 return true;
587 } catch (\Throwable) {
588 return false;
589 }
590 }
591
592 private function ensurePathInZIP(\ZipArchive $zip, string $path, bool $is_file): string
593 {
594 if ($path === '' || $path === '/') {
595 return $path;
596 }
597
598 $filename = '';
599 if ($is_file) {
600 $filename = basename($path);
601 $path = dirname($path);
602 }
603
604 // try to determine if a path inside the zip exists with or without a slash at the beginning
605 // determine root directory of the path using regex
606 $parts = explode('/', $path);
607 $root = array_shift($parts);
608 $root = $root === '' ? array_shift($parts) : $root;
609
610 // check if the root directory exists without a slash at the beginning
611 if ($zip->locateName($root . '/') !== false) {
612 $root = $root;
613 } elseif ($zip->locateName('/' . $root . '/') !== false) {
614 // check if the root directory exists with a slash at the beginning
615 $root = '/' . $root;
616 } else {
617 // if the root directory does not exist, create it
618 $zip->addEmptyDir($root);
619 }
620
621 $path_inside_container = $root;
622 foreach ($parts as $part) {
623 $path_inside_container .= '/' . $part;
624 if ($zip->locateName($path_inside_container . '/') === false) {
625 $zip->addEmptyDir($path_inside_container . '/');
626 }
627 }
628
629 return rtrim((string) $path_inside_container, '/') . '/' . $filename;
630 }
631
634 string $path_inside_container,
635 ): bool {
636 $revision = $container->getCurrentRevisionIncludingDraft();
637 $stream = $this->extractStream($revision);
638
639 // create directory inside ZipArchive
640 try {
641 $zip = new \ZipArchive();
642 $zip->open($stream->getMetadata()['uri']);
643
644 $return = $zip->deleteName($path_inside_container);
645 // remove all files inside the directory
646 for ($i = 0; $i < $zip->numFiles; $i++) {
647 $path = $zip->getNameIndex($i);
648 if ($path === false) {
649 continue;
650 }
651 if (str_starts_with($path, $path_inside_container)) {
652 $zip->deleteIndex($i);
653 }
654 }
655
656 $zip->close();
657
658 // cleanup revision and flavours
659 $this->storage_handler_factory->getHandlerForRevision($revision)->clearFlavours($revision);
660 $revision->getInformation()->setSize(filesize($stream->getMetadata()['uri']));
661 $this->storeRevision($revision);
662
663 return $return;
664 } catch (\Throwable) {
665 $this->storage_handler_factory->getHandlerForRevision($revision)->clearFlavours($revision);
666 return false;
667 }
668 }
669
670 public function addUploadToContainer(
672 UploadResult $result,
673 string $parent_path_inside_container,
674 ): bool {
675 $revision = $container->getCurrentRevisionIncludingDraft();
676 $stream = $this->extractStream($revision);
677
678 // create directory inside ZipArchive
679 try {
680 $zip = new \ZipArchive();
681 $zip->open($stream->getMetadata()['uri']);
682
683 $parent_path_inside_container = $this->ensurePathInZIP($zip, $parent_path_inside_container, false);
684
685 $path_inside_zip = rtrim($parent_path_inside_container, '/') . '/' . $result->getName();
686
687 $return = $zip->addFile(
688 $result->getPath(),
689 $path_inside_zip
690 );
691 $zip->close();
692
693 // cleanup revision and flavours
694 $this->storage_handler_factory->getHandlerForRevision($revision)->clearFlavours($revision);
695 $revision->getInformation()->setSize(filesize($stream->getMetadata()['uri']));
696 $this->storeRevision($revision);
697
698 return $return;
699 } catch (\Throwable) {
700 return false;
701 }
702
703 return true;
704 }
705
706 public function addStreamToContainer(
708 FileStream $stream,
709 string $path_inside_container,
710 ): bool {
711 $revision = $container->getCurrentRevisionIncludingDraft();
712 $revision_stream = $this->extractStream($revision);
713
714 try {
715 $zip = new \ZipArchive();
716 $zip->open($revision_stream->getMetadata()['uri']);
717
718 $path_inside_container = $this->ensurePathInZIP($zip, $path_inside_container, true);
719
720 $return = $zip->addFromString(
721 $path_inside_container,
722 (string) $stream
723 );
724 $zip->close();
725
726 // cleanup revision and flavours
727 $this->storage_handler_factory->getHandlerForRevision($revision)->clearFlavours($revision);
728 $revision->getInformation()->setSize(filesize($revision_stream->getMetadata()['uri']));
729 $this->storeRevision($revision);
730
731 return $return;
732 } catch (\Throwable) {
733 return false;
734 }
735
736 return true;
737 }
738
739 private function deleteRevision(StorableResource $resource, Revision $revision): void
740 {
741 try {
742 $this->storage_handler_factory->getHandlerForResource($resource)->deleteRevision($revision);
743 } catch (\Throwable) {
744 }
745
746 $this->information_repository->delete($revision->getInformation(), $revision);
747 $this->revision_repository->delete($revision);
748 $resource->removeRevision($revision);
749 }
750
752 {
753 $revisions = $this->revision_repository->get($resource);
754 $resource->setRevisions($revisions);
755
756 foreach ($revisions->getAll(true) as $i => $revision) {
757 $information = $this->information_repository->get($revision);
758 $revision->setInformation($information);
759 $revision->setStorageID($resource->getStorageID());
760 // $revisions->replaceSingleRevision($this->stream_access->populateRevision($revision)); // currently we do not need populating the stream every time, we will do that in consumers only
761 }
762
763 foreach ($this->stakeholder_repository->getStakeholders($resource->getIdentification()) as $s) {
764 $resource->addStakeholder($s);
765 }
766
767 return $resource;
768 }
769
770 private function populateRevisionInfo(Revision $revision, InfoResolver $info_resolver): Revision
771 {
772 $info = $revision->getInformation();
773
774 $info->setTitle($this->secure($info_resolver->getFileName()));
775 $info->setMimeType($info_resolver->getMimeType());
776 $info->setSuffix($this->secure($info_resolver->getSuffix()));
777 $info->setSize($info_resolver->getSize());
778 $info->setCreationDate($info_resolver->getCreationDate());
779
780 $revision->setInformation($info);
781 $revision->setTitle($this->secure($info_resolver->getRevisionTitle()));
782 $revision->setOwnerId($info_resolver->getOwnerId());
783
784 return $revision;
785 }
786}
$filename
Definition: buildRTE.php:78
Stream factory which enables the user to create streams without the knowledge of the concrete class.
Definition: Streams.php:32
ensurePathInZIP(\ZipArchive $zip, string $path, bool $is_file)
StakeholderRepository $stakeholder_repository
@readonly
newFromStream(FileStream $stream, InfoResolver $info_resolver, bool $keep_original=false, ResourceType $type=ResourceType::SINGLE_FILE)
newBlank(ResourceType $type=ResourceType::SINGLE_FILE)
appendFromStream(StorableResource $resource, FileStream $stream, InfoResolver $info_resolver, RevisionStatus $status, bool $keep_original=false,)
addUploadToContainer(StorableContainerResource $container, UploadResult $result, string $parent_path_inside_container,)
replaceWithStream(StorableResource $resource, FileStream $stream, InfoResolver $info_resolver, bool $keep_original=false,)
populateRevisionInfo(Revision $revision, InfoResolver $info_resolver)
addStreamToContainer(StorableContainerResource $container, FileStream $stream, string $path_inside_container,)
ResourceRepository $resource_repository
@readonly
appendFromRevision(StorableResource $resource, int $revision_number)
populateNakedResourceWithRevisionsAndStakeholders(StorableResource $resource)
RevisionRepository $revision_repository
@readonly
storeRevision(Revision $revision, ?StorableResource $resource=null)
@description Store one Revision
__construct(private StorageHandlerFactory $storage_handler_factory, Repositories $repositories, private LockHandler $lock_handler, private StreamAccess $stream_access, protected FileNamePolicy $file_name_policy=new NoneFileNamePolicy())
ResourceBuilder constructor.
createDirectoryInsideContainer(StorableContainerResource $container, string $path_inside_container,)
store(StorableResource $resource)
@description after you have modified a resource, you can store it here
removePathInsideContainer(StorableContainerResource $container, string $path_inside_container,)
has(ResourceIdentification $identification)
@description check if a resource exists
deleteRevision(StorableResource $resource, Revision $revision)
replaceWithUpload(StorableResource $resource, UploadResult $result, InfoResolver $info_resolver)
@inheritDoc
removeRevision(StorableResource $resource, int $revision_number)
append(StorableResource $resource, UploadResult $result, InfoResolver $info_resolver, RevisionStatus $status)
buildDraftReplacementRevision(StorableResource $resource, Revision $new_revision, InfoResolver $info_resolver)
InformationRepository $information_repository
@readonly
clone(StorableResource $resource)
@description Clone anexisting resource with all it's revisions, stakeholders and information
$info
Definition: entry_point.php:21
The base interface for all filesystem streams.
Definition: FileStream.php:32
setRevisions(RevisionCollection $collection)
setInformation(Information $information)
$path
Definition: ltiservices.php:30
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:61
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26
$container
@noRector
Definition: wac.php:37