]> source.dussan.org Git - nextcloud-server.git/commitdiff
Add getShareTypesInFolder to optimize folder listening
authorRobin Appelman <icewind@owncloud.com>
Sat, 18 Jun 2016 20:04:56 +0000 (22:04 +0200)
committerRoeland Jago Douma <roeland@famdouma.nl>
Mon, 31 Oct 2016 14:55:40 +0000 (15:55 +0100)
Signed-off-by: Robin Appelman <icewind@owncloud.com>
apps/dav/lib/Connector/Sabre/SharesPlugin.php
apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
apps/federatedfilesharing/lib/FederatedShareProvider.php
lib/private/Share20/DefaultShareProvider.php
lib/private/Share20/Manager.php
lib/private/Share20/ProviderFactory.php
lib/public/Share/IManager.php
lib/public/Share/IProviderFactory.php
lib/public/Share/IShareProvider.php
tests/lib/Share20/ManagerTest.php

index cd58f050dda3a569aaee0806b6c7967b6901eed3..ebb7fefff33ad3e1500958887d4da5a8ed361648 100644 (file)
@@ -136,6 +136,30 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin {
                return $shareTypes;
        }
 
+       private function getSharesTypesInFolder(\OCP\Files\Folder $node) {
+               $shares = $this->shareManager->getSharesInFolder(
+                       $this->userId,
+                       $node,
+                       false
+               );
+
+               $children = $node->getDirectoryListing();
+
+               $values = array_map(function (\OCP\Files\Node $node) use ($shares) {
+                       /** @var IShare[] $shares */
+                       $shares = (isset($shares[$node->getId()])) ? $shares[$node->getId()] : [];
+                       return array_map(function(IShare $share) {
+                               return $share->getShareType();
+                       }, $shares);
+               }, $children);
+
+               $keys = array_map(function (\OCP\Files\Node $node) {
+                       return $node->getId();
+               }, $children);
+
+               return array_combine($keys, $values);
+       }
+
        /**
         * Adds shares to propfind response
         *
@@ -156,15 +180,15 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin {
                        && !is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME))
                ) {
                        $folderNode = $this->userFolder->get($sabreNode->getPath());
-                       $children = $folderNode->getDirectoryListing();
 
+                       $childShares = $this->getSharesTypesInFolder($folderNode);
                        $this->cachedShareTypes[$folderNode->getId()] = $this->getShareTypes($folderNode);
-                       foreach ($children as $childNode) {
-                               $this->cachedShareTypes[$childNode->getId()] = $this->getShareTypes($childNode);
+                       foreach ($childShares as $id => $shares) {
+                               $this->cachedShareTypes[$id] = $shares;
                        }
                }
 
-               $propFind->handle(self::SHARETYPES_PROPERTYNAME, function() use ($sabreNode) {
+               $propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode) {
                        if (isset($this->cachedShareTypes[$sabreNode->getId()])) {
                                $shareTypes = $this->cachedShareTypes[$sabreNode->getId()];
                        } else {
index 433ef4ba63a72b8d016855ea755517dbe7e33878..2e17c7d0b384ecd40884cb25e9843321d1dc5629 100644 (file)
@@ -206,6 +206,14 @@ class SharesPluginTest extends \Test\TestCase {
                        ->method('get')
                        ->with('/subdir')
                        ->will($this->returnValue($node));
+               
+               $dummyShares = array_map(function($type) {
+                       $share = $this->getMock('\OCP\Share\IShare');
+                       $share->expects($this->any())
+                               ->method('getShareType')
+                               ->will($this->returnValue($type));
+                       return $share;
+               }, $shareTypes);
 
                $this->shareManager->expects($this->any())
                        ->method('getSharesBy')
@@ -224,6 +232,17 @@ class SharesPluginTest extends \Test\TestCase {
                                return [];
                        }));
 
+               $this->shareManager->expects($this->any())
+                       ->method('getSharesInFolder')
+                       ->with(
+                               $this->equalTo('user1'),
+                               $this->anything(),
+                               $this->equalTo(false)
+                       )
+                       ->will($this->returnCallback(function ($userId, $node, $flag) use ($shareTypes, $dummyShares) {
+                               return [111 => $dummyShares];
+                       }));
+
                // simulate sabre recursive PROPFIND traversal
                $propFindRoot = new \Sabre\DAV\PropFind(
                        '/subdir',
index c567b92c3e4f0972a7db4d3b2d1d032026be86c8..86204782d198024b10413301ef02b9b581d57485 100644 (file)
@@ -563,6 +563,11 @@ class FederatedShareProvider implements IShareProvider {
                return;
        }
 
+
+       public function getSharesInFolder($userId, $node, $reshares) {
+               return [];//TODO
+       }
+
        /**
         * @inheritdoc
         */
index 56b9d5b1ee85833dc3542e15ccefbd04ad070d30..2002e3bf8cbc6a815b3d14acbcaf0c68b7ad7b4f 100644 (file)
@@ -454,6 +454,49 @@ class DefaultShareProvider implements IShareProvider {
                return $share;
        }
 
