Group shares with same source and target

Fixes #24575

Note that this is a very limited solution and eventually we want smarter
merging!
This commit is contained in:
Roeland Jago Douma 2016-06-15 09:47:33 +02:00
parent 0874460e48
commit 04d5465228
No known key found for this signature in database
GPG Key ID: 1E152838F164D13B
3 changed files with 118 additions and 53 deletions

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}