aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/federatedfilesharing/lib/FederatedShareProvider.php39
-rw-r--r--apps/sharebymail/lib/ShareByMailProvider.php37
-rw-r--r--lib/composer/composer/autoload_classmap.php1
-rw-r--r--lib/composer/composer/autoload_static.php1
-rw-r--r--lib/private/Share20/DefaultShareProvider.php42
-rw-r--r--lib/private/Share20/Manager.php13
-rw-r--r--lib/public/Share/IShareProviderSupportsAllSharesInFolder.php24
-rw-r--r--tests/lib/Share20/ManagerTest.php23
8 files changed, 121 insertions, 59 deletions
diff --git a/apps/federatedfilesharing/lib/FederatedShareProvider.php b/apps/federatedfilesharing/lib/FederatedShareProvider.php
index d993b35845c..7c95b83a5dd 100644
--- a/apps/federatedfilesharing/lib/FederatedShareProvider.php
+++ b/apps/federatedfilesharing/lib/FederatedShareProvider.php
@@ -26,6 +26,7 @@ use OCP\Share\Exceptions\GenericShareException;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IShare;
use OCP\Share\IShareProvider;
+use OCP\Share\IShareProviderSupportsAllSharesInFolder;
use Psr\Log\LoggerInterface;
/**
@@ -33,7 +34,7 @@ use Psr\Log\LoggerInterface;
*
* @package OCA\FederatedFileSharing
*/
-class FederatedShareProvider implements IShareProvider {
+class FederatedShareProvider implements IShareProvider, IShareProviderSupportsAllSharesInFolder {
public const SHARE_TYPE_REMOTE = 6;
/** @var string */
@@ -553,7 +554,17 @@ class FederatedShareProvider implements IShareProvider {
if (!$shallow) {
throw new \Exception('non-shallow getSharesInFolder is no longer supported');
}
+ return $this->getSharesInFolderInternal($userId, $node, $reshares);
+ }
+
+ public function getAllSharesInFolder(Folder $node): array {
+ return $this->getSharesInFolderInternal(null, $node, null);
+ }
+ /**
+ * @return array<int, list<IShare>>
+ */
+ private function getSharesInFolderInternal(?string $userId, Folder $node, ?bool $reshares): array {
$qb = $this->dbConnection->getQueryBuilder();
$qb->select('*')
->from('share', 's')
@@ -562,18 +573,20 @@ class FederatedShareProvider implements IShareProvider {
$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
);
- /**
- * Reshares for this user are shares where they are the owner.
- */
- if ($reshares === false) {
- $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
- } else {
- $qb->andWhere(
- $qb->expr()->orX(
- $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
- $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
- )
- );
+ if ($userId !== null) {
+ /**
+ * Reshares for this user are shares where they are the owner.
+ */
+ if ($reshares !== true) {
+ $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
+ } else {
+ $qb->andWhere(
+ $qb->expr()->orX(
+ $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
+ $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
+ )
+ );
+ }
}
$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
diff --git a/apps/sharebymail/lib/ShareByMailProvider.php b/apps/sharebymail/lib/ShareByMailProvider.php
index e6e1cf509e9..194a402848e 100644
--- a/apps/sharebymail/lib/ShareByMailProvider.php
+++ b/apps/sharebymail/lib/ShareByMailProvider.php
@@ -1112,6 +1112,17 @@ class ShareByMailProvider extends DefaultShareProvider implements IShareProvider
}
public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true): array {
+ return $this->getSharesInFolderInternal($userId, $node, $reshares);
+ }
+
+ public function getAllSharesInFolder(Folder $node): array {
+ return $this->getSharesInFolderInternal(null, $node, null);
+ }
+
+ /**
+ * @return array<int, list<IShare>>
+ */
+ private function getSharesInFolderInternal(?string $userId, Folder $node, ?bool $reshares): array {
$qb = $this->dbConnection->getQueryBuilder();
$qb->select('*')
->from('share', 's')
@@ -1120,18 +1131,20 @@ class ShareByMailProvider extends DefaultShareProvider implements IShareProvider
$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
);
- /**
- * Reshares for this user are shares where they are the owner.
- */
- if ($reshares === false) {
- $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
- } else {
- $qb->andWhere(
- $qb->expr()->orX(
- $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
- $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
- )
- );
+ if ($userId !== null) {
+ /**
+ * Reshares for this user are shares where they are the owner.
+ */
+ if ($reshares !== true) {
+ $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
+ } else {
+ $qb->andWhere(
+ $qb->expr()->orX(
+ $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
+ $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
+ )
+ );
+ }
}
$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 177abfefe8e..b1c6c453b0a 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -780,6 +780,7 @@ return array(
'OCP\\Share\\IShareHelper' => $baseDir . '/lib/public/Share/IShareHelper.php',
'OCP\\Share\\IShareProvider' => $baseDir . '/lib/public/Share/IShareProvider.php',
'OCP\\Share\\IShareProviderSupportsAccept' => $baseDir . '/lib/public/Share/IShareProviderSupportsAccept.php',
+ 'OCP\\Share\\IShareProviderSupportsAllSharesInFolder' => $baseDir . '/lib/public/Share/IShareProviderSupportsAllSharesInFolder.php',
'OCP\\Share\\IShareProviderWithNotification' => $baseDir . '/lib/public/Share/IShareProviderWithNotification.php',
'OCP\\Share_Backend' => $baseDir . '/lib/public/Share_Backend.php',
'OCP\\Share_Backend_Collection' => $baseDir . '/lib/public/Share_Backend_Collection.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index ddccd0692ca..6eecb2da4b5 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -821,6 +821,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Share\\IShareHelper' => __DIR__ . '/../../..' . '/lib/public/Share/IShareHelper.php',
'OCP\\Share\\IShareProvider' => __DIR__ . '/../../..' . '/lib/public/Share/IShareProvider.php',
'OCP\\Share\\IShareProviderSupportsAccept' => __DIR__ . '/../../..' . '/lib/public/Share/IShareProviderSupportsAccept.php',
+ 'OCP\\Share\\IShareProviderSupportsAllSharesInFolder' => __DIR__ . '/../../..' . '/lib/public/Share/IShareProviderSupportsAllSharesInFolder.php',
'OCP\\Share\\IShareProviderWithNotification' => __DIR__ . '/../../..' . '/lib/public/Share/IShareProviderWithNotification.php',
'OCP\\Share_Backend' => __DIR__ . '/../../..' . '/lib/public/Share_Backend.php',
'OCP\\Share_Backend_Collection' => __DIR__ . '/../../..' . '/lib/public/Share_Backend_Collection.php',
diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php
index a257bc4f7b5..e1eebe1e450 100644
--- a/lib/private/Share20/DefaultShareProvider.php
+++ b/lib/private/Share20/DefaultShareProvider.php
@@ -5,6 +5,7 @@
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
+
namespace OC\Share20;
use OC\Files\Cache\Cache;
@@ -31,6 +32,7 @@ use OCP\Share\IAttributes;
use OCP\Share\IManager;
use OCP\Share\IShare;
use OCP\Share\IShareProviderSupportsAccept;
+use OCP\Share\IShareProviderSupportsAllSharesInFolder;
use OCP\Share\IShareProviderWithNotification;
use Psr\Log\LoggerInterface;
use function str_starts_with;
@@ -40,7 +42,7 @@ use function str_starts_with;
*
* @package OC\Share20
*/
-class DefaultShareProvider implements IShareProviderWithNotification, IShareProviderSupportsAccept {
+class DefaultShareProvider implements IShareProviderWithNotification, IShareProviderSupportsAccept, IShareProviderSupportsAllSharesInFolder {
// Special share type for user modified group shares
public const SHARE_TYPE_USERGROUP = 2;
@@ -603,6 +605,17 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv
throw new \Exception('non-shallow getSharesInFolder is no longer supported');
}
+ return $this->getSharesInFolderInternal($userId, $node, $reshares);
+ }
+
+ public function getAllSharesInFolder(Folder $node): array {
+ return $this->getSharesInFolderInternal(null, $node, null);
+ }
+
+ /**
+ * @return array<int, list<IShare>>
+ */
+ private function getSharesInFolderInternal(?string $userId, Folder $node, ?bool $reshares): array {
$qb = $this->dbConn->getQueryBuilder();
$qb->select('s.*',
'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
@@ -613,18 +626,20 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv
$qb->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter([IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_LINK], IQueryBuilder::PARAM_INT_ARRAY)));
- /**
- * Reshares for this user are shares where they are the owner.
- */
- if ($reshares === false) {
- $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
- } else {
- $qb->andWhere(
- $qb->expr()->orX(
- $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
- $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
- )
- );
+ if ($userId !== null) {
+ /**
+ * Reshares for this user are shares where they are the owner.
+ */
+ if ($reshares !== true) {
+ $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
+ } else {
+ $qb->andWhere(
+ $qb->expr()->orX(
+ $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
+ $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
+ )
+ );
+ }
}
// todo? maybe get these from the oc_mounts table
@@ -656,7 +671,6 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv
foreach ($chunks as $chunk) {
$qb->setParameter('chunk', $chunk, IQueryBuilder::PARAM_INT_ARRAY);
- $a = $qb->getSQL();
$cursor = $qb->executeQuery();
while ($data = $cursor->fetch()) {
$shares[$data['fileid']][] = $this->createShare($data);
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index 3b247475afa..2104c07593a 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -51,6 +51,7 @@ use OCP\Share\IProviderFactory;
use OCP\Share\IShare;
use OCP\Share\IShareProvider;
use OCP\Share\IShareProviderSupportsAccept;
+use OCP\Share\IShareProviderSupportsAllSharesInFolder;
use OCP\Share\IShareProviderWithNotification;
use Psr\Log\LoggerInterface;
@@ -1213,11 +1214,13 @@ class Manager implements IManager {
$shares = [];
foreach ($providers as $provider) {
if ($isOwnerless) {
- foreach ($node->getDirectoryListing() as $childNode) {
- $data = $provider->getSharesByPath($childNode);
- $fid = $childNode->getId();
- $shares[$fid] ??= [];
- $shares[$fid] = array_merge($shares[$fid], $data);
+ // If the provider does not implement the additional interface,
+ // we lack a performant way of querying all shares and therefore ignore the provider.
+ if ($provider instanceof IShareProviderSupportsAllSharesInFolder) {
+ foreach ($provider->getAllSharesInFolder($node) as $fid => $data) {
+ $shares[$fid] ??= [];
+ $shares[$fid] = array_merge($shares[$fid], $data);
+ }
}
} else {
foreach ($provider->getSharesInFolder($userId, $node, $reshares) as $fid => $data) {
diff --git a/lib/public/Share/IShareProviderSupportsAllSharesInFolder.php b/lib/public/Share/IShareProviderSupportsAllSharesInFolder.php
new file mode 100644
index 00000000000..e27da7682ce
--- /dev/null
+++ b/lib/public/Share/IShareProviderSupportsAllSharesInFolder.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCP\Share;
+
+use OCP\Files\Folder;
+
+/**
+ * Allows defining a IShareProvider with support for the getAllSharesInFolder method.
+ *
+ * @since 32.0.0
+ */
+interface IShareProviderSupportsAllSharesInFolder extends IShareProvider {
+ /**
+ * Get all shares in a folder.
+ *
+ * @return array<int, list<IShare>>
+ * @since 32.0.0
+ */
+ public function getAllSharesInFolder(Folder $node): array;
+}
diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php
index 9e778207a8e..357ae9ee678 100644
--- a/tests/lib/Share20/ManagerTest.php
+++ b/tests/lib/Share20/ManagerTest.php
@@ -55,6 +55,7 @@ use OCP\Share\IManager;
use OCP\Share\IProviderFactory;
use OCP\Share\IShare;
use OCP\Share\IShareProvider;
+use OCP\Share\IShareProviderSupportsAllSharesInFolder;
use PHPUnit\Framework\MockObject\MockBuilder;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
@@ -4551,7 +4552,7 @@ class ManagerTest extends \Test\TestCase {
$manager = $this->createManager($factory);
$factory->setProvider($this->defaultProvider);
- $extraProvider = $this->createMock(IShareProvider::class);
+ $extraProvider = $this->createMock(IShareProviderSupportsAllSharesInFolder::class);
$factory->setSecondProvider($extraProvider);
$share1 = $this->createMock(IShare::class);
@@ -4559,28 +4560,20 @@ class ManagerTest extends \Test\TestCase {
$mount = $this->createMock(IShareOwnerlessMount::class);
- $file = $this->createMock(File::class);
- $file
- ->method('getId')
- ->willReturn(1);
-
$folder = $this->createMock(Folder::class);
$folder
->method('getMountPoint')
->willReturn($mount);
- $folder
- ->method('getDirectoryListing')
- ->willReturn([$file]);
$this->defaultProvider
- ->method('getSharesByPath')
- ->with($file)
- ->willReturn([$share1]);
+ ->method('getAllSharesInFolder')
+ ->with($folder)
+ ->willReturn([1 => [$share1]]);
$extraProvider
- ->method('getSharesByPath')
- ->with($file)
- ->willReturn([$share2]);
+ ->method('getAllSharesInFolder')
+ ->with($folder)
+ ->willReturn([1 => [$share2]]);
$this->assertSame([
1 => [$share1, $share2],