diff options
Diffstat (limited to 'lib/private/Collaboration/Reference/ReferenceManager.php')
-rw-r--r-- | lib/private/Collaboration/Reference/ReferenceManager.php | 71 |
1 files changed, 39 insertions, 32 deletions
diff --git a/lib/private/Collaboration/Reference/ReferenceManager.php b/lib/private/Collaboration/Reference/ReferenceManager.php index 1db87a56494..9287b66b2a2 100644 --- a/lib/private/Collaboration/Reference/ReferenceManager.php +++ b/lib/private/Collaboration/Reference/ReferenceManager.php @@ -2,24 +2,8 @@ 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/>. + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OC\Collaboration\Reference; @@ -27,6 +11,7 @@ namespace OC\Collaboration\Reference; use OC\AppFramework\Bootstrap\Coordinator; use OC\Collaboration\Reference\File\FileReferenceProvider; use OCP\Collaboration\Reference\IDiscoverableReferenceProvider; +use OCP\Collaboration\Reference\IPublicReferenceProvider; use OCP\Collaboration\Reference\IReference; use OCP\Collaboration\Reference\IReferenceManager; use OCP\Collaboration\Reference\IReferenceProvider; @@ -75,14 +60,14 @@ class ReferenceManager implements IReferenceManager { /** * Try to get a cached reference object from a reference string */ - public function getReferenceFromCache(string $referenceId): ?IReference { - $matchedProvider = $this->getMatchedProvider($referenceId); + public function getReferenceFromCache(string $referenceId, bool $public = false, string $sharingToken = ''): ?IReference { + $matchedProvider = $this->getMatchedProvider($referenceId, $public); if ($matchedProvider === null) { return null; } - $cacheKey = $this->getFullCacheKey($matchedProvider, $referenceId); + $cacheKey = $this->getFullCacheKey($matchedProvider, $referenceId, $public, $sharingToken); return $this->getReferenceByCacheKey($cacheKey); } @@ -102,21 +87,31 @@ class ReferenceManager implements IReferenceManager { * Get a reference object from a reference string with a matching provider * Use a cached reference if possible */ - public function resolveReference(string $referenceId): ?IReference { - $matchedProvider = $this->getMatchedProvider($referenceId); + public function resolveReference(string $referenceId, bool $public = false, $sharingToken = ''): ?IReference { + $matchedProvider = $this->getMatchedProvider($referenceId, $public); if ($matchedProvider === null) { return null; } - $cacheKey = $this->getFullCacheKey($matchedProvider, $referenceId); + $cacheKey = $this->getFullCacheKey($matchedProvider, $referenceId, $public, $sharingToken); $cached = $this->cache->get($cacheKey); if ($cached) { return Reference::fromCache($cached); } - $reference = $matchedProvider->resolveReference($referenceId); + $reference = null; + if ($public && $matchedProvider instanceof IPublicReferenceProvider) { + $reference = $matchedProvider->resolveReferencePublic($referenceId, $sharingToken); + } elseif ($matchedProvider instanceof IReferenceProvider) { + $reference = $matchedProvider->resolveReference($referenceId); + } if ($reference) { + $cachePrefix = $matchedProvider->getCachePrefix($referenceId); + if ($cachePrefix !== '') { + // If a prefix is used we set an additional key to know when we need to delete by prefix during invalidateCache() + $this->cache->set('hasPrefix-' . md5($cachePrefix), true, self::CACHE_TTL); + } $this->cache->set($cacheKey, Reference::toCache($reference), self::CACHE_TTL); return $reference; } @@ -128,11 +123,14 @@ class ReferenceManager implements IReferenceManager { * Try to match a reference string with all the registered providers * Fallback to the link reference provider (using OpenGraph) * - * @return IReferenceProvider|null the first matching provider + * @return IReferenceProvider|IPublicReferenceProvider|null the first matching provider */ - private function getMatchedProvider(string $referenceId): ?IReferenceProvider { + private function getMatchedProvider(string $referenceId, bool $public): null|IReferenceProvider|IPublicReferenceProvider { $matchedProvider = null; foreach ($this->getProviders() as $provider) { + if ($public && !($provider instanceof IPublicReferenceProvider)) { + continue; + } $matchedProvider = $provider->matchReference($referenceId) ? $provider : null; if ($matchedProvider !== null) { break; @@ -149,8 +147,13 @@ class ReferenceManager implements IReferenceManager { /** * Get a hashed full cache key from a key and prefix given by a provider */ - private function getFullCacheKey(IReferenceProvider $provider, string $referenceId): string { - $cacheKey = $provider->getCacheKey($referenceId); + private function getFullCacheKey(IReferenceProvider $provider, string $referenceId, bool $public, string $sharingToken): string { + if ($public && !($provider instanceof IPublicReferenceProvider)) { + throw new \RuntimeException('Provider doesn\'t support public lookups'); + } + $cacheKey = $public + ? $provider->getCacheKeyPublic($referenceId, $sharingToken) + : $provider->getCacheKey($referenceId); return md5($provider->getCachePrefix($referenceId)) . ( $cacheKey !== null ? ('-' . md5($cacheKey)) : '' ); @@ -161,7 +164,11 @@ class ReferenceManager implements IReferenceManager { */ public function invalidateCache(string $cachePrefix, ?string $cacheKey = null): void { if ($cacheKey === null) { - $this->cache->clear(md5($cachePrefix)); + // clear might be a heavy operation, so we only do it if there have actually been keys set + if ($this->cache->remove('hasPrefix-' . md5($cachePrefix))) { + $this->cache->clear(md5($cachePrefix)); + } + return; } @@ -224,7 +231,7 @@ class ReferenceManager implements IReferenceManager { } $configKey = 'provider-last-use_' . $providerId; - $this->config->setUserValue($userId, 'references', $configKey, (string) $timestamp); + $this->config->setUserValue($userId, 'references', $configKey, (string)$timestamp); return true; } return false; @@ -247,7 +254,7 @@ class ReferenceManager implements IReferenceManager { $timestamps = []; foreach ($keys as $key) { $providerId = substr($key, strlen($prefix)); - $timestamp = (int) $this->config->getUserValue($userId, 'references', $key); + $timestamp = (int)$this->config->getUserValue($userId, 'references', $key); $timestamps[$providerId] = $timestamp; } return $timestamps; |