* * @author Julien Veyssier * @author The Nextcloud Bookmarks contributors * * This file is licensed under the Affero General Public License version 3 or later. See the COPYING file. */ namespace OCA\Bookmarks\Reference; use OCA\Bookmarks\AppInfo\Application; use OCA\Bookmarks\Exception\UrlParseError; use OCA\Bookmarks\Service\Authorizer; use OCA\Bookmarks\Service\BookmarkService; use OCP\AppFramework\Db\DoesNotExistException; use OCP\Collaboration\Reference\ADiscoverableReferenceProvider; use OCP\Collaboration\Reference\IReference; use OCP\Collaboration\Reference\Reference; use OCP\IL10N; use OCP\IURLGenerator; class BookmarkReferenceProvider extends ADiscoverableReferenceProvider { private ?string $userId; private IL10N $l10n; private IURLGenerator $urlGenerator; private BookmarkService $bookmarkService; private Authorizer $authorizer; public function __construct(IL10N $l10n, ?string $userId, IURLGenerator $urlGenerator, BookmarkService $bookmarkService, Authorizer $authorizer) { $this->userId = $userId; $this->l10n = $l10n; $this->urlGenerator = $urlGenerator; $this->bookmarkService = $bookmarkService; $this->authorizer = $authorizer; } /** * @inheritDoc */ public function getId(): string { return Application::APP_ID . '-ref-bookmarks'; } /** * @inheritDoc */ public function getTitle(): string { return $this->l10n->t('Bookmarks'); } /** * @inheritDoc */ public function getOrder(): int { return 10; } /** * @inheritDoc */ public function getIconUrl(): string { return $this->urlGenerator->getAbsoluteURL( $this->urlGenerator->imagePath(Application::APP_ID, 'bookmarks-black.svg') ); } /** * @inheritDoc */ public function matchReference(string $referenceText): bool { $start = $this->urlGenerator->getAbsoluteURL('/apps/' . Application::APP_ID); $startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/' . Application::APP_ID); // link example: https://nextcloud.local/index.php/apps/deck/#/board/2/card/11 $noIndexMatch = preg_match('/^' . preg_quote($start, '/') . '\/bookmarks\/[0-9]+$/', $referenceText) === 1; $indexMatch = preg_match('/^' . preg_quote($startIndex, '/') . '\/bookmarks\/[0-9]+$/', $referenceText) === 1; if ($noIndexMatch || $indexMatch) { return true; } try { $this->bookmarkService->findByUrl($this->userId, $referenceText); return true; } catch (UrlParseError|DoesNotExistException $e) { return false; } } /** * @inheritDoc */ public function resolveReference(string $referenceText): ?IReference { if (!$this->matchReference($referenceText)) { return null; } $id = $this->getBookmarkId($referenceText); if ($id === null) { try { $bookmark = $this->bookmarkService->findByUrl($this->userId, $referenceText); } catch (UrlParseError|DoesNotExistException $e) { return null; } } else { $bookmark = $this->bookmarkService->findById((int)$id); } if ($bookmark === null) { return null; } if (!Authorizer::hasPermission(Authorizer::PERM_READ, $this->authorizer->getUserPermissionsForBookmark($this->userId, (int)$id))) { return null; } /** @var IReference $reference */ $reference = new Reference($referenceText); $reference->setRichObject(Application::APP_ID . '-bookmark', [ 'id' => $id, 'bookmark' => $bookmark->toArray(), ]); return $reference; } private function getBookmarkId(string $url): ?string { $start = $this->urlGenerator->getAbsoluteURL('/apps/' . Application::APP_ID); $startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/' . Application::APP_ID); preg_match('/^' . preg_quote($start, '/') . '\/bookmarks\/([0-9]+)$/', $url, $matches); if ($matches && count($matches) > 1) { return $matches[1]; } preg_match('/^' . preg_quote($startIndex, '/') . '\/bookmarks\/([0-9]+)$/', $url, $matches2); if ($matches2 && count($matches2) > 1) { return $matches2[1]; } return null; } public function getCachePrefix(string $referenceId): string { $id = $this->getBookmarkId($referenceId); return $id ?? $referenceId; } public function getCacheKey(string $referenceId): ?string { return $this->userId ?? ''; } }