+       public function getSharesInFolder($userId, $node, $reshares) {
+               $qb = $this->dbConn->getQueryBuilder();
+               $qb->select('*')
+                       ->from('share', 's')
+                       ->andWhere($qb->expr()->orX(
+                               $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
+                               $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
+                       ));
+
+               $qb->andWhere($qb->expr()->orX(
+                       $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)),
+                       $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP))
+               ));
+
+               /**
+                * 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))
+                               )
+                       );
+               }
+
+               $qb->innerJoin('s', 'filecache' ,'f', 's.file_source = f.fileid');
+               $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
+
+               $qb->orderBy('id');
+
+               $cursor = $qb->execute();
+               $shares = [];
+               while ($data = $cursor->fetch()) {
+                       $shares[$data['fileid']][] = $this->createShare($data);
+               }
+               $cursor->closeCursor();
+
+               return $shares;
+       }
+
        /**
         * @inheritdoc
         */
index 22cf5a3f65a4c935f4dc8e0048e2bc5817e3f795..f2f4acf8d00e0d9e400517688bfa71e70c54ff78 100644 (file)
@@ -34,6 +34,7 @@ use OCP\Files\File;
 use OCP\Files\Folder;
 use OCP\Files\IRootFolder;
 use OCP\Files\Mount\IMountManager;
+use OCP\Files\Node;
 use OCP\Files\NotFoundException;
 use OCP\IConfig;
 use OCP\IGroupManager;
@@ -48,6 +49,7 @@ use OCP\Share\IManager;
 use OCP\Share\IProviderFactory;
 use Symfony\Component\EventDispatcher\EventDispatcher;
 use Symfony\Component\EventDispatcher\GenericEvent;
+use OCP\Share\IShareProvider;
 
 /**
  * This class is the communication hub for all sharing related operations.
@@ -881,6 +883,14 @@ class Manager implements IManager {
                $provider->move($share, $recipientId);
        }
 
+       public function getSharesInFolder($userId, Node $node, $reshares = false) {
+               $providers = $this->factory->getAllProviders();
+
+               return array_reduce($providers, function($shares, IShareProvider $provider) use ($userId, $node, $reshares) {
+                       return $shares + $provider->getSharesInFolder($userId, $node, $reshares);
+               }, []);
+       }
+
        /**
         * @inheritdoc
         */
index e3de10a8aeee985e56f4ab6f6d2181406c89e23c..5cdc9a51a222c5849c7b81d06c39343e30c6fe6b 100644 (file)
@@ -163,4 +163,8 @@ class ProviderFactory implements IProviderFactory {
 
                return $provider;
        }
+
+       public function getAllProviders() {
+               return [$this->defaultShareProvider(), $this->federatedShareProvider()];
+       }
 }
index 37751911883c77258f2094557312cdf209e46eca..e8c69e06f9fd327df7fc53aa927f36cdb60a2b3d 100644 (file)
@@ -87,6 +87,17 @@ interface IManager {
         */
        public function moveShare(IShare $share, $recipientId);
 
+       /**
+        * Get all shares shared by (initiated) by the provided user in a folder.
+        *
+        * @param string $userId
+        * @param Node|null $node
+        * @param bool $reshares
+        * @return IShare[]
+        * @since 9.2.0
+        */
+       public function getSharesInFolder($userId, Node $node, $reshares = false);
+
        /**
         * Get shares shared by (initiated) by the provided user.
         *
index 8d9ea5bfdd0982259f0068f88d03561615fbefbb..928298a786047fe22c4f42de53bf889381ce275e 100644 (file)
@@ -55,4 +55,10 @@ interface IProviderFactory {
         * @since 9.0.0
         */
        public function getProviderForType($shareType);
+
+       /**
+        * @return IShareProvider[]
+        * @since 9.2.0
+        */
+       public function getAllProviders();
 }
index c4e116ac7fd3ef60a4ea4863db5fd76b5b196f75..db444d36935fa18233f424d1cc2bd99b707854b4 100644 (file)
@@ -91,6 +91,17 @@ interface IShareProvider {
         */
        public function move(\OCP\Share\IShare $share, $recipient);
 
+       /**
+        * Get all shares by the given user in a folder
+        *
+        * @param string $userId
+        * @param Node|null $node
+        * @param bool $reshares Also get the shares where $user is the owner instead of just the shares where $user is the initiator
+        * @return \OCP\Share\IShare[]
+        * @since 9.2.0
+        */
+       public function getSharesInFolder($userId, $node, $reshares);
+
        /**
         * Get all shares by the given user
         *
index 72ba4da6e5dd9366cbae3550f9f35f7c02e7ab16..7ed6c6ca153cc3d64ec5a5a82a334ff59d029758 100644 (file)
@@ -2564,4 +2564,13 @@ class DummyFactory implements IProviderFactory {
        public function getProviderForType($shareType) {
                return $this->provider;
        }
+
+       /**
+        * @return IShareProvider[]
+        */
+       public function getAllProviders() {
+               return [$this->provider];
+       }
+
+
 }