diff options
Diffstat (limited to 'lib/private/Collaboration/Reference/File/FileReferenceProvider.php')
-rw-r--r-- | lib/private/Collaboration/Reference/File/FileReferenceProvider.php | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/lib/private/Collaboration/Reference/File/FileReferenceProvider.php b/lib/private/Collaboration/Reference/File/FileReferenceProvider.php new file mode 100644 index 00000000000..3cb174d9607 --- /dev/null +++ b/lib/private/Collaboration/Reference/File/FileReferenceProvider.php @@ -0,0 +1,161 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\Collaboration\Reference\File; + +use OC\User\NoUserException; +use OCP\Collaboration\Reference\ADiscoverableReferenceProvider; +use OCP\Collaboration\Reference\IReference; +use OCP\Collaboration\Reference\Reference; +use OCP\Files\IMimeTypeDetector; +use OCP\Files\InvalidPathException; +use OCP\Files\IRootFolder; +use OCP\Files\NotFoundException; +use OCP\Files\NotPermittedException; +use OCP\IL10N; +use OCP\IPreview; +use OCP\IURLGenerator; +use OCP\IUserSession; +use OCP\L10N\IFactory; + +class FileReferenceProvider extends ADiscoverableReferenceProvider { + private ?string $userId; + private IL10N $l10n; + + public function __construct( + private IURLGenerator $urlGenerator, + private IRootFolder $rootFolder, + IUserSession $userSession, + private IMimeTypeDetector $mimeTypeDetector, + private IPreview $previewManager, + IFactory $l10n, + ) { + $this->userId = $userSession->getUser()?->getUID(); + $this->l10n = $l10n->get('files'); + } + + public function matchReference(string $referenceText): bool { + return $this->getFilesAppLinkId($referenceText) !== null; + } + + private function getFilesAppLinkId(string $referenceText): ?int { + $start = $this->urlGenerator->getAbsoluteURL('/apps/files/'); + $startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/files/'); + + $fileId = null; + + if (mb_strpos($referenceText, $start) === 0) { + $parts = parse_url($referenceText); + parse_str($parts['query'] ?? '', $query); + $fileId = isset($query['fileid']) ? (int)$query['fileid'] : $fileId; + $fileId = isset($query['openfile']) ? (int)$query['openfile'] : $fileId; + } + + if (mb_strpos($referenceText, $startIndex) === 0) { + $parts = parse_url($referenceText); + parse_str($parts['query'] ?? '', $query); + $fileId = isset($query['fileid']) ? (int)$query['fileid'] : $fileId; + $fileId = isset($query['openfile']) ? (int)$query['openfile'] : $fileId; + } + + if (mb_strpos($referenceText, $this->urlGenerator->getAbsoluteURL('/index.php/f/')) === 0) { + $fileId = str_replace($this->urlGenerator->getAbsoluteURL('/index.php/f/'), '', $referenceText); + } + + if (mb_strpos($referenceText, $this->urlGenerator->getAbsoluteURL('/f/')) === 0) { + $fileId = str_replace($this->urlGenerator->getAbsoluteURL('/f/'), '', $referenceText); + } + + return $fileId !== null ? (int)$fileId : null; + } + + public function resolveReference(string $referenceText): ?IReference { + if ($this->matchReference($referenceText)) { + $reference = new Reference($referenceText); + try { + $this->fetchReference($reference); + } catch (NotFoundException $e) { + $reference->setRichObject('file', null); + $reference->setAccessible(false); + } + return $reference; + } + + return null; + } + + /** + * @throws NotFoundException + */ + private function fetchReference(Reference $reference): void { + if ($this->userId === null) { + throw new NotFoundException(); + } + + $fileId = $this->getFilesAppLinkId($reference->getId()); + if ($fileId === null) { + throw new NotFoundException(); + } + + try { + $userFolder = $this->rootFolder->getUserFolder($this->userId); + $file = $userFolder->getFirstNodeById($fileId); + + if (!$file) { + throw new NotFoundException(); + } + + $reference->setTitle($file->getName()); + $reference->setDescription($file->getMimetype()); + $reference->setUrl($this->urlGenerator->getAbsoluteURL('/index.php/f/' . $fileId)); + if ($this->previewManager->isMimeSupported($file->getMimeType())) { + $reference->setImageUrl($this->urlGenerator->linkToRouteAbsolute('core.Preview.getPreviewByFileId', ['x' => 1600, 'y' => 630, 'fileId' => $fileId])); + } else { + $fileTypeIconUrl = $this->mimeTypeDetector->mimeTypeIcon($file->getMimeType()); + $reference->setImageUrl($fileTypeIconUrl); + } + + $reference->setRichObject('file', [ + 'id' => $file->getId(), + 'name' => $file->getName(), + 'size' => $file->getSize(), + 'path' => $userFolder->getRelativePath($file->getPath()), + 'link' => $reference->getUrl(), + 'mimetype' => $file->getMimetype(), + 'mtime' => $file->getMTime(), + 'preview-available' => $this->previewManager->isAvailable($file) + ]); + } catch (InvalidPathException|NotFoundException|NotPermittedException|NoUserException $e) { + throw new NotFoundException(); + } + } + + public function getCachePrefix(string $referenceId): string { + return (string)$this->getFilesAppLinkId($referenceId); + } + + public function getCacheKey(string $referenceId): ?string { + return $this->userId ?? ''; + } + + public function getId(): string { + return 'files'; + } + + public function getTitle(): string { + return $this->l10n->t('Files'); + } + + public function getOrder(): int { + return 0; + } + + public function getIconUrl(): string { + return $this->urlGenerator->imagePath('files', 'folder.svg'); + } +} |