diff options
author | Julius Härtl <jus@bitgrid.net> | 2023-01-27 12:35:44 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-27 12:35:44 +0100 |
commit | a63b5575687bb838c82f86a11a1545668157dc71 (patch) | |
tree | aa0768aeee92df212b2af031a2032c1e906e42bd | |
parent | 8744029e14f0003f0878a953478c24394687c01a (diff) | |
parent | 81c2122ff8214332e2aeca5724b79c565b0979b3 (diff) | |
download | nextcloud-server-a63b5575687bb838c82f86a11a1545668157dc71.tar.gz nextcloud-server-a63b5575687bb838c82f86a11a1545668157dc71.zip |
Merge pull request #35557 from nextcloud/enh/31667/extend-reference-api-for-frontend-picker
-rw-r--r-- | build/psalm-baseline.xml | 5 | ||||
-rw-r--r-- | core/Controller/ReferenceApiController.php | 30 | ||||
-rw-r--r-- | core/routes.php | 2 | ||||
-rw-r--r-- | lib/base.php | 5 | ||||
-rw-r--r-- | lib/composer/composer/autoload_classmap.php | 4 | ||||
-rw-r--r-- | lib/composer/composer/autoload_static.php | 4 | ||||
-rw-r--r-- | lib/private/Collaboration/Reference/File/FileReferenceEventListener.php | 4 | ||||
-rw-r--r-- | lib/private/Collaboration/Reference/ReferenceManager.php | 116 | ||||
-rw-r--r-- | lib/private/Collaboration/Reference/RenderReferenceEventListener.php | 66 | ||||
-rw-r--r-- | lib/public/Collaboration/Reference/ADiscoverableReferenceProvider.php | 48 | ||||
-rw-r--r-- | lib/public/Collaboration/Reference/IDiscoverableReferenceProvider.php | 60 | ||||
-rw-r--r-- | lib/public/Collaboration/Reference/IReferenceManager.php | 28 | ||||
-rw-r--r-- | lib/public/Collaboration/Reference/ISearchableReferenceProvider.php | 36 |
13 files changed, 405 insertions, 3 deletions
diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index ed7b19eaa7f..c1c39c135f8 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -2015,6 +2015,11 @@ <code>addServiceListener</code> </InvalidArgument> </file> + <file src="lib/private/Collaboration/Reference/RenderReferenceEventListener.php"> + <InvalidArgument occurrences="1"> + <code>addServiceListener</code> + </InvalidArgument> + </file> <file src="lib/private/Command/CallableJob.php"> <ParamNameMismatch occurrences="1"> <code>$serializedCallable</code> diff --git a/core/Controller/ReferenceApiController.php b/core/Controller/ReferenceApiController.php index 266532113d8..6aba56d7e77 100644 --- a/core/Controller/ReferenceApiController.php +++ b/core/Controller/ReferenceApiController.php @@ -25,15 +25,21 @@ declare(strict_types=1); namespace OC\Core\Controller; use OCP\AppFramework\Http\DataResponse; +use OCP\Collaboration\Reference\IDiscoverableReferenceProvider; use OCP\Collaboration\Reference\IReferenceManager; use OCP\IRequest; class ReferenceApiController extends \OCP\AppFramework\OCSController { private IReferenceManager $referenceManager; + private ?string $userId; - public function __construct(string $appName, IRequest $request, IReferenceManager $referenceManager) { + public function __construct(string $appName, + IRequest $request, + IReferenceManager $referenceManager, + ?string $userId) { parent::__construct($appName, $request); $this->referenceManager = $referenceManager; + $this->userId = $userId; } /** @@ -88,4 +94,26 @@ class ReferenceApiController extends \OCP\AppFramework\OCSController { 'references' => array_filter($result) ]); } + + /** + * @NoAdminRequired + */ + public function getProvidersInfo(): DataResponse { + $providers = $this->referenceManager->getDiscoverableProviders(); + $jsonProviders = array_map(static function (IDiscoverableReferenceProvider $provider) { + return $provider->jsonSerialize(); + }, $providers); + return new DataResponse($jsonProviders); + } + + /** + * @NoAdminRequired + */ + public function touchProvider(string $providerId, ?int $timestamp = null): DataResponse { + if ($this->userId !== null) { + $success = $this->referenceManager->touchProvider($this->userId, $providerId, $timestamp); + return new DataResponse(['success' => $success]); + } + return new DataResponse(['success' => false]); + } } diff --git a/core/routes.php b/core/routes.php index a3fdfafd7bf..dcf8e4024af 100644 --- a/core/routes.php +++ b/core/routes.php @@ -134,6 +134,8 @@ $application->registerRoutes($this, [ ['root' => '/references', 'name' => 'ReferenceApi#resolveOne', 'url' => '/resolve', 'verb' => 'GET'], ['root' => '/references', 'name' => 'ReferenceApi#extract', 'url' => '/extract', 'verb' => 'POST'], ['root' => '/references', 'name' => 'ReferenceApi#resolve', 'url' => '/resolve', 'verb' => 'POST'], + ['root' => '/references', 'name' => 'ReferenceApi#getProvidersInfo', 'url' => '/providers', 'verb' => 'GET'], + ['root' => '/references', 'name' => 'ReferenceApi#touchProvider', 'url' => '/provider/{providerId}', 'verb' => 'PUT'], ['root' => '/profile', 'name' => 'ProfileApi#setVisibility', 'url' => '/{targetUserId}', 'verb' => 'PUT'], diff --git a/lib/base.php b/lib/base.php index 6186e29bd6d..b5c5845b5a0 100644 --- a/lib/base.php +++ b/lib/base.php @@ -762,6 +762,7 @@ class OC { self::registerAccountHooks(); self::registerResourceCollectionHooks(); self::registerFileReferenceEventListener(); + self::registerRenderReferenceEventListener(); self::registerAppRestrictionsHooks(); // Make sure that the application class is not loaded before the database is setup @@ -925,6 +926,10 @@ class OC { \OC\Collaboration\Reference\File\FileReferenceEventListener::register(Server::get(IEventDispatcher::class)); } + private static function registerRenderReferenceEventListener() { + \OC\Collaboration\Reference\RenderReferenceEventListener::register(Server::get(IEventDispatcher::class)); + } + /** * register hooks for sharing */ diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 853d97f4a2e..465ea6b20e3 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -144,9 +144,12 @@ return array( 'OCP\\Collaboration\\Collaborators\\ISearchPlugin' => $baseDir . '/lib/public/Collaboration/Collaborators/ISearchPlugin.php', 'OCP\\Collaboration\\Collaborators\\ISearchResult' => $baseDir . '/lib/public/Collaboration/Collaborators/ISearchResult.php', 'OCP\\Collaboration\\Collaborators\\SearchResultType' => $baseDir . '/lib/public/Collaboration/Collaborators/SearchResultType.php', + 'OCP\\Collaboration\\Reference\\ADiscoverableReferenceProvider' => $baseDir . '/lib/public/Collaboration/Reference/ADiscoverableReferenceProvider.php', + 'OCP\\Collaboration\\Reference\\IDiscoverableReferenceProvider' => $baseDir . '/lib/public/Collaboration/Reference/IDiscoverableReferenceProvider.php', 'OCP\\Collaboration\\Reference\\IReference' => $baseDir . '/lib/public/Collaboration/Reference/IReference.php', 'OCP\\Collaboration\\Reference\\IReferenceManager' => $baseDir . '/lib/public/Collaboration/Reference/IReferenceManager.php', 'OCP\\Collaboration\\Reference\\IReferenceProvider' => $baseDir . '/lib/public/Collaboration/Reference/IReferenceProvider.php', + 'OCP\\Collaboration\\Reference\\ISearchableReferenceProvider' => $baseDir . '/lib/public/Collaboration/Reference/ISearchableReferenceProvider.php', 'OCP\\Collaboration\\Reference\\Reference' => $baseDir . '/lib/public/Collaboration/Reference/Reference.php', 'OCP\\Collaboration\\Reference\\RenderReferenceEvent' => $baseDir . '/lib/public/Collaboration/Reference/RenderReferenceEvent.php', 'OCP\\Collaboration\\Resources\\CollectionException' => $baseDir . '/lib/public/Collaboration/Resources/CollectionException.php', @@ -837,6 +840,7 @@ return array( 'OC\\Collaboration\\Reference\\File\\FileReferenceProvider' => $baseDir . '/lib/private/Collaboration/Reference/File/FileReferenceProvider.php', 'OC\\Collaboration\\Reference\\LinkReferenceProvider' => $baseDir . '/lib/private/Collaboration/Reference/LinkReferenceProvider.php', 'OC\\Collaboration\\Reference\\ReferenceManager' => $baseDir . '/lib/private/Collaboration/Reference/ReferenceManager.php', + 'OC\\Collaboration\\Reference\\RenderReferenceEventListener' => $baseDir . '/lib/private/Collaboration/Reference/RenderReferenceEventListener.php', 'OC\\Collaboration\\Resources\\Collection' => $baseDir . '/lib/private/Collaboration/Resources/Collection.php', 'OC\\Collaboration\\Resources\\Listener' => $baseDir . '/lib/private/Collaboration/Resources/Listener.php', 'OC\\Collaboration\\Resources\\Manager' => $baseDir . '/lib/private/Collaboration/Resources/Manager.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 455eccc45fd..bf19606cb4a 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -177,9 +177,12 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Collaboration\\Collaborators\\ISearchPlugin' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/ISearchPlugin.php', 'OCP\\Collaboration\\Collaborators\\ISearchResult' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/ISearchResult.php', 'OCP\\Collaboration\\Collaborators\\SearchResultType' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/SearchResultType.php', + 'OCP\\Collaboration\\Reference\\ADiscoverableReferenceProvider' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/ADiscoverableReferenceProvider.php', + 'OCP\\Collaboration\\Reference\\IDiscoverableReferenceProvider' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/IDiscoverableReferenceProvider.php', 'OCP\\Collaboration\\Reference\\IReference' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/IReference.php', 'OCP\\Collaboration\\Reference\\IReferenceManager' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/IReferenceManager.php', 'OCP\\Collaboration\\Reference\\IReferenceProvider' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/IReferenceProvider.php', + 'OCP\\Collaboration\\Reference\\ISearchableReferenceProvider' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/ISearchableReferenceProvider.php', 'OCP\\Collaboration\\Reference\\Reference' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/Reference.php', 'OCP\\Collaboration\\Reference\\RenderReferenceEvent' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Reference/RenderReferenceEvent.php', 'OCP\\Collaboration\\Resources\\CollectionException' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Resources/CollectionException.php', @@ -870,6 +873,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Collaboration\\Reference\\File\\FileReferenceProvider' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Reference/File/FileReferenceProvider.php', 'OC\\Collaboration\\Reference\\LinkReferenceProvider' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Reference/LinkReferenceProvider.php', 'OC\\Collaboration\\Reference\\ReferenceManager' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Reference/ReferenceManager.php', + 'OC\\Collaboration\\Reference\\RenderReferenceEventListener' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Reference/RenderReferenceEventListener.php', 'OC\\Collaboration\\Resources\\Collection' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Resources/Collection.php', 'OC\\Collaboration\\Resources\\Listener' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Resources/Listener.php', 'OC\\Collaboration\\Resources\\Manager' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Resources/Manager.php', diff --git a/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php b/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php index 6ccae9903dc..cb53b496406 100644 --- a/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php +++ b/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php @@ -27,11 +27,13 @@ namespace OC\Collaboration\Reference\File; use OCP\Collaboration\Reference\IReferenceManager; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventDispatcher; +use OCP\EventDispatcher\IEventListener; use OCP\Files\Events\Node\NodeDeletedEvent; use OCP\Share\Events\ShareCreatedEvent; use OCP\Share\Events\ShareDeletedEvent; -class FileReferenceEventListener implements \OCP\EventDispatcher\IEventListener { +/** @template-implements IEventListener<Event|NodeDeletedEvent|ShareDeletedEvent|ShareCreatedEvent> */ +class FileReferenceEventListener implements IEventListener { private IReferenceManager $manager; public function __construct(IReferenceManager $manager) { diff --git a/lib/private/Collaboration/Reference/ReferenceManager.php b/lib/private/Collaboration/Reference/ReferenceManager.php index a11d92fe2a9..2897410f5d6 100644 --- a/lib/private/Collaboration/Reference/ReferenceManager.php +++ b/lib/private/Collaboration/Reference/ReferenceManager.php @@ -26,13 +26,16 @@ namespace OC\Collaboration\Reference; use OC\AppFramework\Bootstrap\Coordinator; use OC\Collaboration\Reference\File\FileReferenceProvider; +use OCP\Collaboration\Reference\IDiscoverableReferenceProvider; use OCP\Collaboration\Reference\IReference; use OCP\Collaboration\Reference\IReferenceManager; use OCP\Collaboration\Reference\IReferenceProvider; use OCP\Collaboration\Reference\Reference; use OCP\ICache; use OCP\ICacheFactory; +use OCP\IConfig; use OCP\IURLGenerator; +use OCP\IUserSession; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; use Throwable; @@ -47,15 +50,31 @@ class ReferenceManager implements IReferenceManager { private ContainerInterface $container; private LinkReferenceProvider $linkReferenceProvider; private LoggerInterface $logger; + private IConfig $config; + private IUserSession $userSession; - public function __construct(LinkReferenceProvider $linkReferenceProvider, ICacheFactory $cacheFactory, Coordinator $coordinator, ContainerInterface $container, LoggerInterface $logger) { + public function __construct(LinkReferenceProvider $linkReferenceProvider, + ICacheFactory $cacheFactory, + Coordinator $coordinator, + ContainerInterface $container, + LoggerInterface $logger, + IConfig $config, + IUserSession $userSession) { $this->linkReferenceProvider = $linkReferenceProvider; $this->cache = $cacheFactory->createDistributed('reference'); $this->coordinator = $coordinator; $this->container = $container; $this->logger = $logger; + $this->config = $config; + $this->userSession = $userSession; } + /** + * Extract a list of URLs from a text + * + * @param string $text + * @return string[] + */ public function extractReferences(string $text): array { preg_match_all(IURLGenerator::URL_REGEX, $text, $matches); $references = $matches[0] ?? []; @@ -64,6 +83,12 @@ class ReferenceManager implements IReferenceManager { }, $references); } + /** + * Try to get a cached reference object from a reference string + * + * @param string $referenceId + * @return IReference|null + */ public function getReferenceFromCache(string $referenceId): ?IReference { $matchedProvider = $this->getMatchedProvider($referenceId); @@ -75,6 +100,12 @@ class ReferenceManager implements IReferenceManager { return $this->getReferenceByCacheKey($cacheKey); } + /** + * Try to get a cached reference object from a full cache key + * + * @param string $cacheKey + * @return IReference|null + */ public function getReferenceByCacheKey(string $cacheKey): ?IReference { $cached = $this->cache->get($cacheKey); if ($cached) { @@ -84,6 +115,13 @@ class ReferenceManager implements IReferenceManager { return null; } + /** + * Get a reference object from a reference string with a matching provider + * Use a cached reference if possible + * + * @param string $referenceId + * @return IReference|null + */ public function resolveReference(string $referenceId): ?IReference { $matchedProvider = $this->getMatchedProvider($referenceId); @@ -106,6 +144,13 @@ class ReferenceManager implements IReferenceManager { return null; } + /** + * Try to match a reference string with all the registered providers + * Fallback to the link reference provider (using OpenGraph) + * + * @param string $referenceId + * @return IReferenceProvider|null the first matching provider + */ private function getMatchedProvider(string $referenceId): ?IReferenceProvider { $matchedProvider = null; foreach ($this->getProviders() as $provider) { @@ -122,6 +167,13 @@ class ReferenceManager implements IReferenceManager { return $matchedProvider; } + /** + * Get a hashed full cache key from a key and prefix given by a provider + * + * @param IReferenceProvider $provider + * @param string $referenceId + * @return string + */ private function getFullCacheKey(IReferenceProvider $provider, string $referenceId): string { $cacheKey = $provider->getCacheKey($referenceId); return md5($provider->getCachePrefix($referenceId)) . ( @@ -129,6 +181,13 @@ class ReferenceManager implements IReferenceManager { ); } + /** + * Remove a specific cache entry from its key+prefix + * + * @param string $cachePrefix + * @param string|null $cacheKey + * @return void + */ public function invalidateCache(string $cachePrefix, ?string $cacheKey = null): void { if ($cacheKey === null) { $this->cache->clear(md5($cachePrefix)); @@ -167,4 +226,59 @@ class ReferenceManager implements IReferenceManager { return $this->providers; } + + /** + * @inheritDoc + */ + public function getDiscoverableProviders(): array { + // preserve 0 based index to avoid returning an object in data responses + return array_values( + array_filter($this->getProviders(), static function (IReferenceProvider $provider) { + return $provider instanceof IDiscoverableReferenceProvider; + }) + ); + } + + /** + * @inheritDoc + */ + public function touchProvider(string $userId, string $providerId, ?int $timestamp = null): bool { + $providers = $this->getDiscoverableProviders(); + $matchingProviders = array_filter($providers, static function (IDiscoverableReferenceProvider $provider) use ($providerId) { + return $provider->getId() === $providerId; + }); + if (!empty($matchingProviders)) { + if ($timestamp === null) { + $timestamp = time(); + } + + $configKey = 'provider-last-use_' . $providerId; + $this->config->setUserValue($userId, 'references', $configKey, (string) $timestamp); + return true; + } + return false; + } + + /** + * @inheritDoc + */ + public function getUserProviderTimestamps(): array { + $user = $this->userSession->getUser(); + if ($user === null) { + return []; + } + $userId = $user->getUID(); + $keys = $this->config->getUserKeys($userId, 'references'); + $prefix = 'provider-last-use_'; + $keys = array_filter($keys, static function (string $key) use ($prefix) { + return str_starts_with($key, $prefix); + }); + $timestamps = []; + foreach ($keys as $key) { + $providerId = substr($key, strlen($prefix)); + $timestamp = (int) $this->config->getUserValue($userId, 'references', $key); + $timestamps[$providerId] = $timestamp; + } + return $timestamps; + } } diff --git a/lib/private/Collaboration/Reference/RenderReferenceEventListener.php b/lib/private/Collaboration/Reference/RenderReferenceEventListener.php new file mode 100644 index 00000000000..dc2c5612666 --- /dev/null +++ b/lib/private/Collaboration/Reference/RenderReferenceEventListener.php @@ -0,0 +1,66 @@ +<?php + +declare(strict_types=1); +/** + * @copyright Copyright (c) 2022 Julien Veyssier <eneiluj@posteo.net> + * + * @author Julien Veyssier <eneiluj@posteo.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\IDiscoverableReferenceProvider; +use OCP\Collaboration\Reference\IReferenceManager; +use OCP\Collaboration\Reference\RenderReferenceEvent; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\EventDispatcher\IEventListener; +use OCP\IInitialStateService; + +/** @template-implements IEventListener<Event|RenderReferenceEvent> */ +class RenderReferenceEventListener implements IEventListener { + private IReferenceManager $manager; + private IInitialStateService $initialStateService; + + public function __construct(IReferenceManager $manager, IInitialStateService $initialStateService) { + $this->manager = $manager; + $this->initialStateService = $initialStateService; + } + + public static function register(IEventDispatcher $eventDispatcher): void { + $eventDispatcher->addServiceListener(RenderReferenceEvent::class, RenderReferenceEventListener::class); + } + + /** + * @inheritDoc + */ + public function handle(Event $event): void { + if (!($event instanceof RenderReferenceEvent)) { + return; + } + + $providers = $this->manager->getDiscoverableProviders(); + $jsonProviders = array_map(static function (IDiscoverableReferenceProvider $provider) { + return $provider->jsonSerialize(); + }, $providers); + $this->initialStateService->provideInitialState('core', 'reference-provider-list', $jsonProviders); + + $timestamps = $this->manager->getUserProviderTimestamps(); + $this->initialStateService->provideInitialState('core', 'reference-provider-timestamps', $timestamps); + } +} diff --git a/lib/public/Collaboration/Reference/ADiscoverableReferenceProvider.php b/lib/public/Collaboration/Reference/ADiscoverableReferenceProvider.php new file mode 100644 index 00000000000..9fa6fe691c9 --- /dev/null +++ b/lib/public/Collaboration/Reference/ADiscoverableReferenceProvider.php @@ -0,0 +1,48 @@ +<?php + +declare(strict_types=1); +/** + * @copyright Copyright (c) 2022 Julien Veyssier <eneiluj@posteo.net> + * + * @author Julien Veyssier <eneiluj@posteo.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 JsonSerializable; + +/** + * @since 26.0.0 + */ +abstract class ADiscoverableReferenceProvider implements IDiscoverableReferenceProvider, JsonSerializable { + /** + * @since 26.0.0 + */ + public function jsonSerialize(): array { + $json = [ + 'id' => $this->getId(), + 'title' => $this->getTitle(), + 'icon_url' => $this->getIconUrl(), + 'order' => $this->getOrder(), + ]; + if ($this instanceof ISearchableReferenceProvider) { + $json['search_providers_ids'] = $this->getSupportedSearchProviderIds(); + } + return $json; + } +} diff --git a/lib/public/Collaboration/Reference/IDiscoverableReferenceProvider.php b/lib/public/Collaboration/Reference/IDiscoverableReferenceProvider.php new file mode 100644 index 00000000000..847e03c602e --- /dev/null +++ b/lib/public/Collaboration/Reference/IDiscoverableReferenceProvider.php @@ -0,0 +1,60 @@ +<?php + +declare(strict_types=1); +/** + * @copyright Copyright (c) 2022 Julien Veyssier <eneiluj@posteo.net> + * + * @author Julien Veyssier <eneiluj@posteo.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; + +/** + * @since 26.0.0 + */ +interface IDiscoverableReferenceProvider extends IReferenceProvider { + /** + * @return string Unique id that identifies the reference provider + * @since 26.0.0 + */ + public function getId(): string; + + /** + * @return string User facing title of the widget + * @since 26.0.0 + */ + public function getTitle(): string; + + /** + * @return int Initial order for reference provider sorting + * @since 26.0.0 + */ + public function getOrder(): int; + + /** + * @return string url to an icon that can be displayed next to the reference provider title + * @since 26.0.0 + */ + public function getIconUrl(): string; + + /** + * @return array representation of the provider + * @since 26.0.0 + */ + public function jsonSerialize(): array; +} diff --git a/lib/public/Collaboration/Reference/IReferenceManager.php b/lib/public/Collaboration/Reference/IReferenceManager.php index 487e243c7ed..d757d35834a 100644 --- a/lib/public/Collaboration/Reference/IReferenceManager.php +++ b/lib/public/Collaboration/Reference/IReferenceManager.php @@ -67,4 +67,32 @@ interface IReferenceManager { * @since 25.0.0 */ public function invalidateCache(string $cachePrefix, ?string $cacheKey = null): void; + + /** + * Get information on discoverable reference providers (id, title, icon and order) + * If the provider is searchable, also get the list of supported unified search providers + * + * @return IDiscoverableReferenceProvider[] + * @since 26.0.0 + */ + public function getDiscoverableProviders(): array; + + /** + * Update or set the last used timestamp for a provider + * + * @param string $userId + * @param string $providerId + * @param int|null $timestamp use current timestamp if null + * @return bool + * @since 26.0.0 + */ + public function touchProvider(string $userId, string $providerId, ?int $timestamp = null): bool; + + /** + * Get all known last used timestamps for reference providers + * + * @return int[] + * @since 26.0.0 + */ + public function getUserProviderTimestamps(): array; } diff --git a/lib/public/Collaboration/Reference/ISearchableReferenceProvider.php b/lib/public/Collaboration/Reference/ISearchableReferenceProvider.php new file mode 100644 index 00000000000..b863de468a8 --- /dev/null +++ b/lib/public/Collaboration/Reference/ISearchableReferenceProvider.php @@ -0,0 +1,36 @@ +<?php + +declare(strict_types=1); +/** + * @copyright Copyright (c) 2022 Julien Veyssier <eneiluj@posteo.net> + * + * @author Julien Veyssier <eneiluj@posteo.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; + +/** + * @since 26.0.0 + */ +interface ISearchableReferenceProvider extends IDiscoverableReferenceProvider { + /** + * @return string[] list of search provider IDs that can be used by the vue-richtext picker + * @since 26.0.0 + */ + public function getSupportedSearchProviderIds(): array; +} |