ILIAS  release_8 Revision v8.24
class.ilFileVersionsGUI.php
Go to the documentation of this file.
1<?php
2
24
30{
31 public const KEY_FILE_RID = 'file_rid';
32 public const KEY_FILE_EXTRACT = 'file_extract';
33 public const KEY_FILE_STRUCTURE = 'file_structure';
34
35 public const CMD_DEFAULT = 'index';
36 public const CMD_DELETE_VERSIONS = "deleteVersions";
37 public const CMD_ROLLBACK_VERSION = "rollbackVersion";
38 public const CMD_DOWNLOAD_VERSION = "sendFile";
39 public const HIST_ID = 'hist_id';
40 public const CMD_CANCEL_DELETE = "cancelDeleteFile";
41 public const CMD_CONFIRMED_DELETE_FILE = "confirmDeleteFile";
42 public const CMD_CONFIRMED_DELETE_VERSIONS = 'confirmDeleteVersions';
43 public const CMD_ADD_NEW_VERSION = 'addNewVersion';
44 public const CMD_CREATE_NEW_VERSION = 'saveVersion';
45 public const CMD_ADD_REPLACING_VERSION = 'addReplacingVersion';
46 public const CMD_CREATE_REPLACING_VERSION = 'createReplacingVersion';
47 public const CMD_UNZIP_CURRENT_REVISION = 'unzipCurrentRevision';
48 public const CMD_PROCESS_UNZIP = 'processUnzip';
49
51 private \ILIAS\ResourceStorage\Services $storage;
52 private \ILIAS\DI\UIServices $ui;
54 private \ilWorkspaceAccessHandler $wsp_access;
55 private int $ref_id;
57 private Services $http;
59 private ilCtrl $ctrl;
61 private \ilObjFile $file;
63 protected ?int $version_id = null;
64 protected ilTree $tree;
65 protected int $parent_id;
66
70 public function __construct(ilObjFile $file)
71 {
72 global $DIC;
73 $this->file = $file;
74 $this->ctrl = $DIC->ctrl();
75 $this->tpl = $DIC->ui()->mainTemplate();
76 $this->tabs = $DIC->tabs();
77 $this->http = $DIC->http();
78 $this->lng = $DIC->language();
79 $this->ref_id = $this->http->wrapper()->query()->retrieve('ref_id', $DIC->refinery()->kindlyTo()->int());
80 $this->toolbar = $DIC->toolbar();
81 $this->access = $DIC->access();
82 $this->storage = $DIC->resourceStorage();
83 $this->file_service_settings = $DIC->fileServiceSettings();
84 $this->ui = $DIC->ui();
85 if ($this->isWorkspaceContext()) {
86 $this->tree = new ilWorkspaceTree($DIC->user()->getId());
87 } else {
88 $this->tree = $DIC->repositoryTree();
89 }
90
91 $this->parent_id = $this->tree->getParentId($this->file->getRefId()) ?? $this->getParentIdType();
92 $this->wsp_access = new ilWorkspaceAccessHandler($this->tree);
93 $this->version_id = $this->http->wrapper()->query()->has(self::HIST_ID)
94 ? $this->http->wrapper()->query()->retrieve(self::HIST_ID, $DIC->refinery()->kindlyTo()->int())
95 : null;
96 }
97
103 protected function performCommand(): void
104 {
105 $cmd = $this->ctrl->getCmd(self::CMD_DEFAULT);
106 switch ($cmd) {
108 $this->index();
109 break;
111 $this->downloadVersion();
112 break;
114 $this->deleteVersions();
115 break;
117 $this->rollbackVersion();
118 break;
121 break;
124 break;
127 // no break
130 break;
132 $this->confirmDeleteVersions();
133 break;
135 $this->confirmDeleteFile();
136 break;
138 $this->unzipCurrentRevision();
139 break;
141 $this->processUnzip();
142 break;
143 }
144 }
145
150 protected function setBackTab(): void
151 {
152 $this->tabs->clearTargets();
153 $this->tabs->setBackTarget(
154 $this->lng->txt('back'),
155 $this->ctrl->getLinkTarget($this, self::CMD_DEFAULT)
156 );
157 }
158
159 public function executeCommand(): void
160 {
161 // bugfix mantis 26007: use new function hasPermission to ensure that the check also works for workspace files
162 if (!$this->hasPermission('write')) {
163 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('permission_denied'), true);
164 $this->ctrl->returnToParent($this);
165 }
166 switch ($this->ctrl->getNextClass()) {
167 case strtolower(ilFileVersionsUploadHandlerGUI::class):
168 $this->ctrl->forwardCommand(
170 $this->file
171 )
172 );
173 return;
174 default:
175 $this->performCommand();
176 break;
177 }
178 }
179
180 private function unzipCurrentRevision(): void
181 {
182 $this->setBackTab();
183 $this->tpl->setContent(
184 $this->ui->renderer()->render(
185 $this->getFileZipOptionsForm()
186 )
187 );
188 }
189
190 private function processUnzip(): void
191 {
192 $form = $this->getFileZipOptionsForm()->withRequest($this->http->request());
193 $data = $form->getData();
194
195 if (!empty($data)) {
196 $file_rid = $this->storage->manage()->find($data[self::KEY_FILE_RID]);
197 if (null !== $file_rid) {
198 $processor = $this->getFileProcessor($data[self::KEY_FILE_STRUCTURE]);
199 $processor->process($file_rid);
200
201 if ($processor->getInvalidFileNames() !== []) {
202 $this->ui->mainTemplate()->setOnScreenMessage(
203 'info',
204 sprintf(
205 $this->lng->txt('file_upload_info_file_with_critical_extension'),
206 implode(', ', $processor->getInvalidFileNames())
207 ),
208 true
209 );
210 }
211
212 $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_unzip_success'), true);
213 $this->ctrl->setParameterByClass(ilRepositoryGUI::class, "ref_id", $this->parent_id);
214 $this->ctrl->redirectByClass(ilRepositoryGUI::class);
215 }
216
217 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('file_not_found'));
218 }
219
220 $this->tpl->setContent(
221 $this->ui->renderer()->render(
222 $this->getFileZipOptionsForm()
223 )
224 );
225 }
226
227 private function index(): void
228 {
229 // Buttons
230 $add_version = ilLinkButton::getInstance();
231 $add_version->setCaption('file_new_version');
232 $add_version->setUrl($this->ctrl->getLinkTarget($this, self::CMD_ADD_NEW_VERSION));
233 $this->toolbar->addButtonInstance($add_version);
234
235 $replace_version = ilLinkButton::getInstance();
236 $replace_version->setCaption('replace_file');
237 $replace_version->setUrl($this->ctrl->getLinkTarget($this, self::CMD_ADD_REPLACING_VERSION));
238 $this->toolbar->addButtonInstance($replace_version);
239
240 $current_file_revision = $this->getCurrentFileRevision();
241
242 // only add unzip button if the current revision is a zip.
243 if (null !== $current_file_revision &&
244 in_array($current_file_revision->getInformation()->getMimeType(), [MimeType::APPLICATION__ZIP, MimeType::APPLICATION__X_ZIP_COMPRESSED], true)
245 ) {
246 $unzip_button = ilLinkButton::getInstance();
247 $unzip_button->setCaption($this->lng->txt('unzip'), false);
248 $unzip_button->setUrl(
249 $this->ctrl->getLinkTargetByClass(
250 self::class,
251 self::CMD_UNZIP_CURRENT_REVISION
252 )
253 );
254
255 $this->toolbar->addButtonInstance($unzip_button);
256 }
257
258 $table = new ilFileVersionsTableGUI($this, self::CMD_DEFAULT);
259 $this->tpl->setContent($table->getHTML());
260 }
261
262 private function addVersion(int $mode = ilFileVersionFormGUI::MODE_ADD): void
263 {
264 $this->setBackTab();
265
266 $form = new ilFileVersionFormGUI($this, $mode);
267 $this->tpl->setContent($form->getHTML());
268 }
269
274 private function saveVersion(int $mode = ilFileVersionFormGUI::MODE_ADD): void
275 {
276 $form = new ilFileVersionFormGUI($this, $mode);
277 if ($form->saveObject()) {
278 $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_obj_modified'), true);
279 $this->ctrl->redirect($this, self::CMD_DEFAULT);
280 }
281 $this->tpl->setContent($form->getHTML());
282 }
283
284 private function downloadVersion(): void
285 {
286 try {
287 $this->file->sendFile($this->version_id);
288 } catch (FileNotFoundException $e) {
289 }
290 }
291
292 private function deleteVersions(): void
293 {
294 $version_ids = $this->getVersionIdsFromRequest();
295 $existing_versions = $this->file->getVersions();
296 $remaining_versions = array_udiff(
297 $existing_versions,
298 $version_ids,
299 static function ($a, $b) {
300 if ($a instanceof ilObjFileVersion) {
301 $a = $a->getHistEntryId();
302 }
303 if ($b instanceof ilObjFileVersion) {
304 $b = $b->getHistEntryId();
305 }
306 return $a - $b;
307 }
308 );
309
310 if (count($version_ids) < 1) {
311 $this->tpl->setOnScreenMessage('failure', $this->lng->txt("no_checkbox"), true);
312 $this->ctrl->redirect($this, self::CMD_DEFAULT);
313 } else {
314 $conf_gui = new ilConfirmationGUI();
315 $conf_gui->setFormAction($this->ctrl->getFormAction($this, self::CMD_DEFAULT));
316 $conf_gui->setCancel($this->lng->txt("cancel"), self::CMD_DEFAULT);
317
318 $icon = ilObject::_getIcon($this->file->getId(), "small", $this->file->getType());
319 $alt = $this->lng->txt("icon") . " " . $this->lng->txt("obj_" . $this->file->getType());
320
321 if (count($remaining_versions) < 1) {
322 // Ask
323 $conf_gui->setHeaderText($this->lng->txt('file_confirm_delete_all_versions'));
324 $conf_gui->setConfirm($this->lng->txt("confirm"), self::CMD_CONFIRMED_DELETE_FILE);
325 $conf_gui->addItem(
326 "id[]",
327 $this->ref_id,
328 $this->file->getTitle(),
329 $icon,
330 $alt
331 );
332 } else {
333 // Ask
334 $conf_gui->setHeaderText($this->lng->txt('file_confirm_delete_versions'));
335 $conf_gui->setConfirm($this->lng->txt("confirm"), self::CMD_CONFIRMED_DELETE_VERSIONS);
336
337 foreach ($this->file->getVersions($version_ids) as $version) {
338 $a_text = $version['filename'] ?? $version->getFilename() ?? $this->file->getTitle();
339 $version_string = $version['hist_id'] ?? $version->getVersion();
340 $a_text .= " (v" . $version_string . ")";
341 $conf_gui->addItem(
342 "hist_id[]",
343 $version['hist_entry_id'],
344 $a_text,
345 $icon,
346 $alt
347 );
348 }
349 }
350
351 $this->tpl->setContent($conf_gui->getHTML());
352 }
353 }
354
355 private function rollbackVersion(): void
356 {
357 $version_ids = $this->getVersionIdsFromRequest();
358
359 // more than one entry selected?
360 if (count($version_ids) != 1) {
361 $this->tpl->setOnScreenMessage('info', $this->lng->txt("file_rollback_select_exact_one"), true);
362 $this->ctrl->redirect($this, self::CMD_DEFAULT);
363 }
364
365 // rollback the version
366 $this->file->rollback($version_ids[0]);
367
368 $this->tpl->setOnScreenMessage('success', sprintf($this->lng->txt("file_rollback_done"), ''), true);
369 $this->ctrl->redirect($this, self::CMD_DEFAULT);
370 }
371
372 private function confirmDeleteVersions(): void
373 {
374 // delete versions after confirmation
375 $versions_to_delete = $this->getVersionIdsFromRequest();
376 if (is_array($versions_to_delete) && $versions_to_delete !== []) {
377 $this->file->deleteVersions($versions_to_delete);
378 $this->tpl->setOnScreenMessage('success', $this->lng->txt("file_versions_deleted"), true);
379 }
380
381 $this->ctrl->setParameter($this, self::HIST_ID, "");
382 $this->ctrl->redirect($this, self::CMD_DEFAULT);
383 }
384
385 private function confirmDeleteFile(): void
386 {
387 $parent_id = $this->tree->getParentId($this->ref_id);
388
389 ilRepUtil::deleteObjects($parent_id, [$this->ref_id]);
390
391 // redirect to parent object
392 $this->ctrl->setParameterByClass(ilRepositoryGUI::class, "ref_id", $parent_id);
393 $this->ctrl->redirectByClass(ilRepositoryGUI::class);
394 }
395
396 public function getFile(): ilObjFile
397 {
398 return $this->file;
399 }
400
401 private function getVersionIdsFromRequest(): array
402 {
403 // get ids either from GET (if single item was clicked) or
404 // from POST (if multiple items were selected)
405 $request = $this->http->request();
406
407 $version_ids = [];
408 if (isset($request->getQueryParams()[self::HIST_ID])) {
409 $version_ids = [$request->getQueryParams()[self::HIST_ID]];
410 } elseif (isset($request->getParsedBody()[self::HIST_ID])) {
411 $version_ids = (array) $request->getParsedBody()[self::HIST_ID];
412 }
413
414 array_walk($version_ids, static function (&$i): void {
415 $i = (int) $i;
416 });
417
418 return $version_ids;
419 }
420
425 private function getVersionsToKeep(array $version_ids): array
426 {
427 $versions_to_keep = $this->file->getVersions();
428 array_udiff($versions_to_keep, $version_ids, static function ($v1, $v2): bool {
429 if (is_array($v1) || $v1 instanceof ilObjFileVersion) {
430 $v1 = (int) $v1["hist_entry_id"];
431 } else {
432 if (!is_numeric($v1)) {
433 $v1 = (int) $v1;
434 }
435 }
436
437 if (is_array($v2) || $v2 instanceof ilObjFileVersion) {
438 $v2 = (int) $v2["hist_entry_id"];
439 } else {
440 if (!is_numeric($v2)) {
441 $v2 = (int) $v2;
442 }
443 }
444
445 return $v1 === $v2;
446 });
447
448 return $versions_to_keep;
449 }
450
456 private function hasPermission(string $a_permission): bool
457 {
458 // determine if the permission check concerns a workspace- or repository-object
459 if ($this->isWorkspaceContext()) {
460 // permission-check concerning a workspace object
461 if ($this->wsp_access->checkAccess($a_permission, "", $this->ref_id)) {
462 return true;
463 }
464 } else {
465 // permission-check concerning a repository object
466 if ($this->access->checkAccess($a_permission, '', $this->ref_id)) {
467 return true;
468 }
469 }
470
471 return false;
472 }
473
474 private function getFileZipOptionsForm(): Form
475 {
476 return $this->ui->factory()->input()->container()->form()->standard(
477 $this->ctrl->getFormActionByClass(self::class, self::CMD_PROCESS_UNZIP),
478 [
479 self::KEY_FILE_RID => $this->ui->factory()->input()->field()->hidden()->withValue($this->file->getResourceId()),
480 self::KEY_FILE_STRUCTURE => $this->ui->factory()->input()->field()->checkbox(
481 $this->lng->txt('take_over_structure'),
482 $this->lng->txt('take_over_structure_info'),
483 ),
484 ]
485 );
486 }
487
488 private function getFileProcessor(bool $keep_structure): ilObjFileProcessorInterface
489 {
490 $context = $this->getParentIdType();
491
492 if ($keep_structure) {
495 new ilObjFileGUI(
496 $this->file->getId(),
497 $context,
498 $this->parent_id
499 ),
500 $this->storage,
501 $this->file_service_settings,
502 $this->tree
503 );
504 }
505
508 new ilObjFileGUI(
509 $this->file->getId(),
510 $context,
511 $this->parent_id
512 ),
513 $this->storage,
514 $this->file_service_settings,
515 $this->tree
516 );
517 }
518
519 private function getCurrentFileRevision(): ?Revision
520 {
521 $file_rid = $this->storage->manage()->find($this->file->getResourceId());
522 if (null !== $file_rid) {
523 return $this->storage->manage()->getCurrentRevision($file_rid);
524 }
525
526 return null;
527 }
528
529 private function getParentIdType(): int
530 {
531 return ($this->isWorkspaceContext()) ?
534 }
535
536 private function isWorkspaceContext(): bool
537 {
538 return $this->http->wrapper()->query()->has('wsp_id');
539 }
540}
$version
Definition: plugin.php:24
Mime type determination.
Definition: MimeType.php:28
Class Services.
Definition: Services.php:38
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ilCtrl provides processing control methods.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ilFileVersionFormGUI.
Class ilFileVersionsGUI.
ILIAS ResourceStorage Services $storage
getFileProcessor(bool $keep_structure)
ilGlobalTemplateInterface $tpl
saveVersion(int $mode=ilFileVersionFormGUI::MODE_ADD)
getVersionsToKeep(array $version_ids)
addVersion(int $mode=ilFileVersionFormGUI::MODE_ADD)
hasPermission(string $a_permission)
bugfix mantis 26007: this function was created to ensure that the access check not only works for rep...
ilFileServicesSettings $file_service_settings
ilWorkspaceAccessHandler $wsp_access
ILIAS DI UIServices $ui
__construct(ilObjFile $file)
ilFileVersionsGUI constructor.
Class ilFileVersionsTableGUI.
Class ilFileVersionsUploadHandlerGUI.
language handling
GUI class for file objects.
Class ilObjFileStakeholder.
Class ilObjFileUnzipFlatProcessor.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ilObjFile.
static _getIcon(int $obj_id=0, string $size="big", string $type="", bool $offline=false)
Get icon for repository item.
static deleteObjects(int $a_cur_ref_id, array $a_ids, bool $throw_error_on_already_deleted=true)
Delete objects.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
global $DIC
Definition: feed.php:28
This describes commonalities between all forms.
Definition: Form.php:33
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$i
Definition: metadata.php:41
static http()
Fetches the global http state from ILIAS.
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
$context
Definition: webdav.php:29