ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilObjFile.php
Go to the documentation of this file.
1 <?php
2 
27 
36 {
38  use ilObjFileUsages;
39  use ilObjFileNews;
41 
42  public const MODE_FILELIST = "filelist";
43  public const MODE_OBJECT = "object";
44  public const OBJECT_TYPE = "file";
45  public const CLICK_MODE_DOWNLOAD = 1;
46  public const CLICK_MODE_INFOPAGE = 2;
48 
50 
51  protected ?string $important_info = null;
52  protected int $page_count = 0;
53  protected bool $rating = false;
54  protected ?ilLogger $log;
55  protected string $filename = '';
56  protected string $filetype = '';
57  protected int $filesize;
58  protected int $version = 0;
59  protected int $max_version = 0;
60  protected ?string $copyright_id = null;
61  protected string $action = '';
62  protected ?string $resource_id = null;
63  public string $mode = self::MODE_OBJECT;
64  protected Manager $manager;
65  protected FileUpload $upload;
68  protected int $on_click_mode = self::CLICK_MODE_DOWNLOAD;
69  protected int $amount_of_downloads = 0;
70 
76  public function __construct(int $a_id = 0, bool $a_call_by_reference = true)
77  {
78  global $DIC;
79  $this->manager = $DIC->resourceStorage()->manage();
80  $this->database = $DIC->database();
81  $this->implementation = new ilObjFileImplementationEmpty();
82  $this->stakeholder = new ilObjFileStakeholder($DIC->user()->getId());
83  $this->upload = $DIC->upload();
84  $this->log = ilLoggerFactory::getLogger(self::OBJECT_TYPE);
85 
86  parent::__construct($a_id, $a_call_by_reference);
87  $this->initFileInfo($a_id, $a_call_by_reference);
88  }
89 
90  protected function initFileInfo(int $id, bool $is_ref_id): void
91  {
92  $repository = new ilObjFileInfoRepository();
93  $this->file_info = $is_ref_id ? $repository->getByRefId($id) : $repository->getByObjectId($id);
94  }
95 
96  #[\Override]
97  public function getPresentationTitle(): string
98  {
99  return $this->file_info->getHeaderTitle();
100  }
101 
102  protected function initImplementation(): void
103  {
104  if ($this->resource_id && ($id = $this->manager->find(
105  $this->resource_id
106  )) instanceof ResourceIdentification) {
107  $resource = $this->manager->getResource($id);
108  $this->implementation = new ilObjFileImplementationStorage($resource);
109  $this->max_version = $resource->getMaxRevision(false);
110  $this->version = $resource->getCurrentRevision()->getVersionNumber();
111  }
112  $this->initFileInfo($this->getId(), false);
113  }
114 
115  public function updateObjectFromCurrentRevision(): void
116  {
118  $this->manager->getCurrentRevision($this->manager->find($this->getResourceId()))
119  );
120  }
121 
122  private function updateObjectFromRevision(Revision $r): void
123  {
124  $this->initFileInfo($this->getId(), false);
125  $this->setTitle(
126  $this->ensureSuffix(
127  $r->getTitle(),
128  $this->extractSuffixFromFilename($r->getInformation()->getTitle())
129  )
130  );
131  $this->setFileName($r->getInformation()->getTitle());
132  $this->update();
133  }
134 
135  public function appendSuffixToTitle(string $title, string $filename): string
136  {
137  $suffix = $this->file_info->getSuffix();
138  $filename_suffix = $this->extractSuffixFromFilename($filename);
139  if (empty($suffix) || $suffix !== $filename_suffix) {
140  $suffix = $filename_suffix;
141  }
142 
143  return $this->ensureSuffix($title, $suffix);
144  }
145 
149  public function appendStream(FileStream $stream, string $title): int
150  {
151  $title = $this->ensureSuffix(
152  $title,
153  $this->extractSuffixFromFilename($title)
154  ?? pathinfo($stream->getMetadata('uri'))['extension']
155  ?? null
156  );
157  if ($this->getResourceId() && $i = $this->manager->find($this->getResourceId())) {
158  $revision = $this->manager->appendNewRevisionFromStream($i, $stream, $this->stakeholder, $title);
159  } else {
160  $i = $this->manager->stream($stream, $this->stakeholder, $title);
161  $revision = $this->manager->getCurrentRevision($i);
162  $this->setResourceId($i->serialize());
163  $this->initImplementation();
164  }
165  $this->enableNotification();
166  $this->updateObjectFromRevision($revision);
167 
168  return $revision->getVersionNumber();
169  }
170 
174  public function appendUpload(UploadResult $result, string $title): int
175  {
176  $title = $this->appendSuffixToTitle($title, $result->getName());
177  if ($this->getResourceId() && $i = $this->manager->find($this->getResourceId())) {
178  $revision = $this->manager->appendNewRevision($i, $result, $this->stakeholder, $title);
179  } else {
180  $i = $this->manager->upload($result, $this->stakeholder, $title);
181  $revision = $this->manager->getCurrentRevision($i);
182  $this->setResourceId($i->serialize());
183  $this->initImplementation();
184  }
187  }
188  $this->enableNotification();
189  $this->updateObjectFromRevision($revision);
190 
191  return $revision->getVersionNumber();
192  }
193 
197  public function replaceWithStream(FileStream $stream, string $title): int
198  {
199  if ($this->getResourceId() && $i = $this->manager->find($this->getResourceId())) {
200  $revision = $this->manager->replaceWithStream($i, $stream, $this->stakeholder, $title);
201  } else {
202  throw new LogicException('only files with existing resource and revision can be replaced');
203  }
204  $this->enableNotification();
205  $this->updateObjectFromRevision($revision);
206 
207  return $revision->getVersionNumber();
208  }
209 
213  public function replaceWithUpload(UploadResult $result, string $title): int
214  {
215  $title = $this->appendSuffixToTitle($title, $result->getName());
216  if ($this->getResourceId() && $i = $this->manager->find($this->getResourceId())) {
217  $revision = $this->manager->replaceWithUpload($i, $result, $this->stakeholder, $title);
218  } else {
219  throw new LogicException('only files with existing resource and revision can be replaced');
220  }
223  }
224  $this->enableNotification();
225  $this->updateObjectFromRevision($revision);
226 
227  return $revision->getVersionNumber();
228  }
229 
233  public function getFile(?int $a_hist_entry_id = null): string
234  {
235  $this->initImplementation();
236  return $this->implementation->getFile($a_hist_entry_id);
237  }
238 
239  public function getDirectory($a_version = 0): string
240  {
241  return $this->implementation->getDirectory($a_version);
242  }
243 
244  public function getDownloadFilename(): string
245  {
246  return $this->implementation->getDownloadFilename();
247  }
248 
249  public function getImportantInfo(): ?string
250  {
251  return $this->important_info;
252  }
253 
254  public function setImportantInfo(string $a_important_info): void
255  {
256  $this->important_info = empty($a_important_info) ? null : $a_important_info;
257  }
258 
259  public function getVersion(bool $inclduing_drafts = false): int
260  {
261  return $this->implementation->getVersion($inclduing_drafts);
262  }
263 
264  public function setVersion(int $a_version): void
265  {
266  $this->version = $a_version;
267  }
268 
269  public function getFileName(): string
270  {
271  return $this->implementation->getFileName();
272  }
273 
274  public function setFileName(string $a_name): void
275  {
276  $this->filename = $a_name;
277  }
278 
279  public function setRating(bool $a_value): void
280  {
281  $this->rating = $a_value;
282  }
283 
284  public function setResourceId(?string $resource_id): self
285  {
286  $this->resource_id = $resource_id;
287  return $this;
288  }
289 
290  public function getResourceId(): string
291  {
292  return $this->resource_id ?? '-';
293  }
294 
295  public function getStorageID(): ?string
296  {
297  return $this->implementation->getStorageID();
298  }
299 
300  public function getMode(): string
301  {
302  return $this->mode;
303  }
304 
308  public function setMode(string $a_mode): void
309  {
310  $this->mode = $a_mode;
311  }
312 
313  public function getFileSize(): int
314  {
315  return $this->implementation->getFileSize();
316  }
317 
321  public function setFileSize(int $a_size): void
322  {
323  throw new LogicException('cannot change filesize');
324  }
325 
326  public function getFileType(): string
327  {
328  return $this->implementation->getFileType();
329  }
330 
334  public function setFileType(string $a_type): void
335  {
336  throw new LogicException('cannot change filetype');
337  }
338 
339  public function hasRating(): bool
340  {
341  return $this->rating;
342  }
343 
344  public function getMaxVersion(): int
345  {
346  return $this->max_version;
347  }
348 
352  public function setMaxVersion(int $a_max_version): void
353  {
354  throw new LogicException('cannot change max-version');
355  }
356 
357  public function getCopyrightID(): ?string
358  {
359  return $this->copyright_id;
360  }
361 
362  public function setCopyrightID(?string $copyright_id): void
363  {
364  $this->copyright_id = $copyright_id;
365  }
366 
367  public function getPageCount(): int
368  {
369  return $this->page_count;
370  }
371 
372  public function setPageCount(int $page_count): void
373  {
374  $this->page_count = $page_count;
375  }
376 
380  public function getAction(): string
381  {
382  return $this->action;
383  }
384 
385  public function directDownload(): bool
386  {
387  return $this->on_click_mode === self::CLICK_MODE_DOWNLOAD;
388  }
389 
390  public function getOnClickMode(): int
391  {
392  return $this->on_click_mode;
393  }
394 
395  public function setOnclickMode(int $on_click_mode): void
396  {
397  $this->on_click_mode = $on_click_mode;
398  }
399 
400  public function getAmountOfDownloads(): int
401  {
403  }
404 
405  public function setAmountOfDownloads(int $amount): void
406  {
407  if (0 > $amount) {
408  throw new LogicException("Amount cannot be a negative number.");
409  }
410 
411  $this->amount_of_downloads = $amount;
412  }
413 
414  public function getLPMode(): int
415  {
416  return ilObjectLP::getInstance($this->getId())->getCurrentMode();
417  }
418 
424  public function setAction(string $a_action): void
425  {
426  throw new LogicException('cannot change action');
427  }
428 
429  public function handleChangedObjectTitle(string $new_title): void
430  {
431  $new_title = $this->ensureSuffix($new_title, $this->file_info->getSuffix());
432  $this->setTitle($new_title);
433  $this->implementation->handleChangedObjectTitle($new_title);
434  }
435 
436  protected function doCreate(bool $clone_mode = false): void
437  {
438  $this->createProperties(true);
439  $this->updateCopyright();
440  $this->getObjectProperties()->storePropertyIsOnline(new Online(true));
441  $this->notifyCreation($this->getId(), $this->getDescription());
442  }
443 
444  protected function doRead(): void
445  {
446  $q = "SELECT * FROM file_data WHERE file_id = %s";
447  $r = $this->database->queryF($q, ['integer'], [$this->getId()]);
448  $row = $r->fetchObject();
449 
450  $this->filename = $this->secure($row->file_name ?? '');
451  $this->filetype = $row->file_type ?? '';
452  $this->filesize = $row->file_size ?? 0;
453  $this->version = $row->version ?? 1;
454  $this->max_version = $row->max_version ?? 1;
455  $this->mode = $row->f_mode ?? self::MODE_OBJECT;
456  $this->important_info = $row->important_info ?? "";
457  $this->rating = (bool) ($row->rating ?? false);
458  $this->page_count = (int) ($row->page_count ?? 0);
459  $this->resource_id = $row->rid ?? null;
460  $this->on_click_mode = (int) ($row->on_click_mode ?? self::CLICK_MODE_DOWNLOAD);
461  $this->amount_of_downloads = (int) ($row->downloads ?? 0);
462 
463  $this->initImplementation();
464  }
465 
466  protected function doCloneObject(ilObject2 $new_obj, int $a_target_id, ?int $a_copy_id = 0): void
467  {
468  assert($new_obj instanceof ilObjFile);
469  $identification = $this->manager->find($this->resource_id);
470  if ($identification === null) {
471  throw new RuntimeException('Cannot clone file since no corresponding resource identification was found');
472  }
473 
474  $this->cloneMetaData($new_obj);
475  // object created now copy other settings
476  $new_obj->updateFileData();
477 
478  // Copy Resource
479  $cloned_title = $new_obj->getTitle();
480  $new_resource_identification = $this->manager->clone($identification);
481  $new_current_revision = $this->manager->getCurrentRevision($new_resource_identification);
482  $new_obj->setResourceId($new_resource_identification->serialize());
483  $new_obj->initImplementation();
484  $new_obj->updateObjectFromRevision($new_current_revision); // Previews are already copied in 453
485  $new_obj->setTitle($cloned_title); // see https://mantis.ilias.de/view.php?id=31375
486  $new_obj->setPageCount($this->getPageCount());
487  $new_obj->update();
488 
489  $new_obj->getObjectProperties()->storePropertyIsOnline(new Online(true));
490 
491  // Copy learning progress settings
492  $obj_settings = new ilLPObjSettings($this->getId());
493  $obj_settings->cloneSettings($new_obj->getId());
494  unset($obj_settings);
495  }
496 
497  protected function doUpdate(): void
498  {
499  $a_columns = $this->getArrayForDatabase();
500  $this->database->update('file_data', $a_columns, [
501  'file_id' => [
502  'integer',
503  $this->getId(),
504  ],
505  ]);
506 
507  $this->notifyUpdate($this->getId(), $this->getDescription());
508  $this->initImplementation();
509  }
510 
511  #[\Override]
512  protected function beforeUpdate(): bool
513  {
514  $suffix = $this->file_info->getSuffix();
515  if (empty($suffix)) {
516  $suffix = $this->extractSuffixFromFilename($this->getTitle());
517  }
518  $this->setTitle($this->ensureSuffix($this->getTitle(), $suffix));
519 
520  // no meta data handling for file list files
521  if ($this->getMode() !== self::MODE_FILELIST) {
522  $this->updateMetaData();
523  $this->updateCopyright();
524  }
525 
526  return true;
527  }
528 
529  #[\Override]
530  protected function beforeDelete(): bool
531  {
532  // check, if file is used somewhere
533  $usages = $this->getUsages();
534  return $usages === [];
535  }
536 
537  protected function doDelete(): void
538  {
539  // delete file data entry
540  $this->database->manipulateF("DELETE FROM file_data WHERE file_id = %s", ['integer'], [$this->getId()]);
541 
542  // delete history entries
544 
545  // delete meta data
546  if ($this->getMode() !== self::MODE_FILELIST) {
547  $this->deleteMetaData();
548  }
549 
550  // delete resource
551  $identification = $this->getResourceId();
552  if ($identification && $identification !== '-') {
553  $resource = $this->manager->find($identification);
554  if ($resource !== null) {
555  $this->manager->remove($resource, $this->stakeholder);
556  }
557  }
558  }
559 
563  private function getArrayForDatabase(): array
564  {
565  return [
566  'file_id' => ['integer', $this->getId()],
567  'file_name' => ['text', $this->getFileName()],
568  'f_mode' => ['text', $this->getMode()],
569  'important_info' => ['text', $this->getImportantInfo()],
570  'page_count' => ['text', $this->getPageCount()],
571  'rating' => ['integer', $this->hasRating()],
572  'rid' => ['text', $this->resource_id ?? ''],
573  'on_click_mode' => ['integer', $this->getOnClickMode()],
574  'downloads' => ['integer', $this->getAmountOfDownloads()],
575  ];
576  }
577 
578  protected function initType(): void
579  {
580  $this->type = self::OBJECT_TYPE;
581  }
582 
583  // Upload Handling
584 
588  public function replaceFile($a_upload_file, $a_filename): null
589  {
590  return null;
591  }
592 
593  private function prepareUpload(): void
594  {
595  if (!$this->upload->hasBeenProcessed()) {
596  if (defined('PATH_TO_GHOSTSCRIPT') && PATH_TO_GHOSTSCRIPT !== "") {
597  $this->upload->register(new ilCountPDFPagesPreProcessors());
598  }
599 
600  $this->upload->process();
601  }
602  }
603 
609  public function getUploadFile($a_upload_file, string $title, bool $a_prevent_preview = false): bool
610  {
611  $this->prepareUpload();
612 
613  $results = $this->upload->getResults();
614  $upload = $results[$a_upload_file];
615 
616  $this->appendUpload($upload, $title);
617 
618  return true;
619  }
620 
624  public function isHidden(): bool
625  {
626  return ilObjFileAccess::_isFileHidden($this->getTitle());
627  }
628 
633  public function clearDataDirectory(): void
634  {
635  $this->implementation->clearDataDirectory();
636  }
637 
642  public function deleteVersions($a_hist_entry_ids = null): void
643  {
644  $this->implementation->deleteVersions($a_hist_entry_ids);
645  // update file object as the deletion of versions might affect its attributes (title, max_version etc.)
646  if ($this->getResourceId() && $rid = $this->manager->find($this->getResourceId())) {
647  $latest_revision = $this->manager->getCurrentRevision($rid);
648  $this->updateObjectFromRevision($latest_revision);
649  }
650  }
651 
652  public function sendFile(?int $a_hist_entry_id = null, bool $inline = true): void
653  {
654  // increment file download count by one.
655  $this->setAmountOfDownloads($this->getAmountOfDownloads() + 1);
656  $this->update();
657  $info = (new ilObjFileInfoRepository())->getByObjectId($this->getId());
658  $this->implementation->sendFile($a_hist_entry_id, $info->shouldDeliverInline());
659  }
660 
664  public function export(string $a_target_dir): void
665  {
666  //
667  }
668 
673  public function getVersions($version_ids = null): array
674  {
675  return $this->implementation->getVersions($version_ids);
676  }
677 
682  public function rollback(int $version_id): void
683  {
684  if ($this->getResourceId() && $i = $this->manager->find($this->getResourceId())) {
685  $this->manager->rollbackRevision($i, $version_id);
686  $latest_revision = $this->manager->getCurrentRevision($i);
687  $this->updateObjectFromRevision($latest_revision);
688  } else {
689  throw new LogicException('only files with existing resource and revision can be replaced');
690  }
691  }
692 
696  public function checkFileExtension(string $new_filename, string $new_title): string
697  {
698  return $this->appendSuffixToTitle($new_title, $new_filename);
699  }
700 
701  public function getFileExtension(): string
702  {
703  return $this->implementation->getFileExtension();
704  }
705 
706  public function stripTitleOfFileExtension(string $a_title): string
707  {
708  return $this->secure(preg_replace('/\.[^.]*$/', '', $a_title));
709  }
710 }
string $title
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ilObjFileStakeholder.
Class ilObjFileImplementationStorage.
setFileName(string $a_name)
static getLogger(string $a_component_id)
Get component logger.
updateObjectFromRevision(Revision $r)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
cloneMetaData(ilObject $target_obj)
replaceWithUpload(UploadResult $result, string $title)
doCloneObject(ilObject2 $new_obj, int $a_target_id, ?int $a_copy_id=0)
ilLogger $log
trait ilObjFileMetadata
Trait ilObjFileMetadata.
appendSuffixToTitle(string $title, string $filename)
rollback(int $version_id)
Makes the specified version the current one.
static _isFileHidden(string $a_file_name)
Returns true, if a file with the specified name, is usually hidden from the user. ...
getDirectory($a_version=0)
string $action
const OBJECT_TYPE
setTitle(string $title)
updateObjectFromCurrentRevision()
setMode(string $a_mode)
appendUpload(UploadResult $result, string $title)
doCreate(bool $clone_mode=false)
ilObjFileImplementationInterface $implementation
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
replaceFile($a_upload_file, $a_filename)
setAction(string $a_action)
setFileSize(int $a_size)
string $copyright_id
initFileInfo(int $id, bool $is_ref_id)
static _removeEntriesForObject(int $a_obj_id)
remove all history entries for an object
getVersion(bool $inclduing_drafts=false)
appendStream(FileStream $stream, string $title)
stripTitleOfFileExtension(string $a_title)
ilObjFileStakeholder $stakeholder
const CLICK_MODE_DOWNLOAD
getUploadFile($a_upload_file, string $title, bool $a_prevent_preview=false)
This Method is used to append a fileupload by it&#39;s POST-name to the current ilObjFile ...
Class ilObjFile.
const MODE_FILELIST
global $DIC
Definition: shib_login.php:26
setPageCount(int $page_count)
string $resource_id
ilObjFileInfo $file_info
ilDBInterface $database
string $filetype
extractSuffixFromFilename(string $filename)
$results
Class FileUpload.
Definition: FileUpload.php:37
setVersion(int $a_version)
string $filename
setMaxVersion(int $a_max_version)
__construct(int $a_id=0, bool $a_call_by_reference=true)
ilObjFile constructor.
setOnclickMode(int $on_click_mode)
const MODE_OBJECT
deleteVersions($a_hist_entry_ids=null)
trait ilObjFileSecureString
Trait ilObjFileSecureString.
getFileExtension()
Returns the extension of the file name converted to lower-case.
setRating(bool $a_value)
enableNotification()
Manager $manager
notifyUpdate(int $obj_id, ?string $additional_message=null)
replaceWithStream(FileStream $stream, string $title)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
__construct(Container $dic, ilPlugin $plugin)
$q
Definition: shib_logout.php:23
setAmountOfDownloads(int $amount)
createProperties(bool $a_upload=false)
The basic properties of a file object are stored in table object_data.
sendFile(?int $a_hist_entry_id=null, bool $inline=true)
checkFileExtension(string $new_filename, string $new_title)
notifyCreation(int $obj_id, ?string $additional_message=null)
Class ilCountPDFPagesPreProcessors.
setFileType(string $a_type)
FileUpload $upload
setImportantInfo(string $a_important_info)
$info
Definition: entry_point.php:21
string $important_info
setResourceId(?string $resource_id)
handleChangedObjectTitle(string $new_title)
static getInstance(int $obj_id)
The base interface for all filesystem streams.
Definition: FileStream.php:31
getVersions($version_ids=null)
int $amount_of_downloads
export(string $a_target_dir)
ensureSuffix(string $title, ?string $suffix=null)
setCopyrightID(?string $copyright_id)
const CLICK_MODE_INFOPAGE
trait ilObjFileNews
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getFile(?int $a_hist_entry_id=null)
$r