From 39ebf120c265b947e7cb6ec5cf0af2a57ccadd60 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Wed, 15 Jun 2016 09:47:33 +0200 Subject: [PATCH] Group shares with same source and target Fixes #24575 Note that this is a very limited solution and eventually we want smarter merging! --- apps/files_sharing/lib/MountProvider.php | 70 ++++++++++++++++++++- apps/files_sharing/lib/SharedMount.php | 24 +++++--- apps/files_sharing/lib/sharedstorage.php | 77 +++++++++++------------- 3 files changed, 118 insertions(+), 53 deletions(-) diff --git a/apps/files_sharing/lib/MountProvider.php b/apps/files_sharing/lib/MountProvider.php index 1a08b5e9b6..6bd6cf84d7 100644 --- a/apps/files_sharing/lib/MountProvider.php +++ b/apps/files_sharing/lib/MountProvider.php @@ -75,16 +75,21 @@ class MountProvider implements IMountProvider { return $share->getPermissions() > 0 && $share->getShareOwner() !== $user->getUID(); }); - $mounts = []; - foreach ($shares as $share) { + $groupedShares = $this->groupShares($shares); + $superShares = $this->superShares($groupedShares); + + + $mounts = []; + foreach ($superShares as $share) { try { $mounts[] = new SharedMount( '\OC\Files\Storage\Shared', $mounts, [ 'user' => $user->getUID(), - 'newShare' => $share, + 'superShare' => $share[0], + 'groupedShares' => $share[1], ], $storageFactory ); @@ -97,4 +102,63 @@ class MountProvider implements IMountProvider { // array_filter removes the null values from the array return array_filter($mounts); } + + /** + * @param \OCP\Share\IShare[] $shares + * @return \OCP\Share\IShare[] + */ + private function groupShares(array $shares) { + $tmp = []; + + foreach ($shares as $share) { + if (!isset($tmp[$share->getNodeId()])) { + $tmp[$share->getNodeId()] = []; + } + $tmp[$share->getNodeId()][$share->getTarget()][] = $share; + } + + $result = []; + foreach ($tmp as $tmp2) { + foreach ($tmp2 as $item) { + $result[] = $item; + } + } + + return $result; + } + + /** + * Extract super shares + * + * @param array $shares Array of \OCP\Share\IShare[] + * @return array Tuple of [superShare, groupedShares] + */ + private function superShares(array $groupedShares) { + $result = []; + + /** @var \OCP\Share\IShare[] $shares */ + foreach ($groupedShares as $shares) { + if (count($shares) === 0) { + continue; + } + + $superShare = $this->shareManager->newShare(); + + $superShare->setId($shares[0]->getId()) + ->setShareOwner($shares[0]->getShareOwner()) + ->setNodeId($shares[0]->getNodeId()) + ->setTarget($shares[0]->getTarget()); + + $permissions = 0; + foreach ($shares as $share) { + $permissions |= $share->getPermissions(); + } + + $superShare->setPermissions($permissions); + + $result[] = [$superShare, $shares]; + } + + return $result; + } } diff --git a/apps/files_sharing/lib/SharedMount.php b/apps/files_sharing/lib/SharedMount.php index e5b7edc8e0..57610db907 100644 --- a/apps/files_sharing/lib/SharedMount.php +++ b/apps/files_sharing/lib/SharedMount.php @@ -52,7 +52,10 @@ class SharedMount extends MountPoint implements MoveableMount { private $user; /** @var \OCP\Share\IShare */ - private $share; + private $superShare; + + /** @var \OCP\Share\IShare[] */ + private $groupedShares; /** * @param string $storage @@ -63,10 +66,13 @@ class SharedMount extends MountPoint implements MoveableMount { public function __construct($storage, array $mountpoints, $arguments = null, $loader = null) { $this->user = $arguments['user']; $this->recipientView = new View('/' . $this->user . '/files'); - $this->share = $arguments['newShare']; - $newMountPoint = $this->verifyMountPoint($this->share, $mountpoints); + + $this->superShare = $arguments['superShare']; + $this->groupedShares = $arguments['groupedShares']; + + $newMountPoint = $this->verifyMountPoint($this->superShare, $mountpoints); $absMountPoint = '/' . $this->user . '/files' . $newMountPoint; - $arguments['ownerView'] = new View('/' . $this->share->getShareOwner() . '/files'); + $arguments['ownerView'] = new View('/' . $this->superShare->getShareOwner() . '/files'); parent::__construct($storage, $absMountPoint, $arguments, $loader); } @@ -108,7 +114,11 @@ class SharedMount extends MountPoint implements MoveableMount { */ private function updateFileTarget($newPath, &$share) { $share->setTarget($newPath); - \OC::$server->getShareManager()->moveShare($share, $this->user); + + foreach ($this->groupedShares as $share) { + $share->setTarget($newPath); + \OC::$server->getShareManager()->moveShare($share, $this->user); + } } @@ -214,7 +224,7 @@ class SharedMount extends MountPoint implements MoveableMount { * @return \OCP\Share\IShare */ public function getShare() { - return $this->share; + return $this->superShare; } /** @@ -223,6 +233,6 @@ class SharedMount extends MountPoint implements MoveableMount { * @return int */ public function getStorageRootId() { - return $this->share->getNodeId(); + return $this->getShare()->getNodeId(); } } diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 710137cfe9..8e9a0f4122 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -43,11 +43,11 @@ use OCP\Lock\ILockingProvider; * Convert target path to source path and pass the function call to the correct storage provider */ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { - - private $share; // the shared resource - /** @var \OCP\Share\IShare */ - private $newShare; + private $superShare; + + /** @var \OCP\Share\IShare[] */ + private $groupedShares; /** * @var \OC\Files\View @@ -77,11 +77,14 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { public function __construct($arguments) { $this->ownerView = $arguments['ownerView']; $this->logger = \OC::$server->getLogger(); - $this->newShare = $arguments['newShare']; + + $this->superShare = $arguments['superShare']; + $this->groupedShares = $arguments['groupedShares']; + $this->user = $arguments['user']; - Filesystem::initMountPoints($this->newShare->getShareOwner()); - $sourcePath = $this->ownerView->getPath($this->newShare->getNodeId()); + Filesystem::initMountPoints($this->superShare->getShareOwner()); + $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId()); list($storage, $internalPath) = $this->ownerView->resolvePath($sourcePath); parent::__construct([ @@ -96,8 +99,8 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { } $this->initialized = true; try { - Filesystem::initMountPoints($this->newShare->getShareOwner()); - $sourcePath = $this->ownerView->getPath($this->newShare->getNodeId()); + Filesystem::initMountPoints($this->superShare->getShareOwner()); + $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId()); list($this->sourceStorage, $sourceInternalPath) = $this->ownerView->resolvePath($sourcePath); $this->sourceRootInfo = $this->sourceStorage->getCache()->get($sourceInternalPath); } catch (\Exception $e) { @@ -105,6 +108,13 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { } } + /** + * @return string + */ + public function getShareId() { + return $this->superShare->getId(); + } + private function isValid() { $this->init(); return $this->sourceRootInfo && ($this->sourceRootInfo->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE; @@ -119,15 +129,6 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { return 'shared::' . $this->getMountPoint(); } - /** - * get file cache of the shared item source - * - * @return int - */ - public function getSourceId() { - return $this->newShare->getNodeId(); - } - /** * Get the permissions granted for a shared file * @@ -138,7 +139,7 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { if (!$this->isValid()) { return 0; } - $permissions = $this->newShare->getPermissions(); + $permissions = $this->superShare->getPermissions(); // part files and the mount point always have delete permissions if ($target === '' || pathinfo($target, PATHINFO_EXTENSION) === 'part') { $permissions |= \OCP\Constants::PERMISSION_DELETE; @@ -260,30 +261,18 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { * @return string */ public function getMountPoint() { - return $this->newShare->getTarget(); + return $this->superShare->getTarget(); } /** * @param string $path */ public function setMountPoint($path) { - $this->newShare->setTarget($path); - } + $this->superShare->setTarget($path); - /** - * @return int - */ - public function getShareType() { - return $this->newShare->getShareType(); - } - - /** - * get share ID - * - * @return integer unique share ID - */ - public function getShareId() { - return $this->newShare->getId(); + foreach ($this->groupedShares as $share) { + $share->setTarget($path); + } } /** @@ -292,14 +281,14 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { * @return string */ public function getSharedFrom() { - return $this->newShare->getShareOwner(); + return $this->superShare->getShareOwner(); } /** * @return \OCP\Share\IShare */ public function getShare() { - return $this->newShare; + return $this->superShare; } /** @@ -308,7 +297,7 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { * @return string */ public function getItemType() { - return $this->newShare->getNodeType(); + return $this->superShare->getNodeType(); } public function getCache($path = '', $storage = null) { @@ -337,7 +326,7 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { } public function getOwner($path) { - return $this->newShare->getShareOwner(); + return $this->superShare->getShareOwner(); } /** @@ -346,7 +335,9 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { * @return bool */ public function unshareStorage() { - \OC::$server->getShareManager()->deleteFromSelf($this->newShare, $this->user); + foreach ($this->groupedShares as $share) { + \OC::$server->getShareManager()->deleteFromSelf($share, $this->user); + } return true; } @@ -362,7 +353,7 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { $targetStorage->acquireLock($targetInternalPath, $type, $provider); // lock the parent folders of the owner when locking the share as recipient if ($path === '') { - $sourcePath = $this->ownerView->getPath($this->newShare->getNodeId()); + $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId()); $this->ownerView->lockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true); } } @@ -378,7 +369,7 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage { $targetStorage->releaseLock($targetInternalPath, $type, $provider); // unlock the parent folders of the owner when unlocking the share as recipient if ($path === '') { - $sourcePath = $this->ownerView->getPath($this->newShare->getNodeId()); + $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId()); $this->ownerView->unlockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true); } }