Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJulius Härtl <jus@bitgrid.net>2022-08-10 11:41:59 +0300
committerJulius Härtl <jus@bitgrid.net>2022-08-31 17:20:05 +0300
commitde3e541fde5c1ac2f71368127474341e730e4030 (patch)
tree9b4a925f6df1c5c6c3d80b89ff9aae9818461075 /lib
parent650b809a03017bd624fe31c92387c91c1122a393 (diff)
API for fetching reference metadata
Signed-off-by: Julius Härtl <jus@bitgrid.net>
Diffstat (limited to 'lib')
-rw-r--r--lib/private/Collaboration/Reference/FileReferenceProvider.php93
-rw-r--r--lib/private/Collaboration/Reference/LinkReferenceProvider.php83
-rw-r--r--lib/private/Collaboration/Reference/Reference.php146
-rw-r--r--lib/private/Collaboration/Reference/ReferenceManager.php79
-rw-r--r--lib/public/Collaboration/Reference/IReference.php31
-rw-r--r--lib/public/Collaboration/Reference/IReferenceManager.php31
-rw-r--r--lib/public/Collaboration/Reference/IReferenceProvider.php27
7 files changed, 490 insertions, 0 deletions
diff --git a/lib/private/Collaboration/Reference/FileReferenceProvider.php b/lib/private/Collaboration/Reference/FileReferenceProvider.php
new file mode 100644
index 00000000000..9fb083f749c
--- /dev/null
+++ b/lib/private/Collaboration/Reference/FileReferenceProvider.php
@@ -0,0 +1,93 @@
+<?php
+/**
+ * @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OC\Collaboration\Reference;
+
+use OCP\Collaboration\Reference\IReference;
+use OCP\Collaboration\Reference\IReferenceProvider;
+use OCP\Files\IRootFolder;
+use OCP\Files\Node;
+use OCP\Files\NotFoundException;
+use OCP\IURLGenerator;
+use OCP\IUserSession;
+
+class FileReferenceProvider implements IReferenceProvider {
+ private IURLGenerator $urlGenerator;
+ private IRootFolder $rootFolder;
+ private ?string $userId;
+
+ public function __construct(IURLGenerator $urlGenerator, IRootFolder $rootFolder, IUserSession $userSession) {
+ $this->urlGenerator = $urlGenerator;
+ $this->rootFolder = $rootFolder;
+ $this->userId = $userSession->getUser() ? $userSession->getUser()->getUID() : null;
+ }
+
+ public function resolveReference(string $referenceText): ?IReference {
+ if (str_starts_with($referenceText, $this->urlGenerator->getAbsoluteURL('/index.php/f/')) || str_starts_with($referenceText, $this->urlGenerator->getAbsoluteURL('/f/'))) {
+ $reference = new Reference($referenceText);
+ try {
+ $this->fetchReference($reference);
+ } catch (NotFoundException $e) {
+ $reference->setAccessible(false);
+ }
+ return $reference;
+ }
+
+ return null;
+ }
+
+ /**
+ * @throws \OCP\Files\NotPermittedException
+ * @throws \OCP\Files\InvalidPathException
+ * @throws NotFoundException
+ * @throws \OC\User\NoUserException
+ */
+ private function fetchReference(Reference $reference) {
+ $fileId = str_replace($this->urlGenerator->getAbsoluteURL('/index.php/f/'), '', $reference->getId());
+ $fileId = str_replace($this->urlGenerator->getAbsoluteURL('/f/'), '', $fileId);
+
+ $userFolder = $this->rootFolder->getUserFolder($this->userId);
+ $files = $userFolder->getById((int)$fileId);
+
+ if (empty($files)) {
+ throw new NotFoundException();
+ }
+
+ /** @var Node $file */
+ $file = array_shift($files);
+
+ $reference->setTitle($file->getName());
+ $reference->setDescription($file->getMimetype());
+ $reference->setUrl($this->urlGenerator->getAbsoluteURL('/index.php/f/' . $fileId));
+ $reference->setImageUrl($this->urlGenerator->linkToRouteAbsolute('core.Preview.getPreviewByFileId', ['x' => 1600, 'y' => 630, 'fileId' => $fileId]));
+
+ $reference->setRichObject('file', [
+ 'id' => $file->getId(),
+ 'name' => $file->getName(),
+ 'size' => $file->getSize(),
+ 'path' => $file->getPath(),
+ 'link' => $reference->getUrl(),
+ 'mimetype' => $file->getMimetype(),
+ 'preview-available' => false
+ ]);
+ }
+}
diff --git a/lib/private/Collaboration/Reference/LinkReferenceProvider.php b/lib/private/Collaboration/Reference/LinkReferenceProvider.php
new file mode 100644
index 00000000000..75d6717de10
--- /dev/null
+++ b/lib/private/Collaboration/Reference/LinkReferenceProvider.php
@@ -0,0 +1,83 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OC\Collaboration\Reference;
+
+use Fusonic\OpenGraph\Consumer;
+use OCP\Collaboration\Reference\IReference;
+use OCP\Collaboration\Reference\IReferenceProvider;
+use OCP\Http\Client\IClientService;
+use Psr\Log\LoggerInterface;
+
+class LinkReferenceProvider implements IReferenceProvider {
+ public const URL_PATTERN = '/(\s|^)(https?:\/\/)?((?:[-A-Z0-9+_]+\.)+[-A-Z]+(?:\/[-A-Z0-9+&@#%?=~_|!:,.;()]*)*)(\s|$)/i';
+
+ private IClientService $clientService;
+ private LoggerInterface $logger;
+
+ public function __construct(IClientService $clientService, LoggerInterface $logger) {
+ $this->clientService = $clientService;
+ $this->logger = $logger;
+ }
+
+ public function resolveReference(string $referenceText): ?IReference {
+ if (preg_match(self::URL_PATTERN, $referenceText)) {
+ $reference = new Reference($referenceText);
+ $this->fetchReference($reference);
+ return $reference;
+ }
+
+ return null;
+ }
+
+ public function fetchReference(Reference $reference) {
+ $client = $this->clientService->newClient();
+ try {
+ $response = $client->get($reference->getId());
+ } catch (\Exception $e) {
+ $this->logger->debug('Failed to fetch link for obtaining open graph data', ['exception' => $e]);
+ return;
+ }
+
+ $responseBody = (string)$response->getBody();
+
+ $reference->setUrl($reference->getId());
+
+ // OpenGraph handling
+ $consumer = new Consumer();
+ $object = $consumer->loadHtml($responseBody);
+
+ if ($object->title) {
+ $reference->setTitle($object->title);
+ }
+
+ if ($object->description) {
+ $reference->setDescription($object->description);
+ }
+
+ if ($object->images) {
+ $reference->setImageUrl($object->images[0]->url);
+ }
+ }
+}
diff --git a/lib/private/Collaboration/Reference/Reference.php b/lib/private/Collaboration/Reference/Reference.php
new file mode 100644
index 00000000000..b7cfc00ecef
--- /dev/null
+++ b/lib/private/Collaboration/Reference/Reference.php
@@ -0,0 +1,146 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OC\Collaboration\Reference;
+
+class Reference implements \OCP\Collaboration\Reference\IReference, \JsonSerializable {
+ private string $reference;
+
+ private bool $accessible = true;
+
+ private ?string $title = null;
+ private ?string $description = null;
+ private ?string $imageUrl = null;
+ private ?string $url = null;
+
+ private ?string $richObjectType = null;
+ private ?array $richObject = null;
+
+ public function __construct(string $reference) {
+ $this->reference = $reference;
+ }
+
+ public function getId(): string {
+ return $this->reference;
+ }
+
+ public function setAccessible(bool $accessible): void {
+ $this->accessible = $accessible;
+ }
+
+ public function setTitle(string $title): void {
+ $this->title = $title;
+ }
+
+ public function getTitle(): string {
+ return $this->title ?? $this->reference;
+ }
+
+ public function setDescription(?string $description): void {
+ $this->description = $description;
+ }
+
+ public function getDescription(): ?string {
+ return $this->description;
+ }
+
+ public function setImageUrl(?string $imageUrl): void {
+ $this->imageUrl = $imageUrl;
+ }
+
+ public function getImageUrl(): ?string {
+ return $this->imageUrl;
+ }
+
+ public function setUrl(?string $url): void {
+ $this->url = $url;
+ }
+
+ public function getUrl(): ?string {
+ return $this->url;
+ }
+
+ public function setRichObject(string $type, array $richObject): void {
+ $this->richObjectType = $type;
+ $this->richObject = $richObject;
+ }
+
+ public function getRichObjectType(): string {
+ if (!$this->richObjectType) {
+ return 'open-graph';
+ }
+ return $this->richObjectType;
+ }
+
+ public function getRichObject(): array {
+ if (!$this->richObject) {
+ return $this->getOpenGraphObject();
+ }
+ return $this->richObject;
+ }
+
+ public function getOpenGraphObject(): array {
+ return [
+ 'id' => $this->getId(),
+ 'name' => $this->getTitle(),
+ 'description' => $this->getDescription(),
+ 'thumb' => $this->getImageUrl(),
+ 'link' => $this->getUrl()
+ ];
+ }
+
+ public static function toCache(Reference $reference): array {
+ return [
+ 'id' => $reference->getId(),
+ 'title' => $reference->getTitle(),
+ 'imageUrl' => $reference->getImageUrl(),
+ 'description' => $reference->getDescription(),
+ 'link' => $reference->getUrl(),
+ 'accessible' => $reference->accessible,
+ 'richObjectType' => $reference->getRichObjectType(),
+ 'richObject' => $reference->getRichObject(),
+ ];
+ }
+
+ public static function fromCache(array $cache): Reference {
+ $reference = new Reference($cache['id']);
+ $reference->setTitle($cache['title']);
+ $reference->setDescription($cache['description']);
+ $reference->setImageUrl($cache['imageUrl']);
+ $reference->setUrl($cache['link']);
+ $reference->setRichObject($cache['richObjectType'], $cache['richObject']);
+ $reference->setAccessible($cache['accessible']);
+ return $reference;
+ }
+
+ public function jsonSerialize() {
+ return [
+ 'richObjectType' => $this->getRichObjectType(),
+ 'richObject' => $this->getRichObject(),
+ 'openGraphObject' => $this->getOpenGraphObject(),
+ 'accessible' => $this->accessible
+ ];
+ }
+}
diff --git a/lib/private/Collaboration/Reference/ReferenceManager.php b/lib/private/Collaboration/Reference/ReferenceManager.php
new file mode 100644
index 00000000000..dc2f01416fe
--- /dev/null
+++ b/lib/private/Collaboration/Reference/ReferenceManager.php
@@ -0,0 +1,79 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OC\Collaboration\Reference;
+
+use OCP\Collaboration\Reference\IReference;
+use OCP\Collaboration\Reference\IReferenceManager;
+use OCP\Collaboration\Reference\IReferenceProvider;
+use OCP\ICache;
+use OCP\ICacheFactory;
+
+class ReferenceManager implements IReferenceManager {
+ public const URL_PATTERN = '/(\s|\n|^)(https?:\/\/)?((?:[-A-Z0-9+_]+\.)+[-A-Z]+(?:\/[-A-Z0-9+&@#%?=~_|!:,.;()]*)*)(\s|\n|$)/mi';
+ public const REF_PATTERN = '/#[A-z0-9_]+\/[A-z0-9_]+/i';
+
+ /** @var IReferenceProvider[] */
+ private array $providers = [];
+ private ICache $cache;
+
+ public function __construct(LinkReferenceProvider $linkReferenceProvider, FileReferenceProvider $fileReferenceProvider, ICacheFactory $cacheFactory) {
+ $this->registerReferenceProvider($fileReferenceProvider);
+ $this->registerReferenceProvider($linkReferenceProvider);
+ $this->cache = $cacheFactory->createDistributed('reference');
+ }
+
+ public function extractReferences(string $text): array {
+ $matches = [];
+ preg_match_all(self::REF_PATTERN, $text, $matches);
+ $references = $matches[0] ?? [];
+
+ preg_match_all(self::URL_PATTERN, $text, $matches);
+ $references = array_merge($references, $matches[0] ?? []);
+ return array_map(function ($reference) {
+ return trim($reference);
+ }, $references);
+ }
+
+ public function resolveReference(string $referenceId): ?IReference {
+ $cached = $this->cache->get($referenceId);
+ if ($cached) {
+ // TODO: Figure out caching for references that depend on the viewer user
+ return Reference::fromCache($cached);
+ }
+ foreach ($this->providers as $provider) {
+ $reference = $provider->resolveReference($referenceId);
+ if ($reference) {
+ $this->cache->set($referenceId, Reference::toCache($reference), 60);
+ return $reference;
+ }
+ }
+
+ return null;
+ }
+
+ public function registerReferenceProvider(IReferenceProvider $provider): void {
+ $this->providers[] = $provider;
+ }
+}
diff --git a/lib/public/Collaboration/Reference/IReference.php b/lib/public/Collaboration/Reference/IReference.php
new file mode 100644
index 00000000000..1f4bf04c796
--- /dev/null
+++ b/lib/public/Collaboration/Reference/IReference.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCP\Collaboration\Reference;
+
+use OC\Collaboration\Reference\Reference;
+
+interface IReference {
+ public function getRichObject(): array;
+
+ public static function toCache(Reference $reference): array;
+}
diff --git a/lib/public/Collaboration/Reference/IReferenceManager.php b/lib/public/Collaboration/Reference/IReferenceManager.php
new file mode 100644
index 00000000000..baf75d74838
--- /dev/null
+++ b/lib/public/Collaboration/Reference/IReferenceManager.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCP\Collaboration\Reference;
+
+interface IReferenceManager {
+ public function extractReferences(string $text): array;
+
+ public function resolveReference(string $reference): ?IReference;
+
+ public function registerReferenceProvider(IReferenceProvider $provider): void;
+}
diff --git a/lib/public/Collaboration/Reference/IReferenceProvider.php b/lib/public/Collaboration/Reference/IReferenceProvider.php
new file mode 100644
index 00000000000..232874709c2
--- /dev/null
+++ b/lib/public/Collaboration/Reference/IReferenceProvider.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCP\Collaboration\Reference;
+
+interface IReferenceProvider {
+ public function resolveReference(string $referenceText): ?IReference;
+}