From 3ec1bfaf8b8f83c89cbbcce744bd92b9c3e03dc7 Mon Sep 17 00:00:00 2001 From: Fabian Schmid Date: Fri, 25 Oct 2024 15:06:47 +0200 Subject: [PATCH] [FEATURE] WOPI View Actions for File Objects --- .../classes/Capabilities/Capabilities.php | 56 ++++++ .../File/classes/Capabilities/Capability.php | 70 +++++++ .../Capabilities/CapabilityBuilder.php | 107 +++++++++++ .../Capabilities/CapabilityCollection.php | 63 +++++++ .../classes/Capabilities/Check/BaseCheck.php | 64 +++++++ .../File/classes/Capabilities/Check/Check.php | 47 +++++ .../Capabilities/Check/CheckHelpers.php | 42 +++++ .../classes/Capabilities/Check/Download.php | 93 ++++++++++ .../File/classes/Capabilities/Check/Edit.php | 59 ++++++ .../Capabilities/Check/EditContent.php | 65 +++++++ .../File/classes/Capabilities/Check/Info.php | 62 +++++++ .../classes/Capabilities/Check/Manage.php | 59 ++++++ .../File/classes/Capabilities/Check/None.php | 50 +++++ .../File/classes/Capabilities/Check/Unzip.php | 64 +++++++ .../Capabilities/Check/ViewContent.php | 65 +++++++ .../File/classes/Capabilities/Permissions.php | 39 ++++ .../class.ilFileObjectRBACDatabase.php | 16 +- .../Versions/class.ilFileVersionsGUI.php | 14 +- .../classes/class.ilFileStaticURLHandler.php | 43 ++++- .../File/classes/class.ilObjFileAccess.php | 38 ++-- .../ILIAS/File/classes/class.ilObjFileGUI.php | 171 ++++++++++-------- .../File/classes/class.ilObjFileListGUI.php | 134 +++++++------- .../class.ilWOPIAdministrationGUI.php | 23 ++- 23 files changed, 1267 insertions(+), 177 deletions(-) create mode 100644 components/ILIAS/File/classes/Capabilities/Capabilities.php create mode 100644 components/ILIAS/File/classes/Capabilities/Capability.php create mode 100644 components/ILIAS/File/classes/Capabilities/CapabilityBuilder.php create mode 100644 components/ILIAS/File/classes/Capabilities/CapabilityCollection.php create mode 100644 components/ILIAS/File/classes/Capabilities/Check/BaseCheck.php create mode 100644 components/ILIAS/File/classes/Capabilities/Check/Check.php create mode 100644 components/ILIAS/File/classes/Capabilities/Check/CheckHelpers.php create mode 100644 components/ILIAS/File/classes/Capabilities/Check/Download.php create mode 100644 components/ILIAS/File/classes/Capabilities/Check/Edit.php create mode 100644 components/ILIAS/File/classes/Capabilities/Check/EditContent.php create mode 100644 components/ILIAS/File/classes/Capabilities/Check/Info.php create mode 100644 components/ILIAS/File/classes/Capabilities/Check/Manage.php create mode 100644 components/ILIAS/File/classes/Capabilities/Check/None.php create mode 100644 components/ILIAS/File/classes/Capabilities/Check/Unzip.php create mode 100644 components/ILIAS/File/classes/Capabilities/Check/ViewContent.php create mode 100644 components/ILIAS/File/classes/Capabilities/Permissions.php diff --git a/components/ILIAS/File/classes/Capabilities/Capabilities.php b/components/ILIAS/File/classes/Capabilities/Capabilities.php new file mode 100644 index 000000000000..d7c24e528072 --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Capabilities.php @@ -0,0 +1,56 @@ + + */ + +namespace ILIAS\File\Capabilities; + +enum Capabilities: string +{ + case EDIT_EXTERNAL = 'editExternal'; + case INFO_PAGE = 'showSummary'; + case MANAGE_VERSIONS = 'versions'; + case EDIT_SETTINGS = 'edit'; + case UNZIP = 'unzipCurrentRevision'; + case DOWNLOAD = 'sendfile'; + case VIEW_EXTERNAL = 'viewExternal'; + case NONE = 'none'; + + public static function fromName(string $name): Capabilities + { + foreach (self::cases() as $case) { + if ($name === $case->name) { + return $case; + } + } + return self::NONE; + } + + public static function fromCommand(string $cmd): Capabilities + { + foreach (self::cases() as $case) { + if ($cmd === $case->value) { + return $case; + } + } + return self::NONE; + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/Capability.php b/components/ILIAS/File/classes/Capabilities/Capability.php new file mode 100644 index 000000000000..add3631ee6af --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Capability.php @@ -0,0 +1,70 @@ + + */ + +namespace ILIAS\File\Capabilities; + +use ILIAS\Data\URI; + +class Capability +{ + private bool $unlocked = false; + private ?URI $uri = null; + + public function __construct( + private Capabilities $capability, + private Permissions $permission + ) { + } + + public function withUnlocked(bool $unlocked): Capability + { + $this->unlocked = $unlocked; + return $this; + } + + public function withURI(?URI $uri): Capability + { + $this->uri = $uri; + return $this; + } + + public function isUnlocked(): bool + { + return $this->unlocked; + } + + public function getUri(): ?URI + { + return $this->uri; + } + + public function getCapability(): Capabilities + { + return $this->capability; + } + + public function getPermission(): Permissions + { + return $this->permission; + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/CapabilityBuilder.php b/components/ILIAS/File/classes/Capabilities/CapabilityBuilder.php new file mode 100644 index 000000000000..6ba8b42dded5 --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/CapabilityBuilder.php @@ -0,0 +1,107 @@ + + */ +class CapabilityBuilder +{ + protected array $cache = []; + /** + * @var Check[] + */ + private array $checks = []; + + public function __construct( + private \ilObjFileInfoRepository $file_info_repository, + private \ilAccessHandler $access, + private \ilCtrlInterface $ctrl, + private ActionRepository $action_repository + ) { + $this->checks = [ + new Download(), + new Edit(), + new EditContent(), + new Info(), + new Manage(), + new None(), + new Unzip(), + new ViewContent(), + ]; + } + + public function get(int $ref_id, bool $do_checks = true): CapabilityCollection + { + if (isset($this->cache[$ref_id])) { + return $this->cache[$ref_id]; + } + + /** + * This is the order of priorities when + * using @see CapabilityCollection::getBest() + * which will return the first unlocked Capability + */ + $capabilities = [ + new Capability(Capabilities::VIEW_EXTERNAL, Permissions::VIEW_CONTENT), + new Capability(Capabilities::EDIT_EXTERNAL, Permissions::EDIT_FILE), + new Capability(Capabilities::DOWNLOAD, Permissions::READ), + new Capability(Capabilities::MANAGE_VERSIONS, Permissions::WRITE), + new Capability(Capabilities::EDIT_SETTINGS, Permissions::WRITE), + new Capability(Capabilities::INFO_PAGE, Permissions::VISIBLE), + new Capability(Capabilities::NONE, Permissions::NONE), + new Capability(Capabilities::UNZIP, Permissions::WRITE), + ]; + + + if (\ilObject2::_lookupType($ref_id, true) !== 'file') { + return new CapabilityCollection($capabilities); + } + + $info = $this->file_info_repository->getByRefId($ref_id); + $helpers = new CheckHelpers($this->access, $this->ctrl, $this->action_repository); + $this->ctrl->setParameterByClass(\ilObjFileGUI::class, 'ref_id', $ref_id); + + foreach ($capabilities as $capability) { + foreach ($this->checks as $check) { + if ($check->canUnlock() === $capability->getCapability()) { + $capability = $check->maybeUnlock($capability, $helpers, $info, $ref_id); + $capability = $check->maybeBuildURI($capability, $helpers, $ref_id); + } + } + } + return $this->cache[$ref_id] = new CapabilityCollection($capabilities); + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/CapabilityCollection.php b/components/ILIAS/File/classes/Capabilities/CapabilityCollection.php new file mode 100644 index 000000000000..826fc75c65d0 --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/CapabilityCollection.php @@ -0,0 +1,63 @@ + + */ +class CapabilityCollection +{ + /** + * @param Capability[] $capabilities + */ + public function __construct( + private array $capabilities + ) { + } + + public function all(): array + { + return $this->capabilities; + } + + public function get(Capabilities $capability): Capability|false + { + foreach ($this->capabilities as $cap) { + if ($cap->getCapability() === $capability) { + return $cap; + } + } + return false; + } + + public function getBest(): Capability + { + foreach ($this->capabilities as $cap) { + if ($cap->isUnlocked()) { + return $cap; + } + } + return new Capability(Capabilities::NONE, Permissions::NONE); + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/Check/BaseCheck.php b/components/ILIAS/File/classes/Capabilities/Check/BaseCheck.php new file mode 100644 index 000000000000..90d4c1860f72 --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Check/BaseCheck.php @@ -0,0 +1,64 @@ + + */ +abstract class BaseCheck implements Check +{ + public function __construct() + { + } + + protected function hasPermission( + CheckHelpers $helpers, + int $ref_id, + Permissions ...$permission + ): bool { + $permission_string = implode( + ',', + array_map(static fn(Permissions $permission) => $permission->value, $permission) + ); + + return $helpers->access->checkAccess($permission_string, '', $ref_id, 'file'); + } + + protected function hasWopiAction(CheckHelpers $helpers, string $suffix, ActionTarget ...$action): bool + { + return $helpers->action_repository->hasActionForSuffix($suffix, $action); + } + + public function hasWopiEditAction(CheckHelpers $helpers, string $suffix): bool + { + return $helpers->action_repository->hasEditActionForSuffix($suffix); + } + + public function hasWopiViewAction(CheckHelpers $helpers, string $suffix): bool + { + return $helpers->action_repository->hasViewActionForSuffix($suffix); + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/Check/Check.php b/components/ILIAS/File/classes/Capabilities/Check/Check.php new file mode 100644 index 000000000000..dc2f1832ab60 --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Check/Check.php @@ -0,0 +1,47 @@ + + */ + +namespace ILIAS\File\Capabilities\Check; + +use ILIAS\Data\URI; +use ILIAS\File\Capabilities\Capability; +use ILIAS\File\Capabilities\Capabilities; + +interface Check +{ + public function __construct(); + + public function canUnlock(): Capabilities; + + public function maybeUnlock( + Capability $capability, + CheckHelpers $helpers, + \ilObjFileInfo $info, + int $ref_id, + ): Capability; + + public function maybeBuildURI( + Capability $capability, + CheckHelpers $helpers, + int $ref_id, + ): Capability; +} diff --git a/components/ILIAS/File/classes/Capabilities/Check/CheckHelpers.php b/components/ILIAS/File/classes/Capabilities/Check/CheckHelpers.php new file mode 100644 index 000000000000..63fb9f802a03 --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Check/CheckHelpers.php @@ -0,0 +1,42 @@ + + */ + +namespace ILIAS\File\Capabilities\Check; + +use ILIAS\components\WOPI\Discovery\ActionRepository; +use ILIAS\Data\URI; + +class CheckHelpers +{ + public function __construct( + public \ilAccessHandler $access, + public \ilCtrlInterface $ctrl, + public ActionRepository $action_repository + ) { + } + + public function fromTarget(string $target): URI + { + return (new URI(rtrim(ILIAS_HTTP_PATH, '/') . '/' . $target)); + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/Check/Download.php b/components/ILIAS/File/classes/Capabilities/Check/Download.php new file mode 100644 index 000000000000..3e9680cf8a98 --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Check/Download.php @@ -0,0 +1,93 @@ + + */ +class Download extends BaseCheck implements Check +{ + private URIBuilder $static_url; + protected ?\ilObjFileInfo $info = null; + + public function __construct() + { + global $DIC; + $this->static_url = $DIC['static_url.uri_builder']; + parent::__construct(); + } + + public function canUnlock(): Capabilities + { + return Capabilities::DOWNLOAD; + } + + public function maybeUnlock( + Capability $capability, + CheckHelpers $helpers, + \ilObjFileInfo $info, + int $ref_id, + ): Capability { + $this->info = $info; + return $capability->withUnlocked($this->hasPermission($helpers, $ref_id, $capability->getPermission())); + } + + public function maybeBuildURI(Capability $capability, CheckHelpers $helpers, int $ref_id): Capability + { + if (!$capability->isUnlocked()) { + return $capability; + } + + if (!$this->info->shouldDownloadDirectly()) { + return $capability->withURI( + $helpers->fromTarget( + $helpers->ctrl->getLinkTargetByClass( + [\ilRepositoryGUI::class, \ilObjFileGUI::class, \ilInfoScreenGUI::class], + Capabilities::INFO_PAGE->value + ) + ) + ); + } + + return $capability->withURI( + $helpers->fromTarget( + $helpers->ctrl->getLinkTargetByClass( + [\ilRepositoryGUI::class, \ilObjFileGUI::class], + Capabilities::DOWNLOAD->value + ) + ) + ); + + return $capability->withURI( + $this->static_url->build( + 'file', + new ReferenceId($ref_id), + ['download'] + ) + ); + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/Check/Edit.php b/components/ILIAS/File/classes/Capabilities/Check/Edit.php new file mode 100644 index 000000000000..234cd398839d --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Check/Edit.php @@ -0,0 +1,59 @@ + + */ +class Edit extends BaseCheck implements Check +{ + public function canUnlock(): Capabilities + { + return Capabilities::EDIT_SETTINGS; + } + + public function maybeUnlock( + Capability $capability, + CheckHelpers $helpers, + \ilObjFileInfo $info, + int $ref_id, + ): Capability { + return $capability->withUnlocked($this->hasPermission($helpers, $ref_id, $capability->getPermission())); + } + + public function maybeBuildURI(Capability $capability, CheckHelpers $helpers, int $ref_id): Capability + { + if (!$capability->isUnlocked()) { + return $capability; + } + return $capability->withURI( + $helpers->fromTarget( + $helpers->ctrl->getLinkTargetByClass([\ilRepositoryGUI::class, \ilObjFileGUI::class], Capabilities::EDIT_SETTINGS->value) + ) + ); + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/Check/EditContent.php b/components/ILIAS/File/classes/Capabilities/Check/EditContent.php new file mode 100644 index 000000000000..bb65a7b8a0ef --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Check/EditContent.php @@ -0,0 +1,65 @@ + + */ +class EditContent extends BaseCheck implements Check +{ + public function canUnlock(): Capabilities + { + return Capabilities::EDIT_EXTERNAL; + } + + public function maybeUnlock( + Capability $capability, + CheckHelpers $helpers, + \ilObjFileInfo $info, + int $ref_id, + ): Capability { + if (!$this->hasPermission($helpers, $ref_id, $capability->getPermission())) { + return $capability->withUnlocked(false); + } + + return $capability->withUnlocked($this->hasWopiEditAction($helpers, $info->getSuffix())); + } + + public function maybeBuildURI(Capability $capability, CheckHelpers $helpers, int $ref_id): Capability + { + if (!$capability->isUnlocked()) { + return $capability; + } + return $capability->withURI( + $helpers->fromTarget( + $helpers->ctrl->getLinkTargetByClass( + [\ilRepositoryGUI::class, \ilObjFileGUI::class, \ilWOPIEmbeddedApplicationGUI::class], + \ilWOPIEmbeddedApplicationGUI::CMD_EDIT + ) + ) + ); + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/Check/Info.php b/components/ILIAS/File/classes/Capabilities/Check/Info.php new file mode 100644 index 000000000000..53b8d52cae2c --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Check/Info.php @@ -0,0 +1,62 @@ + + */ +class Info extends BaseCheck implements Check +{ + public function canUnlock(): Capabilities + { + return Capabilities::INFO_PAGE; + } + + public function maybeUnlock( + Capability $capability, + CheckHelpers $helpers, + \ilObjFileInfo $info, + int $ref_id, + ): Capability { + return $capability->withUnlocked($this->hasPermission($helpers, $ref_id, $capability->getPermission())); + } + + public function maybeBuildURI(Capability $capability, CheckHelpers $helpers, int $ref_id): Capability + { + if (!$capability->isUnlocked()) { + return $capability; + } + $helpers->ctrl->setParameterByClass(\ilObjFileInfoGUI::class, 'ref_id', $ref_id); + $helpers->ctrl->setParameterByClass(\ilInfoScreenGUI::class, 'ref_id', $ref_id); + + return $capability->withURI( + $helpers->fromTarget( + $helpers->ctrl->getLinkTargetByClass([\ilRepositoryGUI::class, \ilObjFileGUI::class, \ilInfoScreenGUI::class], Capabilities::INFO_PAGE->value) + ) + ); + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/Check/Manage.php b/components/ILIAS/File/classes/Capabilities/Check/Manage.php new file mode 100644 index 000000000000..e4ad2c815770 --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Check/Manage.php @@ -0,0 +1,59 @@ + + */ +class Manage extends BaseCheck implements Check +{ + public function canUnlock(): Capabilities + { + return Capabilities::MANAGE_VERSIONS; + } + + public function maybeUnlock( + Capability $capability, + CheckHelpers $helpers, + \ilObjFileInfo $info, + int $ref_id, + ): Capability { + return $capability->withUnlocked($this->hasPermission($helpers, $ref_id, $capability->getPermission())); + } + + public function maybeBuildURI(Capability $capability, CheckHelpers $helpers, int $ref_id): Capability + { + if (!$capability->isUnlocked()) { + return $capability; + } + return $capability->withURI( + $helpers->fromTarget( + $helpers->ctrl->getLinkTargetByClass([\ilRepositoryGUI::class, \ilObjFileGUI::class, \ilFileVersionsGUI::class]) + ) + ); + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/Check/None.php b/components/ILIAS/File/classes/Capabilities/Check/None.php new file mode 100644 index 000000000000..738f9d2fe3c1 --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Check/None.php @@ -0,0 +1,50 @@ + + */ +class None extends BaseCheck implements Check +{ + public function canUnlock(): Capabilities + { + return Capabilities::NONE; + } + + public function maybeUnlock( + Capability $capability, + CheckHelpers $helpers, + \ilObjFileInfo $info, + int $ref_id, + ): Capability { + return $capability->withUnlocked(true); + } + + public function maybeBuildURI(Capability $capability, CheckHelpers $helpers, int $ref_id): Capability + { + return $capability; + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/Check/Unzip.php b/components/ILIAS/File/classes/Capabilities/Check/Unzip.php new file mode 100644 index 000000000000..bc8cefb803d3 --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Check/Unzip.php @@ -0,0 +1,64 @@ + + */ +class Unzip extends BaseCheck implements Check +{ + public function canUnlock(): Capabilities + { + return Capabilities::UNZIP; + } + + public function maybeUnlock( + Capability $capability, + CheckHelpers $helpers, + \ilObjFileInfo $info, + int $ref_id, + ): Capability { + if (!$info->isZip()) { + return $capability; + } + + return $capability->withUnlocked($this->hasPermission($helpers, $ref_id, $capability->getPermission())); + } + + public function maybeBuildURI(Capability $capability, CheckHelpers $helpers, int $ref_id): Capability + { + if (!$capability->isUnlocked()) { + return $capability; + } + return $capability->withURI( + $helpers->fromTarget( + $helpers->ctrl->getLinkTargetByClass( + [\ilRepositoryGUI::class, \ilObjFileGUI::class, \ilFileVersionsGUI::class], + Capabilities::UNZIP->value + ) + ) + ); + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/Check/ViewContent.php b/components/ILIAS/File/classes/Capabilities/Check/ViewContent.php new file mode 100644 index 000000000000..aabb32544d10 --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Check/ViewContent.php @@ -0,0 +1,65 @@ + + */ +class ViewContent extends BaseCheck implements Check +{ + public function canUnlock(): Capabilities + { + return Capabilities::VIEW_EXTERNAL; + } + + public function maybeUnlock( + Capability $capability, + CheckHelpers $helpers, + \ilObjFileInfo $info, + int $ref_id, + ): Capability { + if (!$this->hasPermission($helpers, $ref_id, $capability->getPermission())) { + return $capability->withUnlocked(false); + } + + return $capability->withUnlocked($this->hasWopiViewAction($helpers, $info->getSuffix())); + } + + public function maybeBuildURI(Capability $capability, CheckHelpers $helpers, int $ref_id): Capability + { + if (!$capability->isUnlocked()) { + return $capability; + } + return $capability->withURI( + $helpers->fromTarget( + $helpers->ctrl->getLinkTargetByClass( + [\ilRepositoryGUI::class, \ilObjFileGUI::class, \ilWOPIEmbeddedApplicationGUI::class], + \ilWOPIEmbeddedApplicationGUI::CMD_VIEW + ) + ) + ); + } + +} diff --git a/components/ILIAS/File/classes/Capabilities/Permissions.php b/components/ILIAS/File/classes/Capabilities/Permissions.php new file mode 100644 index 000000000000..ba946f6a9231 --- /dev/null +++ b/components/ILIAS/File/classes/Capabilities/Permissions.php @@ -0,0 +1,39 @@ + + */ + +namespace ILIAS\File\Capabilities; + +enum Permissions: string +{ + case NONE = 'none'; + case VISIBLE = 'visible'; + case READ = 'read'; + case VIEW_CONTENT = 'view_content'; + case READ_LP = 'read_learning_progress'; + case EDIT_LP = 'edit_learning_progress'; + case EDIT_PERMISSIONS = 'edit_permission'; + case WRITE = 'write'; + case DELETE = 'delete'; + case COPY = 'copy'; + case EDIT_FILE = 'edit_file'; + +} diff --git a/components/ILIAS/File/classes/Setup/Database/class.ilFileObjectRBACDatabase.php b/components/ILIAS/File/classes/Setup/Database/class.ilFileObjectRBACDatabase.php index a3604cf82028..caa938b41929 100755 --- a/components/ILIAS/File/classes/Setup/Database/class.ilFileObjectRBACDatabase.php +++ b/components/ILIAS/File/classes/Setup/Database/class.ilFileObjectRBACDatabase.php @@ -25,6 +25,7 @@ use ILIAS\Setup; use ILIAS\Setup\Objective; use ILIAS\Setup\Environment; +use ILIAS\BookingManager\Setup\AccessRBACOperationClonedObjective; /** * @author Fabian Schmid @@ -42,7 +43,20 @@ public function getPreconditions(Environment $environment): array "object", 5990, ["file"] - ) + ), + new \ilAccessCustomRBACOperationAddedObjective( + "view_content", + "View Content in external Editor", + "object", + 5991, + ["file"] + ), + new AccessRBACOperationClonedObjective( + "file", + "read", + "view_content" + ), + ] ); } diff --git a/components/ILIAS/File/classes/Versions/class.ilFileVersionsGUI.php b/components/ILIAS/File/classes/Versions/class.ilFileVersionsGUI.php index ef9d9fb92ec5..1ef9c8fa6305 100755 --- a/components/ILIAS/File/classes/Versions/class.ilFileVersionsGUI.php +++ b/components/ILIAS/File/classes/Versions/class.ilFileVersionsGUI.php @@ -31,6 +31,7 @@ use ILIAS\components\WOPI\Discovery\ActionTarget; use ILIAS\FileUpload\MimeType; use ILIAS\MetaData\Services\ServicesInterface as LOMServices; +use ILIAS\File\Capabilities\Capabilities; /** * @author Fabian Schmid @@ -60,7 +61,7 @@ class ilFileVersionsGUI public const CMD_CREATE_NEW_VERSION = 'saveVersion'; public const CMD_ADD_REPLACING_VERSION = 'addReplacingVersion'; public const CMD_CREATE_REPLACING_VERSION = 'createReplacingVersion'; - public const CMD_UNZIP_CURRENT_REVISION = 'unzipCurrentRevision'; + public const CMD_UNZIP_CURRENT_REVISION = Capabilities::UNZIP->value; public const CMD_PROCESS_UNZIP = 'processUnzip'; public const CMD_RENDER_DELETE_SELECTED_VERSIONS_MODAL = 'renderDeleteSelectedVersionsModal'; public const CMD_PUBLISH = 'publish'; @@ -375,14 +376,14 @@ private function rollbackVersion(): void $this->ctrl->redirect($this, self::CMD_DEFAULT); } - if($this->current_revision->getStatus() === RevisionStatus::DRAFT) { + if ($this->current_revision->getStatus() === RevisionStatus::DRAFT) { $this->tpl->setOnScreenMessage('failure', $this->lng->txt("file_rollback_rollback_first"), true); $this->ctrl->redirect($this, self::CMD_DEFAULT); } // rollback the version $version_id = $version_ids[0]; - if($version_id === $this->current_revision->getVersionNumber()) { + if ($version_id === $this->current_revision->getVersionNumber()) { $this->tpl->setOnScreenMessage('info', $this->lng->txt("file_rollback_same_version"), true); $this->ctrl->redirect($this, self::CMD_DEFAULT); } @@ -558,7 +559,7 @@ protected function checkSanityOfDeletionRequest(array $requested_deletion_versio $this->current_revision->getStatus() === RevisionStatus::DRAFT ) { $this->tpl->setOnScreenMessage('failure', $this->lng->txt('publish_before_delete'), $redirect); - if($redirect) { + if ($redirect) { $this->ctrl->redirect($this, self::CMD_DEFAULT); } } @@ -566,7 +567,7 @@ protected function checkSanityOfDeletionRequest(array $requested_deletion_versio // no checkbox has been selected if (count($requested_deletion_version) < 1) { $this->tpl->setOnScreenMessage('failure', $this->lng->txt("no_checkbox"), $redirect); - if($redirect) { + if ($redirect) { $this->ctrl->redirect($this, self::CMD_DEFAULT); } } @@ -649,12 +650,10 @@ private function getFileZipOptionsForm(): Form $this->lng->txt('take_over_structure_info'), ); - // return form at this point if copyright selection is not enabled if (!$this->lom_services->copyrightHelper()->isCopyrightSelectionActive()) { return $this->ui->factory()->input()->container()->form()->standard($form_action, $inputs); } - // add the option for letting all unzipped files inherit the copyright of their parent zip (if a copyright has been set for the zip) $lom_reader = $this->lom_services->read($this->file->getId(), 0, $this->file->getType()); $lom_cp_helper = $this->lom_services->copyrightHelper(); @@ -679,7 +678,6 @@ private function getFileZipOptionsForm(): Form ); } - // add the option to collectively select the copyright for all unzipped files independent of the original copyright of the zip $copyright_selection_input = $this->getCopyrightSelectionInput('set_license_for_all_files'); $copyright_options[self::KEY_SELECT_COPYRIGHT] = $this->ui->factory()->input()->field()->group( [self::KEY_COPYRIGHT_ID => $copyright_selection_input], diff --git a/components/ILIAS/File/classes/class.ilFileStaticURLHandler.php b/components/ILIAS/File/classes/class.ilFileStaticURLHandler.php index 0946d39ff544..104e7a4580d7 100755 --- a/components/ILIAS/File/classes/class.ilFileStaticURLHandler.php +++ b/components/ILIAS/File/classes/class.ilFileStaticURLHandler.php @@ -23,6 +23,9 @@ use ILIAS\StaticURL\Response\Response; use ILIAS\StaticURL\Response\Factory; use ILIAS\StaticURL\Handler\BaseHandler; +use ILIAS\File\Capabilities\CapabilityBuilder; +use ILIAS\components\WOPI\Discovery\ActionDBRepository; +use ILIAS\File\Capabilities\Capabilities; /** * @author Fabian Schmid @@ -31,6 +34,21 @@ class ilFileStaticURLHandler extends BaseHandler implements Handler { public const DOWNLOAD = 'download'; public const VERSIONS = 'versions'; + public const EDIT = 'edit'; + public const VIEW = 'view'; + private CapabilityBuilder $capabilities; + + public function __construct() + { + global $DIC; + parent::__construct(); + $this->capabilities = new CapabilityBuilder( + new ilObjFileInfoRepository(), + $DIC->access(), + $DIC->ctrl(), + new ActionDBRepository($DIC->database()) + ); + } public function getNamespace(): string { @@ -47,18 +65,23 @@ public function handle(Request $request, Context $context, Factory $response_fac ilObjectGUI::_gotoSharedWorkspaceNode((int) $ref_id); } - $uri = match ($additional_params) { - self::DOWNLOAD => $context->ctrl()->getLinkTargetByClass( - [ilRepositoryGUI::class, ilObjFileGUI::class], - ilObjFileGUI::CMD_SEND_FILE - ), - self::VERSIONS => $context->ctrl()->getLinkTargetByClass( - [ilRepositoryGUI::class, ilObjFileGUI::class, ilFileVersionsGUI::class] - ), - default => $context->ctrl()->getLinkTargetByClass([ilRepositoryGUI::class, ilObjFileGUI::class]), + $capabilities = $this->capabilities->get($ref_id); + + $capability = match ($additional_params) { + self::DOWNLOAD => $capabilities->get(Capabilities::DOWNLOAD), + self::VERSIONS => $capabilities->get(Capabilities::MANAGE_VERSIONS), + self::EDIT => $capabilities->get(Capabilities::EDIT_EXTERNAL), + self::VIEW => $capabilities->get(Capabilities::VIEW_EXTERNAL), + default => $capabilities->get(Capabilities::INFO_PAGE), }; - return $response_factory->can($uri); + if (!$capability->isUnlocked() || $capability->getUri() === null) { + return $response_factory->cannot(); + } + + $uri = $capability->getUri(); + + return $response_factory->can($uri->getPath() . '?' . $uri->getQuery()); } } diff --git a/components/ILIAS/File/classes/class.ilObjFileAccess.php b/components/ILIAS/File/classes/class.ilObjFileAccess.php index e2300c535f2d..7516807e2c34 100755 --- a/components/ILIAS/File/classes/class.ilObjFileAccess.php +++ b/components/ILIAS/File/classes/class.ilObjFileAccess.php @@ -18,6 +18,10 @@ use ILIAS\FileUpload\MimeType; use ILIAS\components\File\Settings\General; +use ILIAS\File\Capabilities\Capabilities; +use ILIAS\File\Capabilities\CapabilityResolver; +use ILIAS\components\WOPI\Discovery\ActionDBRepository; +use ILIAS\File\Capabilities\Permissions; /** * Access class for file objects. @@ -73,29 +77,39 @@ public static function _getCommands(): array { return [ [ - "permission" => "read", - "cmd" => "sendfile", + "permission" => Permissions::READ->value, + "cmd" => Capabilities::DOWNLOAD->value, "lang_var" => "download", - "default" => true, + // "default" => true, // we decide the best matching capability later in ListGUI ], [ - "permission" => "write", - "cmd" => ilFileVersionsGUI::CMD_UNZIP_CURRENT_REVISION, + "permission" => Permissions::VISIBLE->value, + "cmd" => Capabilities::INFO_PAGE->value, + "lang_var" => "info", + ], + [ + "permission" => Permissions::WRITE->value, + "cmd" => Capabilities::UNZIP->value, "lang_var" => "unzip", ], [ - "permission" => "edit_file", - "cmd" => 'editExternal', + "permission" => Permissions::EDIT_FILE->value, + "cmd" => Capabilities::EDIT_EXTERNAL->value, "lang_var" => "open_external_editor", ], [ - "permission" => "write", - "cmd" => "versions", + "permission" => Permissions::VIEW_CONTENT->value, + "cmd" => Capabilities::VIEW_EXTERNAL->value, + "lang_var" => "open_external_viewer", + ], + [ + "permission" => Permissions::WRITE->value, + "cmd" => Capabilities::MANAGE_VERSIONS->value, "lang_var" => "versions", ], [ - "permission" => "write", - "cmd" => "edit", + "permission" => Permissions::WRITE->value, + "cmd" => Capabilities::EDIT_SETTINGS->value, "lang_var" => "settings" ] ]; @@ -127,7 +141,7 @@ public function _checkAccess(string $cmd, string $permission, int $ref_id, int $ } break; // for permission query feature - case "infoScreen": + case Capabilities::INFO_PAGE->value: if (!self::_lookupOnline($obj_id)) { $ilAccess->addInfoItem(ilAccessInfo::IL_NO_OBJECT_ACCESS, $lng->txt("offline")); } else { diff --git a/components/ILIAS/File/classes/class.ilObjFileGUI.php b/components/ILIAS/File/classes/class.ilObjFileGUI.php index 2da90f00d924..97f4de41fc36 100755 --- a/components/ILIAS/File/classes/class.ilObjFileGUI.php +++ b/components/ILIAS/File/classes/class.ilObjFileGUI.php @@ -32,6 +32,13 @@ use ILIAS\Data\URI; use ILIAS\components\WOPI\Discovery\ActionTarget; use ILIAS\MetaData\Services\ServicesInterface as LOMServices; +use ILIAS\File\Capabilities\Capabilities; +use ILIAS\File\Capabilities\ViewContentCapability; +use ILIAS\File\Capabilities\EditContentCapability; +use ILIAS\File\Capabilities\CapabilityBuilder; +use ILIAS\File\Capabilities\CapabilityCollection; +use ILIAS\File\Capabilities\Capability; +use ILIAS\File\Capabilities\Permissions; /** * GUI class for file objects. @@ -59,11 +66,12 @@ class ilObjFileGUI extends ilObject2GUI public const UPLOAD_ORIGIN_STANDARD = 'standard'; public const UPLOAD_ORIGIN_DROPZONE = 'dropzone'; - public const CMD_EDIT = "edit"; - public const CMD_VERSIONS = "versions"; + public const CMD_EDIT = Capabilities::EDIT_SETTINGS->value; + public const CMD_VERSIONS = Capabilities::MANAGE_VERSIONS->value; public const CMD_UPLOAD_FILES = "uploadFiles"; - public const CMD_SEND_FILE = "sendFile"; + public const CMD_SEND_FILE = Capabilities::DOWNLOAD->value; + private \ILIAS\File\Capabilities\CapabilityCollection $capabilities; /** * @var \ilObjFile|null $object @@ -118,6 +126,14 @@ public function __construct(int $a_id = 0, int $a_id_type = self::REPOSITORY_NOD $this->data_factory = new Factory(); $this->action_repo = new ActionDBRepository($DIC->database()); $this->lom_services = $DIC->learningObjectMetadata(); + + $capability_builder = new CapabilityBuilder( + new ilObjFileInfoRepository(), + $this->access, + $this->ctrl, + $this->action_repo + ); + $this->capabilities = $capability_builder->get($a_id); } public function getType(): string @@ -142,15 +158,16 @@ public function executeCommand(): void $next_class = $this->ctrl->getNextClass($this); $cmd = $this->ctrl->getCmd(); - if (!$this->getCreationMode() && ($this->id_type == self::REPOSITORY_NODE_ID - && $this->checkPermissionBool("read"))) { - $ilCtrl->setParameterByClass("ilrepositorygui", "ref_id", $this->node_id); - $link = $ilCtrl->getLinkTargetByClass("ilrepositorygui", "infoScreen"); - $ilCtrl->setParameterByClass("ilrepositorygui", "ref_id", $this->ref_id); + if ( + !$this->getCreationMode() + && ( + $this->id_type == self::REPOSITORY_NODE_ID + && $this->capabilities->get(Capabilities::DOWNLOAD)->isUnlocked() + )) { // add entry to navigation history $ilNavigationHistory->addItem( $this->node_id, - $link, + (string) $this->capabilities->get(Capabilities::INFO_PAGE)->getUri(), ilObjFile::OBJECT_TYPE ); } @@ -164,12 +181,12 @@ public function executeCommand(): void $this->tpl->setTitleIcon($path_file_icon); switch ($next_class) { - case "ilinfoscreengui": + case strtolower(ilInfoScreenGUI::class): $this->infoScreenForward(); // forwards command break; case 'ilobjectmetadatagui': - if (!$this->checkPermissionBool("write")) { + if (!$this->capabilities->get(Capabilities::EDIT_SETTINGS)->isUnlocked()) { $ilErr->raiseError($this->lng->txt('permission_denied'), $ilErr->WARNING); } @@ -231,7 +248,7 @@ public function executeCommand(): void case strtolower(ilFileVersionsGUI::class): $this->tabs_gui->activateTab("id_versions"); - if (!$this->checkPermissionBool("write")) { + if (!$this->capabilities->get(Capabilities::MANAGE_VERSIONS)->isUnlocked()) { $this->error->raiseError($this->lng->txt("permission_denied"), $this->error->MESSAGE); } /** @var ilObjFile $obj */ @@ -242,26 +259,33 @@ public function executeCommand(): void $this->ctrl->forwardCommand(new ilObjFileUploadHandlerGUI()); break; case strtolower(ilWOPIEmbeddedApplicationGUI::class): - if (!$this->checkPermissionBool("edit_file")) { + $capability = match($cmd) { + ilWOPIEmbeddedApplicationGUI::CMD_VIEW => $this->capabilities->get(Capabilities::VIEW_EXTERNAL), + ilWOPIEmbeddedApplicationGUI::CMD_EDIT => $this->capabilities->get(Capabilities::EDIT_EXTERNAL), + ilWOPIEmbeddedApplicationGUI::CMD_RETURN => $this->capabilities->get(Capabilities::INFO_PAGE), + default => null + }; + + if ($capability === null || !$capability->isUnlocked()) { $this->error->raiseError($this->lng->txt("permission_denied"), $this->error->MESSAGE); return; } - $action = $this->action_repo->getEditActionForSuffix( - $this->object->getFileExtension() - ); - if (null === $action) { - $this->error->raiseError($this->lng->txt("no_action_avaliable"), $this->error->MESSAGE); - return; - } + $action = match ($capability->getCapability()) { + Capabilities::VIEW_EXTERNAL => $this->action_repo->getViewActionForSuffix($suffix), + Capabilities::EDIT_EXTERNAL => $this->action_repo->getEditActionForSuffix($suffix), + default => null + }; + + $this->tabs_gui->activateTab('content'); $embeded_application = new EmbeddedApplication( $this->storage->manage()->find($this->object->getResourceId()), $action, $this->stakeholder, - new URI(ilLink::_getLink($this->object->getRefId())) + new URI(ilLink::_getLink($this->object->getRefId())), + $capability->getCapability() === Capabilities::VIEW_EXTERNAL ); - $this->ctrl->forwardCommand( new ilWOPIEmbeddedApplicationGUI( $embeded_application @@ -287,11 +311,6 @@ public function executeCommand(): void // in personal workspace use object2gui if ($this->id_type === self::WORKSPACE_NODE_ID) { $this->addHeaderAction(); - - // coming from goto we need default command - if (empty($cmd)) { - $ilCtrl->setCmd("infoScreen"); - } $ilTabs->clearTargets(); parent::executeCommand(); @@ -299,7 +318,7 @@ public function executeCommand(): void } if (empty($cmd) || $cmd === 'render') { - $cmd = "infoScreen"; + $cmd = Capabilities::INFO_PAGE->value; } $this->$cmd(); @@ -309,14 +328,6 @@ public function executeCommand(): void $this->addHeaderAction(); } - /** - * This Method is needed if called from personal resources - * @see executeCommand() line 162 - */ - protected function render(): void - { - $this->infoScreen(); - } protected function addUIFormToAccordion( ilAccordionGUI $accordion, @@ -411,7 +422,6 @@ public function initUploadForm(): Standard self::UPLOAD_MAX_FILES )->withRequired(true); - // add input for copyright selection if enabled in the metadata settings if ($this->lom_services->copyrightHelper()->isCopyrightSelectionActive()) { $inputs[self::PARAM_COPYRIGHT_ID] = $this->getCopyrightSelectionInput('set_license_for_all_files'); } @@ -575,7 +585,7 @@ public function edit(): void global $DIC; $ilErr = $DIC['ilErr']; - if (!$this->checkPermissionBool("write")) { + if (!$this->capabilities->get(Capabilities::EDIT_SETTINGS)->isUnlocked()) { $ilErr->raiseError($this->lng->txt("msg_no_perm_write")); } @@ -628,7 +638,6 @@ protected function initPropertiesForm(): \ILIAS\UI\Component\Input\Container\For $this->lng->txt('file_info') ); - $online_status = $this->object->getObjectProperties()->getPropertyIsOnline()->toForm( $this->lng, $this->ui->factory()->input()->field(), @@ -668,7 +677,6 @@ protected function initPropertiesForm(): \ILIAS\UI\Component\Input\Container\For ); } - $inputs = array_filter([ "file_info" => $file_info_section, "availability" => $availability_section, @@ -692,7 +700,7 @@ public function sendFile(): bool $this->object->sendFile($hist_entry_id); } - if ($this->checkPermissionBool("read")) { + if ($this->capabilities->get(Capabilities::DOWNLOAD)->isUnlocked()) { // Record read event and catchup with write events ilChangeEvent::_recordReadEvent( $this->object->getType(), @@ -722,34 +730,40 @@ public function sendFile(): bool } /** - * @deprecated + * @deprecated PROXY COMMAND */ + public function showSummary(): void + { + $this->ctrl->redirectToURL( + (string) $this->capabilities->get(Capabilities::INFO_PAGE)->getUri() + ); + } + public function versions(): void { - $this->ctrl->redirectByClass(ilFileVersionsGUI::class); + $this->ctrl->redirectToURL( + (string) $this->capabilities->get(Capabilities::MANAGE_VERSIONS)->getUri() + ); } public function unzipCurrentRevision(): void { - $this->ctrl->redirectByClass(ilFileVersionsGUI::class, ilFileVersionsGUI::CMD_UNZIP_CURRENT_REVISION); + $this->ctrl->redirectToURL( + (string) $this->capabilities->get(Capabilities::UNZIP)->getUri() + ); } protected function editExternal(): void { - $this->ctrl->redirectByClass(ilWOPIEmbeddedApplicationGUI::class, ilWOPIEmbeddedApplicationGUI::CMD_EDIT); + $this->ctrl->redirectToURL( + (string) $this->capabilities->get(Capabilities::EDIT_EXTERNAL)->getUri() + ); } - - /** - * this one is called from the info button in the repository - * not very nice to set cmdClass/Cmd manually, if everything - * works through ilCtrl in the future this may be changed - */ - public function infoScreen(): void + protected function viewExternal(): void { - // @todo: removed deprecated ilCtrl methods, this needs inspection by a maintainer. - // $this->ctrl->setCmd("showSummary"); - // $this->ctrl->setCmdClass("ilinfoscreengui"); - $this->infoScreenForward(); + $this->ctrl->redirectToURL( + (string) $this->capabilities->get(Capabilities::VIEW_EXTERNAL)->getUri() + ); } /** @@ -759,8 +773,11 @@ public function infoScreenForward(): void { $this->tabs_gui->activateTab("id_info"); - if (!$this->checkPermissionBool("visible") && !$this->checkPermissionBool("read")) { - $GLOBALS['DIC']['ilErr']->raiseError($this->lng->txt("msg_no_perm_read"), 2); // TODO remove magic number and old ilErr call + if (!$this->capabilities->get(Capabilities::INFO_PAGE)->isUnlocked()) { + $GLOBALS['DIC']['ilErr']->raiseError( + $this->lng->txt("msg_no_perm_read"), + 2 + ); // TODO remove magic number and old ilErr call } // add set completed button, if LP mode is active @@ -779,12 +796,7 @@ public function infoScreenForward(): void } // Add WOPI editor Button - if ( - $this->checkPermissionBool("edit_file") - && $this->action_repo->hasActionForSuffix( - $this->object->getFileExtension(), - ActionTarget::EDIT - )) { + if ($this->capabilities->get(Capabilities::EDIT_EXTERNAL)->isUnlocked()) { $external_editor = $this->ui->factory() ->button() ->standard( @@ -797,7 +809,6 @@ public function infoScreenForward(): void $this->toolbar->addComponent($external_editor); } - $info = $this->buildInfoScreen(false); $this->ctrl->forwardCommand($info); } @@ -818,23 +829,23 @@ protected function toggleLearningProgress(): void ilLPStatusWrapper::_updateStatus($this->obj_id, $this->user->getId()); $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_obj_modified'), true); - $this->ctrl->redirect($this, 'infoScreen'); + $this->ctrl->redirect($this, Capabilities::INFO_PAGE->value); } public function buildInfoScreen(bool $kiosk_mode): ilInfoScreenGUI { $info = new ilInfoScreenGUI($this); - if(!$kiosk_mode) { // in kiosk mode we don't want to show the following sections + if (!$kiosk_mode) { // in kiosk mode we don't want to show the following sections $info->enablePrivateNotes(); - if ($this->checkPermissionBool("read")) { + if ($this->capabilities->get(Capabilities::DOWNLOAD)->isUnlocked()) { $info->enableNews(); } // no news editing for files, just notifications $info->enableNewsEditing(false); - if ($this->checkPermissionBool("write")) { + if ($this->capabilities->get(Capabilities::MANAGE_VERSIONS)->isUnlocked()) { $news_set = new ilSetting("news"); $enable_internal_rss = $news_set->get("enable_rss_for_internal"); @@ -869,7 +880,7 @@ public function buildInfoScreen(bool $kiosk_mode): ilInfoScreenGUI } // Download Launcher - if ($this->checkPermissionBool("read", self::CMD_SEND_FILE)) { + if ($this->capabilities->get(Capabilities::DOWNLOAD)->isUnlocked()) { // get permanent download link for repository if ($this->id_type === self::REPOSITORY_NODE_ID) { $download_target = ilObjFileAccess::_getPermanentDownloadLink($this->node_id); @@ -955,7 +966,15 @@ protected function setTabs(): void $this->ctrl->setParameter($this, "ref_id", $this->node_id); - if ($this->checkPermissionBool("write")) { + if (($c = $this->capabilities->get(Capabilities::VIEW_EXTERNAL)) && $c->isUnlocked()) { + $this->tabs_gui->addTab( + "content", + $this->lng->txt("content"), + $c->getURI() + ); + } + + if (($c = $this->capabilities->get(Capabilities::MANAGE_VERSIONS)) && $c->isUnlocked()) { $this->tabs_gui->addTab( "id_versions", $this->lng->txt(self::CMD_VERSIONS), @@ -963,7 +982,7 @@ protected function setTabs(): void ); } - if ($this->checkPermissionBool("visible") || $this->checkPermissionBool("read")) { + if (($c = $this->capabilities->get(Capabilities::INFO_PAGE)) && $c->isUnlocked()) { $this->tabs_gui->addTab( "id_info", $this->lng->txt("info_short"), @@ -971,7 +990,7 @@ protected function setTabs(): void ); } - if ($this->checkPermissionBool("write")) { + if (($c = $this->capabilities->get(Capabilities::EDIT_SETTINGS)) && $c->isUnlocked()) { $this->tabs_gui->addTab( "settings", $this->lng->txt("settings"), @@ -988,7 +1007,7 @@ protected function setTabs(): void } // meta data - if ($this->checkPermissionBool("write")) { + if (($c = $this->capabilities->get(Capabilities::EDIT_SETTINGS)) && $c->isUnlocked()) { $mdgui = new ilObjectMetaDataGUI($this->object, null, null, $this->call_by_reference); $mdtab = $mdgui->getTab(); if ($mdtab) { @@ -1001,7 +1020,7 @@ protected function setTabs(): void } // export - if ($this->checkPermissionBool("write")) { + if (($c = $this->capabilities->get(Capabilities::EDIT_SETTINGS)) && $c->isUnlocked()) { $this->tabs_gui->addTab( "export", $this->lng->txt("export"), @@ -1054,7 +1073,7 @@ public static function _goto($a_target, $a_additional = null): void if ($ilAccess->checkAccess("visible", "", $a_target) || $ilAccess->checkAccess("read", "", $a_target)) { - ilObjectGUI::_gotoRepositoryNode($a_target, "infoScreen"); + ilObjectGUI::_gotoRepositoryNode($a_target, Capabilities::INFO_PAGE->value); } elseif ($ilAccess->checkAccess("read", "", ROOT_FOLDER_ID)) { $main_tpl->setOnScreenMessage( 'failure', diff --git a/components/ILIAS/File/classes/class.ilObjFileListGUI.php b/components/ILIAS/File/classes/class.ilObjFileListGUI.php index e3737b9b4bdd..c441a0c6454e 100755 --- a/components/ILIAS/File/classes/class.ilObjFileListGUI.php +++ b/components/ILIAS/File/classes/class.ilObjFileListGUI.php @@ -17,13 +17,12 @@ *********************************************************************/ use ILIAS\File\Icon\IconDatabaseRepository; -use ILIAS\ResourceStorage\Flavour\Definition\CropToRectangle; -use ILIAS\ResourceStorage\Flavour\Definition\FlavourDefinition; -use ILIAS\ResourceStorage\Flavour\Definition\PagesToExtract; use ILIAS\ResourceStorage\Services; -use ILIAS\Data\DataSize; use ILIAS\components\WOPI\Discovery\ActionDBRepository; -use ILIAS\components\WOPI\Discovery\ActionTarget; +use ILIAS\File\Capabilities\CapabilityResolver; +use ILIAS\File\Capabilities\Capabilities; +use ILIAS\File\Capabilities\UnzipCapability; +use ILIAS\File\Capabilities\CapabilityBuilder; /** * Class ilObjFileListGUI @@ -37,9 +36,10 @@ class ilObjFileListGUI extends ilObjectListGUI use ilObjFileSecureString; private ilObjFileInfoRepository $file_info; + private CapabilityBuilder $capability_builder; + private ?\ILIAS\File\Capabilities\CapabilityCollection $capabilities = null; protected string $title; private IconDatabaseRepository $icon_repo; - private ActionDBRepository $action_repo; private Services $irss; public function __construct(int $context = self::CONTEXT_REPOSITORY) @@ -48,8 +48,14 @@ public function __construct(int $context = self::CONTEXT_REPOSITORY) global $DIC; $DIC->language()->loadLanguageModule('wopi'); - $this->action_repo = new ActionDBRepository($DIC->database()); $this->file_info = new ilObjFileInfoRepository(); + $this->capability_builder = new CapabilityBuilder( + $this->file_info, + $this->access, + $this->ctrl, + new ActionDBRepository($DIC->database()) + ); + } /** @@ -69,7 +75,7 @@ public function init(): void $this->copy_enabled = true; $this->subscribe_enabled = true; $this->link_enabled = true; - $this->info_screen_enabled = true; + $this->info_screen_enabled = false; $this->type = ilObjFile::OBJECT_TYPE; $this->gui_class_name = ilObjFileGUI::class; $this->icon_repo = new IconDatabaseRepository(); @@ -82,6 +88,53 @@ public function init(): void $this->commands = ilObjFileAccess::_getCommands(); } + public function getCommands(): array + { + $this->capabilities = $this->capability_builder->get($this->ref_id); + + $best = $this->capabilities->getBest(); + + foreach ($this->commands as $key => $command) { + if ($command['cmd'] === $best->getCapability()->value) { + $default_set = true; + $this->commands[$key]['default'] = true; + } + } + + return parent::getCommands(); + } + + public function getCommandLink(string $cmd): string + { + $info = $this->file_info->getByObjectId($this->obj_id); + $this->capabilities = $this->capability_builder->get($this->ref_id); + + $needed_capability = Capabilities::fromCommand($cmd); + $capability = $this->capabilities->get($needed_capability); + if ($capability === false || !$capability->isUnlocked()) { + return ''; + } + + switch ($this->context) { + case self::CONTEXT_REPOSITORY: + return (string) $capability->getURI(); + case self::CONTEXT_WORKSPACE: + $this->ctrl->setParameterByClass(ilObjFileGUI::class, 'wsp_id', $this->ref_id); + if ($cmd === "sendfile" && !ilObjFileAccess::_shouldDownloadDirectly($this->obj_id)) { + return $this->ctrl->getLinkTargetByClass( + ilObjFileGUI::class, + Capabilities::INFO_PAGE->value + ); + } + break; + + } + + return parent::getCommandLink($cmd); + } + + + public function getTitle(): string { return $this->file_info->getByObjectId($this->obj_id)->getListTitle(); @@ -101,7 +154,7 @@ public function getCommandFrame(string $cmd): string $frame = ""; switch ($cmd) { - case 'sendfile': + case Capabilities::DOWNLOAD->value: if ($info->shouldDeliverInline()) { $frame = '_blank'; } @@ -142,6 +195,8 @@ public function getProperties(): array { global $DIC; + $this->capabilities = $this->capability_builder->get($this->ref_id); + $props = parent::getProperties(); $info = $this->file_info->getByObjectId($this->obj_id); @@ -164,8 +219,9 @@ public function getProperties(): array $version = $info->getVersion(); if ($version > 1) { + // add versions link - if (parent::checkCommandAccess("write", "versions", $this->ref_id, $this->type)) { + if ($this->capabilities->get(Capabilities::MANAGE_VERSIONS)->isUnlocked()) { $link = $this->getCommandLink("versions"); $value = "" . $DIC->language()->txt("version") . ": $version"; } else { @@ -220,13 +276,11 @@ public function checkCommandAccess( if ($this->context !== self::CONTEXT_REPOSITORY && $permission === "edit_learning_progress") { return false; } - $info = $this->file_info->getByObjectId($this->obj_id); - $additional_check = match ($cmd) { - ilFileVersionsGUI::CMD_UNZIP_CURRENT_REVISION => $info->isZip(), - 'editExternal' => $this->action_repo->hasEditActionForSuffix($info->getSuffix()), - default => true, - }; + $this->capabilities = $this->capability_builder->get($this->ref_id); + + $capability = Capabilities::fromCommand($cmd); + $additional_check = $this->capabilities->get($capability)->isUnlocked(); return $additional_check && parent::checkCommandAccess( $permission, @@ -237,53 +291,5 @@ public function checkCommandAccess( ); } - public function getCommandLink(string $cmd): string - { - $info = $this->file_info->getByObjectId($this->obj_id); - $infoscreen = function (): string { - $this->ctrl->setParameterByClass(ilRepositoryGUI::class, 'ref_id', $this->ref_id); - return $this->ctrl->getLinkTargetByClass( - ilRepositoryGUI::class, - 'infoScreen' - ); - }; - switch ($this->context) { - case self::CONTEXT_REPOSITORY: - // only create permalink for repository - if ($cmd === "sendfile") { - if (ilObjFileAccess::_shouldDownloadDirectly($this->obj_id)) { - // return the perma link for downloads - return ilObjFileAccess::_getPermanentDownloadLink($this->ref_id); - } - - return $infoscreen(); - } - if (ilFileVersionsGUI::CMD_UNZIP_CURRENT_REVISION === $cmd) { - if ($info->isZip()) { - $this->ctrl->setParameterByClass(ilRepositoryGUI::class, 'ref_id', $this->ref_id); - $cmd_link = $this->ctrl->getLinkTargetByClass( - ilRepositoryGUI::class, - ilFileVersionsGUI::CMD_UNZIP_CURRENT_REVISION - ); - $this->ctrl->setParameterByClass(ilRepositoryGUI::class, 'ref_id', $this->requested_ref_id); - } else { - $access_granted = false; - } - } - return parent::getCommandLink($cmd); - case self::CONTEXT_WORKSPACE: - $this->ctrl->setParameterByClass(ilObjFileGUI::class, 'wsp_id', $this->ref_id); - if ($cmd === "sendfile" && !ilObjFileAccess::_shouldDownloadDirectly($this->obj_id)) { - return $this->ctrl->getLinkTargetByClass( - ilObjFileGUI::class, - 'infoScreen' - ); - } - break; - - } - - return parent::getCommandLink($cmd); - } } diff --git a/components/ILIAS/WOPI/classes/Administration/class.ilWOPIAdministrationGUI.php b/components/ILIAS/WOPI/classes/Administration/class.ilWOPIAdministrationGUI.php index 1b01b12612ad..7e5a69563266 100755 --- a/components/ILIAS/WOPI/classes/Administration/class.ilWOPIAdministrationGUI.php +++ b/components/ILIAS/WOPI/classes/Administration/class.ilWOPIAdministrationGUI.php @@ -93,14 +93,20 @@ public function executeCommand(): void private function index(): void { $supported_suffixes = $this->getSupportedSuffixes(); + $info = ''; if (!empty($supported_suffixes)) { - $this->maint_tpl->setOnScreenMessage( - 'info', - sprintf( - $this->lng->txt("currently_supported"), - implode(", ", $supported_suffixes) + $listing = $this->ui_factory->panel()->secondary()->legacy( + $this->lng->txt("currently_supported"), + $this->ui_factory->legacy( + $this->ui_renderer->render( + $this->ui_factory->listing()->descriptive([ + $this->lng->txt('action_edit') => implode(", ", $supported_suffixes[ActionTarget::EDIT->value]), + $this->lng->txt('action_view') => implode(", ", $supported_suffixes[ActionTarget::VIEW->value]), + ]) + ) ) ); + $info = $this->ui_renderer->render($listing); } $form = new ilWOPISettingsForm($this->settings); @@ -108,6 +114,8 @@ private function index(): void $this->maint_tpl->setContent( $form->getHTML() ); + + $this->maint_tpl->setRightContent($info); } private function getSupportedSuffixes(): array @@ -116,7 +124,10 @@ private function getSupportedSuffixes(): array if (!$wopi_activated) { return []; } - return $this->action_repo->getSupportedSuffixes(ActionTarget::EDIT); + return [ + ActionTarget::EDIT->value => $this->action_repo->getSupportedSuffixes(ActionTarget::EDIT), + ActionTarget::VIEW->value => $this->action_repo->getSupportedSuffixes(ActionTarget::VIEW), + ]; } private function show(): void