]> source.dussan.org Git - nextcloud-server.git/commitdiff
[Share 2.0] Add share provider factory
authorRoeland Jago Douma <rullzer@owncloud.com>
Mon, 11 Jan 2016 09:30:03 +0000 (10:30 +0100)
committerRoeland Jago Douma <rullzer@owncloud.com>
Wed, 13 Jan 2016 15:35:14 +0000 (16:35 +0100)
* Add providers
* Add share manager to server container
* Use share manager from server container
* Properly get the share manager

apps/files_sharing/api/ocssharewrapper.php
config/config.sample.php
lib/private/server.php
lib/private/share20/defaultshareprovider.php
lib/private/share20/iproviderfactory.php [new file with mode: 0644]
lib/private/share20/ishareprovider.php
lib/private/share20/manager.php
lib/private/share20/providerfactory.php [new file with mode: 0644]
tests/lib/share20/managertest.php

index 7f909d413ee1d2b89d25ad5fb6305df9a882b625..a186a34cf6afbccf533eeba5633fc06df1e14696 100644 (file)
@@ -26,34 +26,8 @@ class OCSShareWrapper {
         * @return Share20OCS
         */
        private function getShare20OCS() {
-               $manager =new \OC\Share20\Manager(
-                       \OC::$server->getLogger(),
-                       \OC::$server->getConfig(),
-                       \OC::$server->getSecureRandom(),
-                       \OC::$server->getHasher(),
-                       \OC::$server->getMountManager(),
-                       \OC::$server->getGroupManager(),
-                       \OC::$server->getL10N('core')
-               );
-
-               $manager->registerProvider('ocdefault',
-                       [
-                               \OCP\Share::SHARE_TYPE_USER,
-                               \OCP\SHARE::SHARE_TYPE_GROUP,
-                               \OCP\SHARE::SHARE_TYPE_LINK
-                       ],
-                       function() {
-                               return new \OC\Share20\DefaultShareProvider(
-                                       \OC::$server->getDatabaseConnection(),
-                                       \OC::$server->getUserManager(),
-                                       \OC::$server->getGroupManager(),
-                                       \OC::$server->getRootFolder()
-                               );
-                       }
-                       );
-
                return new Share20OCS(
-                       $manager,
+                       \OC::$server->getShareManager(),
                        \OC::$server->getGroupManager(),
                        \OC::$server->getUserManager(),
                        \OC::$server->getRequest(),
index b0ede5cc6de6434e8621190ed372a160154a59d9..3dc1f4818c0aa66419bd9c0b74adc1b17c3d9c93 100644 (file)
@@ -975,6 +975,22 @@ $CONFIG = array(
        ),
 ),
 
+
+/**
+ * Sharing
+ *
+ * Global settings for Sharing
+ */
+
+/**
+ * Replaces the default Share Provider Factory. This can be utilized if
+ * own or 3rdParty Share Providers be used that – for instance – uses the
+ * filesystem instead of the database to keep the share information.
+ */
+'sharing.managerFactory' => '\OC\Share20\ProviderFactory',
+
+
+
 /**
  * All other config options
  */
index fe71b748e083faf8f8eb474bb139965948943608..79bd96652edcf452647c620eadbbaf67e68c3af0 100644 (file)
@@ -564,6 +564,25 @@ class Server extends ServerContainer implements IServerContainer {
                                $request
                        );
                });
+               $this->registerService('ShareManager', function(Server $c) {
+                       $config = $c->getConfig();
+                       $factoryClass = $config->getSystemValue('sharing.managerFactory', '\OC\Share20\ProviderFactory');
+                       /** @var \OC\Share20\IProviderFactory $factory */
+                       $factory = new $factoryClass();
+
+                       $manager = new \OC\Share20\Manager(
+                               $c->getLogger(),
+                               $c->getConfig(),
+                               $c->getSecureRandom(),
+                               $c->getHasher(),
+                               $c->getMountManager(),
+                               $c->getGroupManager(),
+                               $c->getL10N('core'),
+                               $factory
+                       );
+
+                       return $manager;
+               });
        }
 
        /**
@@ -1181,5 +1200,12 @@ class Server extends ServerContainer implements IServerContainer {
        public function getUserStoragesService() {
                return \OC_Mount_Config::$app->getContainer()->query('OCA\\Files_External\\Service\\UserStoragesService');
        }
-       
+
+
+       /**
+        * @return \OC\Share20\Manager
+        */
+       public function getShareManager() {
+               return $this->query('ShareManager');
+       }
 }
index adeaf2c44c9d46eb71044c6888afbc666bcd35d6..f961bc5202fc577b9c04cae7cc18a1939de7bf78 100644 (file)
@@ -62,6 +62,19 @@ class DefaultShareProvider implements IShareProvider {
                $this->rootFolder = $rootFolder;
        }
 
+       /**
+        * Return the share types this provider handles
+        *
+        * @return int[]
+        */
+       public function shareTypes() {
+               return [
+                       \OCP\Share::SHARE_TYPE_USER,
+                       \OCP\Share::SHARE_TYPE_GROUP,
+                       \OCP\Share::SHARE_TYPE_LINK,
+               ];
+       }
+
        /**
         * Share a path
         *
diff --git a/lib/private/share20/iproviderfactory.php b/lib/private/share20/iproviderfactory.php
new file mode 100644 (file)
index 0000000..0bbd304
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+/**
+ * @author Roeland Jago Douma <rullzer@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OC\Share20;
+
+/**
+ * Interface IProviderFactory
+ *
+ * @package OC\Share20
+ * @since 9.0.0
+ */
+interface IProviderFactory {
+
+       /**
+        * Creates and returns the shareProviders
+        *
+        * @return IShareProvider[]
+        * @since 9.0.0
+        */
+       public function getProviders();
+}
index ad3c22f43e34ea8dbe083fce227a80907b5da4ea..a7e9c59a97243cfaedaa44c76ff225944a31d123 100644 (file)
@@ -26,6 +26,13 @@ use OCP\IUser;
 
 interface IShareProvider {
 
+       /**
+        * Return the share types this provider handles
+        *
+        * @return int[]
+        */
+       public function shareTypes();
+
        /**
         * Share a path
         * 
index d9014e64dcfb29daecb2ce3e547cac4155f6bdfc..e35b69f0031458c823172f6b898d37032c25e32a 100644 (file)
@@ -41,7 +41,10 @@ use OC\HintException;
  */
 class Manager {
 
-       /** @var array */
+       /** @var IProviderFactory */
+       private $factory;
+
+       /** @var IShareProvider[] */
        private $providers;
 
        /** @var array */
@@ -78,6 +81,7 @@ class Manager {
         * @param IMountManager $mountManager
         * @param IGroupManager $groupManager
         * @param IL10N $l
+        * @param IProviderFactory $factory
         */
        public function __construct(
                        ILogger $logger,
@@ -86,7 +90,8 @@ class Manager {
                        IHasher $hasher,
                        IMountManager $mountManager,
                        IGroupManager $groupManager,
-                       IL10N $l
+                       IL10N $l,
+                       IProviderFactory $factory
        ) {
                $this->providers = [];
                $this->type2provider = [];
@@ -98,82 +103,64 @@ class Manager {
                $this->mountManager = $mountManager;
                $this->groupManager = $groupManager;
                $this->l = $l;
+               $this->factory = $factory;
        }
 
        /**
-        * Register a share provider
-        *
-        * @param string $id The id of the share provider
-        * @param int[] $shareTypes Array containing the share types this provider handles
-        * @param callable $callback Callback that must return an IShareProvider instance
+        * @param IShareProvider[] $providers
         * @throws ProviderException
         */
-       public function registerProvider($id, $shareTypes, callable $callback) {
-               // Providers must have an unique id
-               if (isset($this->providers[$id])) {
-                       throw new ProviderException('A share provider with the id \''. $id . '\' is already registered');
-               }
+       private function addProviders(array $providers) {
+               foreach ($providers as $provider) {
+                       $name = get_class($provider);
 
-               if ($shareTypes === []) {
-                       throw new ProviderException('shareTypes can\'t be an empty array');
-               }
+                       if (!($provider instanceof IShareProvider)) {
+                               throw new ProviderException($name . ' is not an instance of IShareProvider');
+                       }
 
-               foreach($shareTypes as $shareType) {
-                       // We only have 1 provder per share type
-                       if (isset($this->type2provider[$shareType])) {
-                               throw new ProviderException('The share provider ' . $this->type2provider[$shareType] . ' is already registered for share type ' . $shareType);
+                       if (isset($this->providers[$name])) {
+                               throw new ProviderException($name . ' is already registered');
                        }
 
-                       /*
-                        * We only allow providers that provider
-                        * user- / group- / link- / federated-shares
-                        */
-                       if ($shareType !== \OCP\Share::SHARE_TYPE_USER &&
-                               $shareType !== \OCP\Share::SHARE_TYPE_GROUP &&
-                               $shareType !== \OCP\Share::SHARE_TYPE_LINK &&
-                               $shareType !== \OCP\Share::SHARE_TYPE_REMOTE) {
-                               throw new ProviderException('Cannot register provider for share type ' . $shareType);
-                               //Throw exception
+                       $this->providers[$name] = $provider;
+                       $types = $provider->shareTypes();
+
+                       if ($types === []) {
+                               throw new ProviderException('Provider ' . $name . ' must supply share types it can handle');
                        }
-               }
 
-               // Add the provider
-               $this->providers[$id] = [
-                       'id' => $id,
-                       'callback' => $callback,
-                       'provider' => null,
-                       'shareTypes' => $shareTypes,
-               ];
+                       foreach ($types as $type) {
+                               if (isset($this->type2provider[$type])) {
+                                       throw new ProviderException($name . ' tried to register for share type ' . $type . ' but this type is already handled by ' . $this->type2provider[$type]);
+                               }
 
-               // Update the type mapping
-               foreach ($shareTypes as $shareType) {
-                       $this->type2provider[$shareType] = $id;
+                               $this->type2provider[$type] = $name;
+                       }
                }
        }
 
+       private function runFactory() {
+               if (!empty($this->providers)) {
+                       return;
+               }
+
+               $this->addProviders($this->factory->getProviders());
+               $this->factoryDone = true;
+       }
+
        /**
         * @param string $id
         * @return IShareProvider
         * @throws ProviderException
         */
        private function getProvider($id) {
+               $this->runFactory();
+
                if (!isset($this->providers[$id])) {
                        throw new ProviderException('No provider with id ' . $id . ' found');
                }
 
-               if ($this->providers[$id]['provider'] === null) {
-                       // First time using this provider
-                       $provider = call_user_func($this->providers[$id]['callback']);
-
-                       // Make sure a proper provider is returned
-                       if (!($provider instanceof IShareProvider)) {
-                               throw new ProviderException('Callback does not return an IShareProvider instance for provider with id ' . $id);
-                       }
-
-                       $this->providers[$id]['provider'] = $provider;
-               }
-
-               return $this->providers[$id]['provider'];
+               return $this->providers[$id];
        }
 
        /**
@@ -182,6 +169,8 @@ class Manager {
         * @throws ProviderException
         */
        private function getProviderForType($shareType) {
+               $this->runFactory();
+
                if (!isset($this->type2provider[$shareType])) {
                        throw new ProviderException('No share provider registered for share type ' . $shareType);
                }
@@ -189,6 +178,15 @@ class Manager {
                return $this->getProvider($this->type2provider[$shareType]);
        }
 
+       /**
+        * @return IShareProvider[]
+        */
+       private function getProviders() {
+               $this->runFactory();
+
+               return $this->providers;
+       }
+
        /**
         * Verify if a password meets all requirements
         *
@@ -587,10 +585,9 @@ class Manager {
        protected function deleteChildren(IShare $share) {
                $deletedShares = [];
 
-               $providerIds = array_keys($this->providers);
+               $providers = $this->getProviders();
 
-               foreach($providerIds as $providerId) {
-                       $provider = $this->getProvider($providerId);
+               foreach($providers as $provider) {
                        foreach ($provider->getChildren($share) as $child) {
                                $deletedChildren = $this->deleteChildren($child);
                                $deletedShares = array_merge($deletedShares, $deletedChildren);
@@ -691,12 +688,10 @@ class Manager {
 
                //FIXME ids need to become proper providerid:shareid eventually
 
-               $providerIds = array_keys($this->providers);
+               $providers = $this->getProviders();
 
                $share = null;
-               foreach ($providerIds as $providerId) {
-                       $provider = $this->getProvider($providerId);
-
+               foreach ($providers as $provider) {
                        try {
                                $share = $provider->getShareById($id);
                                $found = true;
diff --git a/lib/private/share20/providerfactory.php b/lib/private/share20/providerfactory.php
new file mode 100644 (file)
index 0000000..55ba2aa
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+/**
+ * @author Roeland Jago Douma <rullzer@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OC\Share20;
+
+/**
+ * Class ProviderFactory
+ *
+ * @package OC\Share20
+ */
+class ProviderFactory implements IProviderFactory {
+
+       /**
+        * Create the default share provider.
+        *
+        * @return DefaultShareProvider
+        */
+       protected function defaultShareProvider() {
+               return new DefaultShareProvider(
+                       \OC::$server->getDatabaseConnection(),
+                       \OC::$server->getUserManager(),
+                       \OC::$server->getGroupManager(),
+                       \OC::$server->getRootFolder()
+               );
+       }
+
+       /**
+        * @inheritdoc
+        */
+       public function getProviders() {
+               $providers = [];
+
+               $providers[] = $this->defaultShareProvider();
+
+               return $providers;
+       }
+}
index a83da1187c5ec973a747505f829280359023a6f2..dd1028c78b477d2310be2e5b443d73fad670b8a0 100644 (file)
@@ -20,6 +20,7 @@
  */
 namespace Test\Share20;
 
+use OC\Share20\IProviderFactory;
 use OC\Share20\Manager;
 use OC\Share20\Exception;
 
@@ -67,11 +68,16 @@ class ManagerTest extends \Test\TestCase {
        /** @var IL10N */
        protected $l;
 
+       /** @var IProviderFactory */
+       protected $factory;
+
        public function setUp() {
                
                $this->logger = $this->getMock('\OCP\ILogger');
                $this->config = $this->getMock('\OCP\IConfig');
-               $this->defaultProvider = $this->getMock('\OC\Share20\IShareProvider');
+               $this->defaultProvider = $this->getMockBuilder('\OC\Share20\IShareProvider')
+                       ->setMockClassName('DefaultShareProvider')
+                       ->getMock();
                $this->secureRandom = $this->getMock('\OCP\Security\ISecureRandom');
                $this->hasher = $this->getMock('\OCP\Security\IHasher');
                $this->mountManager = $this->getMock('\OCP\Files\Mount\IMountManager');
@@ -83,6 +89,8 @@ class ManagerTest extends \Test\TestCase {
                                return vsprintf($text, $parameters);
                        }));
 
+               $this->factory = $this->getMock('\OC\Share20\IProviderFactory');
+
                $this->manager = new Manager(
                        $this->logger,
                        $this->config,
@@ -90,24 +98,73 @@ class ManagerTest extends \Test\TestCase {
                        $this->hasher,
                        $this->mountManager,
                        $this->groupManager,
-                       $this->l
+                       $this->l,
+                       $this->factory
                );
-               $this->manager->registerProvider('tmp',
-                       [
-                               \OCP\SHARE::SHARE_TYPE_USER,
+
+               $this->defaultProvider
+                       ->method('shareTypes')
+                       ->willReturn([
+                               \OCP\Share::SHARE_TYPE_USER,
                                \OCP\Share::SHARE_TYPE_GROUP,
-                               \OCP\Share::SHARE_TYPE_LINK
-                       ],
-                       function() {
-                               return $this->defaultProvider;
-                       }
-               );
+                               \OCP\Share::SHARE_TYPE_LINK,
+                       ]);
+       }
+
+       /**
+        * @return \PHPUnit_Framework_MockObject_MockBuilder
+        */
+       private function createManagerMock() {
+               return  $this->getMockBuilder('\OC\Share20\Manager')
+                       ->setConstructorArgs([
+                               $this->logger,
+                               $this->config,
+                               $this->secureRandom,
+                               $this->hasher,
+                               $this->mountManager,
+                               $this->groupManager,
+                               $this->l,
+                               $this->factory
+                       ]);
+       }
+
+       /**
+        * Initialise the factory. If $providers is null add the defaultProvider
+        * @param array $providers
+        */
+       private function factoryProviders(array $providers = null) {
+               if ($providers === null) {
+                       $this->factory->method('getProviders')->willReturn([$this->defaultProvider]);
+               } else {
+                       $this->factory->method('getProviders')->willReturn($providers);
+               }
+       }
+
+       /**
+        * @param int[] $shareTypes Share types for this provider
+        * @param string|null $name The name of this provider
+        * @return \PHPUnit_Framework_MockObject_MockObject|IShareProvider
+        */
+       private function createShareProvider(array $shareTypes, $name = null) {
+               $provider = $this->getMockBuilder('\OC\Share20\IShareProvider');
+
+               if ($name !== null) {
+                       $provider->setMockClassName($name);
+               }
+
+               $provider = $provider->getMock();
+
+               $provider->method('shareTypes')->willReturn($shareTypes);
+
+               return $provider;
        }
 
        /**
         * @expectedException \OC\Share20\Exception\ShareNotFound
         */
        public function testDeleteNoShareId() {
+               $this->factoryProviders();
+
                $share = $this->getMock('\OC\Share20\IShare');
 
                $share
@@ -138,25 +195,17 @@ class ManagerTest extends \Test\TestCase {
         * @dataProvider dataTestDelete
         */
        public function testDelete($shareType, $sharedWith, $sharedWith_string) {
-               $manager = $this->getMockBuilder('\OC\Share20\Manager')
-                       ->setConstructorArgs([
-                               $this->logger,
-                               $this->config,
-                               $this->secureRandom,
-                               $this->hasher,
-                               $this->mountManager,
-                               $this->groupManager,
-                               $this->l
-                       ])
+               $manager = $this->createManagerMock()
                        ->setMethods(['getShareById', 'deleteChildren'])
                        ->getMock();
 
-               $manager->registerProvider('tmp',
-                       [$shareType],
-                       function() {
-                               return $this->defaultProvider;
-                       }
-               );
+               $provider = $this->createShareProvider([
+                       \OCP\Share::SHARE_TYPE_USER,
+                       \OCP\Share::SHARE_TYPE_GROUP,
+                       \OCP\Share::SHARE_TYPE_LINK,
+                       \OCP\Share::SHARE_TYPE_REMOTE,
+               ]);
+               $this->factoryProviders([$provider]);
 
                $sharedBy = $this->getMock('\OCP\IUser');
                $sharedBy->method('getUID')->willReturn('sharedBy');
@@ -175,7 +224,7 @@ class ManagerTest extends \Test\TestCase {
                $manager->expects($this->once())->method('getShareById')->with(42)->willReturn($share);
                $manager->expects($this->once())->method('deleteChildren')->with($share);
 
-               $this->defaultProvider
+               $provider
                        ->expects($this->once())
                        ->method('delete')
                        ->with($share);
@@ -235,27 +284,12 @@ class ManagerTest extends \Test\TestCase {
        }
 
        public function testDeleteNested() {
-               $manager = $this->getMockBuilder('\OC\Share20\Manager')
-                       ->setConstructorArgs([
-                               $this->logger,
-                               $this->config,
-                               $this->secureRandom,
-                               $this->hasher,
-                               $this->mountManager,
-                               $this->groupManager,
-                               $this->l,
-                       ])
+               $manager = $this->createManagerMock()
                        ->setMethods(['getShareById'])
                        ->getMock();
 
-               $manager->registerProvider('tmp',
-                       [
-                               \OCP\Share::SHARE_TYPE_USER
-                       ],
-                       function() {
-                               return $this->defaultProvider;
-                       }
-               );
+               $provider = $this->createShareProvider([\OCP\Share::SHARE_TYPE_USER]);
+               $this->factoryProviders([$provider]);
 
                $sharedBy1 = $this->getMock('\OCP\IUser');
                $sharedBy1->method('getUID')->willReturn('sharedBy1');
@@ -299,7 +333,7 @@ class ManagerTest extends \Test\TestCase {
 
                $manager->expects($this->once())->method('getShareById')->with(42)->willReturn($share1);
 
-               $this->defaultProvider
+               $provider
                        ->method('getChildren')
                        ->will($this->returnValueMap([
                                [$share1, [$share2]],
@@ -388,25 +422,12 @@ class ManagerTest extends \Test\TestCase {
        }
 
        public function testDeleteChildren() {
-               $manager = $this->getMockBuilder('\OC\Share20\Manager')
-                       ->setConstructorArgs([
-                               $this->logger,
-                               $this->config,
-                               $this->secureRandom,
-                               $this->hasher,
-                               $this->mountManager,
-                               $this->groupManager,
-                               $this->l,
-                       ])
+               $manager = $this->createManagerMock()
                        ->setMethods(['deleteShare'])
                        ->getMock();
 
-               $manager->registerProvider('tmp',
-                       [\OCP\Share::SHARE_TYPE_USER],
-                       function() {
-                               return $this->defaultProvider;
-                       }
-               );
+               $provider = $this->createShareProvider([\OCP\Share::SHARE_TYPE_USER]);
+               $this->factoryProviders([$provider]);
 
                $share = $this->getMock('\OC\Share20\IShare');
 
@@ -420,7 +441,7 @@ class ManagerTest extends \Test\TestCase {
                        $child3,
                ];
 
-               $this->defaultProvider
+               $provider
                        ->expects($this->exactly(4))
                        ->method('getChildren')
                        ->will($this->returnCallback(function($_share) use ($share, $shares) {
@@ -430,7 +451,7 @@ class ManagerTest extends \Test\TestCase {
                                return [];
                        }));
 
-               $this->defaultProvider
+               $provider
                        ->expects($this->exactly(3))
                        ->method('delete')
                        ->withConsecutive($child1, $child2, $child3);
@@ -440,6 +461,8 @@ class ManagerTest extends \Test\TestCase {
        }
 
        public function testGetShareById() {
+               $this->factoryProviders();
+
                $share = $this->getMock('\OC\Share20\IShare');
 
                $this->defaultProvider
@@ -771,6 +794,8 @@ class ManagerTest extends \Test\TestCase {
                        ->with($path)
                        ->willReturn([]);
 
+               $this->factoryProviders();
+
                $this->invokePrivate($this->manager, 'userCreateChecks', [$share]);
        }
 
@@ -792,6 +817,8 @@ class ManagerTest extends \Test\TestCase {
                        ->with($path)
                        ->willReturn([$share]);
 
+               $this->factoryProviders();
+
                $this->invokePrivate($this->manager, 'userCreateChecks', [$share]);
        }
 
@@ -825,6 +852,8 @@ class ManagerTest extends \Test\TestCase {
                        ->with($path)
                        ->willReturn([$share2]);
 
+               $this->factoryProviders();
+
                $this->invokePrivate($this->manager, 'userCreateChecks', [$share]);
        }
 
@@ -854,10 +883,11 @@ class ManagerTest extends \Test\TestCase {
                        ->with($path)
                        ->willReturn([$share2]);
 
+               $this->factoryProviders();
+
                $this->invokePrivate($this->manager, 'userCreateChecks', [$share]);
        }
 
-
        /**
         * @expectedException Exception
         * @expectedExceptionMessage Only sharing within your own groups is allowed
@@ -902,6 +932,7 @@ class ManagerTest extends \Test\TestCase {
                                ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
                        ]));
 
+               $this->factoryProviders();
                $this->invokePrivate($this->manager, 'groupCreateChecks', [$share]);
        }
 
@@ -925,6 +956,7 @@ class ManagerTest extends \Test\TestCase {
                        ->with($path)
                        ->willReturn([$share2]);
 
+               $this->factoryProviders();
                $this->invokePrivate($this->manager, 'groupCreateChecks', [$share]);
        }
 
@@ -945,6 +977,8 @@ class ManagerTest extends \Test\TestCase {
                        ->with($path)
                        ->willReturn([$share2]);
 
+               $this->factoryProviders();
+
                $this->invokePrivate($this->manager, 'groupCreateChecks', [$share]);
        }
 
@@ -1019,7 +1053,6 @@ class ManagerTest extends \Test\TestCase {
                $this->invokePrivate($this->manager, 'linkCreateChecks', [$share]);
        }
 
-
        public function testLinkCreateChecksPublicUpload() {
                $share = new \OC\Share20\Share();
 
@@ -1181,16 +1214,7 @@ class ManagerTest extends \Test\TestCase {
                                ['core', 'shareapi_enabled', 'yes', $sharingEnabled],
                        ]));
 
-               $manager = $this->getMockBuilder('\OC\Share20\Manager')
-                       ->setConstructorArgs([
-                               $this->logger,
-                               $this->config,
-                               $this->secureRandom,
-                               $this->hasher,
-                               $this->mountManager,
-                               $this->groupManager,
-                               $this->l,
-                       ])
+               $manager = $this->createManagerMock()
                        ->setMethods(['isSharingDisabledForUser'])
                        ->getMock();
 
@@ -1209,16 +1233,7 @@ class ManagerTest extends \Test\TestCase {
         * @expectedExceptionMessage The Share API is disabled
         */
        public function testCreateShareCantShare() {
-               $manager = $this->getMockBuilder('\OC\Share20\Manager')
-                       ->setConstructorArgs([
-                               $this->logger,
-                               $this->config,
-                               $this->secureRandom,
-                               $this->hasher,
-                               $this->mountManager,
-                               $this->groupManager,
-                               $this->l,
-                       ])
+               $manager = $this->createManagerMock()
                        ->setMethods(['canShare'])
                        ->getMock();
 
@@ -1228,25 +1243,12 @@ class ManagerTest extends \Test\TestCase {
        }
 
        public function testCreateShareUser() {
-               $manager = $this->getMockBuilder('\OC\Share20\Manager')
-                       ->setConstructorArgs([
-                               $this->logger,
-                               $this->config,
-                               $this->secureRandom,
-                               $this->hasher,
-                               $this->mountManager,
-                               $this->groupManager,
-                               $this->l,
-                       ])
+               $manager = $this->createManagerMock()
                        ->setMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
                        ->getMock();
 
-               $manager->registerProvider('tmp',
-                       [\OCP\Share::SHARE_TYPE_USER],
-                       function() {
-                               return $this->defaultProvider;
-                       }
-               );
+               $provider = $this->createShareProvider([\OCP\Share::SHARE_TYPE_USER]);
+               $this->factoryProviders([$provider]);
 
                $sharedWith = $this->getMock('\OCP\IUser');
                $sharedBy = $this->getMock('\OCP\IUser');
@@ -1279,7 +1281,7 @@ class ManagerTest extends \Test\TestCase {
                        ->method('pathCreateChecks')
                        ->with($path);
 
-               $this->defaultProvider
+               $provider
                        ->expects($this->once())
                        ->method('create')
                        ->with($share)
@@ -1296,25 +1298,12 @@ class ManagerTest extends \Test\TestCase {
        }
 
        public function testCreateShareGroup() {
-               $manager = $this->getMockBuilder('\OC\Share20\Manager')
-                       ->setConstructorArgs([
-                               $this->logger,
-                               $this->config,
-                               $this->secureRandom,
-                               $this->hasher,
-                               $this->mountManager,
-                               $this->groupManager,
-                               $this->l,
-                       ])
+               $manager = $this->createManagerMock()
                        ->setMethods(['canShare', 'generalCreateChecks', 'groupCreateChecks', 'pathCreateChecks'])
                        ->getMock();
 
-               $manager->registerProvider('tmp',
-                       [\OCP\Share::SHARE_TYPE_GROUP],
-                       function() {
-                               return $this->defaultProvider;
-                       }
-               );
+               $provider = $this->createShareProvider([\OCP\Share::SHARE_TYPE_GROUP]);
+               $this->factoryProviders([$provider]);
 
                $sharedWith = $this->getMock('\OCP\IGroup');
                $sharedBy = $this->getMock('\OCP\IUser');
@@ -1347,7 +1336,7 @@ class ManagerTest extends \Test\TestCase {
                        ->method('pathCreateChecks')
                        ->with($path);
 
-               $this->defaultProvider
+               $provider
                        ->expects($this->once())
                        ->method('create')
                        ->with($share)
@@ -1364,17 +1353,7 @@ class ManagerTest extends \Test\TestCase {
        }
 
        public function testCreateShareLink() {
-               $manager = $this->getMockBuilder('\OC\Share20\Manager')
-                       ->setConstructorArgs([
-                               $this->logger,
-                               $this->config,
-
-                               $this->secureRandom,
-                               $this->hasher,
-                               $this->mountManager,
-                               $this->groupManager,
-                               $this->l,
-                       ])
+               $manager = $this->createManagerMock()
                        ->setMethods([
                                'canShare',
                                'generalCreateChecks',
@@ -1385,12 +1364,8 @@ class ManagerTest extends \Test\TestCase {
                        ])
                        ->getMock();
 
-               $manager->registerProvider('tmp',
-                       [\OCP\Share::SHARE_TYPE_LINK],
-                       function() {
-                               return $this->defaultProvider;
-                       }
-               );
+               $provider = $this->createShareProvider([\OCP\Share::SHARE_TYPE_LINK]);
+               $this->factoryProviders([$provider]);
 
                $sharedBy = $this->getMock('\OCP\IUser');
                $sharedBy->method('getUID')->willReturn('sharedBy');
@@ -1445,7 +1420,7 @@ class ManagerTest extends \Test\TestCase {
                $this->secureRandom->method('generate')
                        ->willReturn('token');
 
-               $this->defaultProvider
+               $provider
                        ->expects($this->once())
                        ->method('create')
                        ->with($share)
@@ -1512,16 +1487,7 @@ class ManagerTest extends \Test\TestCase {
         * @expectedExceptionMessage I won't let you share
         */
        public function testCreateShareHookError() {
-               $manager = $this->getMockBuilder('\OC\Share20\Manager')
-                       ->setConstructorArgs([
-                               $this->logger,
-                               $this->config,
-                               $this->secureRandom,
-                               $this->hasher,
-                               $this->mountManager,
-                               $this->groupManager,
-                               $this->l,
-                       ])
+               $manager = $this->createManagerMock()
                        ->setMethods([
                                'canShare',
                                'generalCreateChecks',
@@ -1530,12 +1496,8 @@ class ManagerTest extends \Test\TestCase {
                        ])
                        ->getMock();
 
-               $manager->registerProvider('tmp',
-                       [\OCP\Share::SHARE_TYPE_USER],
-                       function() {
-                               return $this->defaultProvider;
-                       }
-               );
+               $provider = $this->createShareProvider([\OCP\Share::SHARE_TYPE_USER]);
+               $this->factoryProviders([$provider]);
 
                $sharedWith = $this->getMock('\OCP\IUser');
                $sharedBy = $this->getMock('\OCP\IUser');
@@ -1545,8 +1507,6 @@ class ManagerTest extends \Test\TestCase {
                $path->method('getOwner')->willReturn($shareOwner);
                $path->method('getName')->willReturn('target');
 
-               $date = new \DateTime();
-
                $share = $this->createShare(
                        null,
                        \OCP\Share::SHARE_TYPE_USER,
@@ -1609,94 +1569,46 @@ class ManagerTest extends \Test\TestCase {
         * @param int[] $shareTypes
         */
        public function testRegisterProvider($shareTypes) {
-               $manager = new Manager(
-                               $this->logger,
-                               $this->config,
-                               $this->secureRandom,
-                               $this->hasher,
-                               $this->mountManager,
-                               $this->groupManager,
-                               $this->l
-               );
+               $provider = $this->createShareProvider($shareTypes);
+               $this->factoryProviders([$provider]);
 
-               $provider = $this->getMock('OC\Share20\IShareProvider');
-               $manager->registerProvider('foo', $shareTypes, function() use ($provider) {
-                       return $provider;
-               });
+               $name = get_class($provider);
 
-               $this->assertEquals($provider, $this->invokePrivate($manager, 'getProvider', ['foo']));
+               $this->assertEquals($provider, $this->invokePrivate($this->manager, 'getProvider', [$name]));
                foreach ($shareTypes as $shareType) {
-                       $this->assertEquals($provider, $this->invokePrivate($manager, 'getProviderForType', [$shareType]));
+                       $this->assertEquals($provider, $this->invokePrivate($this->manager, 'getProviderForType', [$shareType]));
                }
        }
 
        /**
         * @expectedException \OC\Share20\Exception\ProviderException
-        * @expectedExceptionMessage A share provider with the id 'foo' is already registered
+        * @expectedExceptionMessage ShareProvider is already registered
         */
        public function testRegisterProviderDuplicateId() {
-               $manager = new Manager(
-                       $this->logger,
-                       $this->config,
-                       $this->secureRandom,
-                       $this->hasher,
-                       $this->mountManager,
-                       $this->groupManager,
-                       $this->l
-               );
-
-               $provider = $this->getMock('OC\Share20\IShareProvider');
-               $manager->registerProvider('foo', [\OCP\Share::SHARE_TYPE_USER], function() use ($provider) {
-                       return $provider;
-               });
-               $manager->registerProvider('foo', [\OCP\Share::SHARE_TYPE_USER], function() use ($provider) {
-                       return $provider;
-               });
+               $provider = $this->createShareProvider([\OCP\Share::SHARE_TYPE_USER], 'ShareProvider');
+               $this->factoryProviders([$provider, $provider]);
+               $this->invokePrivate($this->manager, 'runFactory', []);
        }
 
        /**
         * @expectedException \OC\Share20\Exception\ProviderException
-        * @expectedExceptionMessage shareTypes can't be an empty array
+        * @expectedExceptionMessage Provider ShareProvider must supply share types it can handle
         */
        public function testRegisterProviderEmptyShareTypes() {
-               $manager = new Manager(
-                       $this->logger,
-                       $this->config,
-                       $this->secureRandom,
-                       $this->hasher,
-                       $this->mountManager,
-                       $this->groupManager,
-                       $this->l
-               );
-
-               $provider = $this->getMock('OC\Share20\IShareProvider');
-               $manager->registerProvider('foo', [], function() use ($provider) {
-                       return $provider;
-               });
+               $provider = $this->createShareProvider([], 'ShareProvider');
+               $this->factoryProviders([$provider]);
+               $this->invokePrivate($this->manager, 'runFactory', []);
        }
 
        /**
         * @expectedException \OC\Share20\Exception\ProviderException
-        * @expectedExceptionMessage The share provider foo is already registered for share type 0
+        * @expectedExceptionMessage  shareProvider2 tried to register for share type 0 but this type is already handled by shareProvider1
         */
        public function testRegisterProviderSameType() {
-               $manager = new Manager(
-                       $this->logger,
-                       $this->config,
-                       $this->secureRandom,
-                       $this->hasher,
-                       $this->mountManager,
-                       $this->groupManager,
-                       $this->l
-               );
-
-               $provider = $this->getMock('OC\Share20\IShareProvider');
-               $manager->registerProvider('foo', [\OCP\Share::SHARE_TYPE_USER], function() use ($provider) {
-                       return $provider;
-               });
-               $manager->registerProvider('bar', [\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP], function() use ($provider) {
-                       return $provider;
-               });
+               $provider1 = $this->createShareProvider([\OCP\Share::SHARE_TYPE_USER], 'shareProvider1');
+               $provider2 = $this->createShareProvider([\OCP\Share::SHARE_TYPE_USER], 'shareProvider2');
+               $this->factoryProviders([$provider1, $provider2]);
+               $this->invokePrivate($this->manager, 'runFactory', []);
        }
 
        /**
@@ -1704,39 +1616,8 @@ class ManagerTest extends \Test\TestCase {
         * @expectedExceptionMessage No provider with id foo found
         */
        public function testGetProviderNoProviderWithId() {
-               $manager = new Manager(
-                       $this->logger,
-                       $this->config,
-                       $this->secureRandom,
-                       $this->hasher,
-                       $this->mountManager,
-                       $this->groupManager,
-                       $this->l
-               );
-
-               $this->invokePrivate($manager, 'getProvider', ['foo']);
-       }
-
-       /**
-        * @expectedException \OC\Share20\Exception\ProviderException
-        * @expectedExceptionMessage Callback does not return an IShareProvider instance for provider with id foo
-        */
-       public function testGetProviderNoIShareProvider() {
-               $manager = new Manager(
-                       $this->logger,
-                       $this->config,
-                       $this->secureRandom,
-                       $this->hasher,
-                       $this->mountManager,
-                       $this->groupManager,
-                       $this->l
-               );
-
-               $provider = $this->getMock('OC\Share20\IShare');
-               $manager->registerProvider('foo', [\OCP\Share::SHARE_TYPE_USER], function() use ($provider) {
-                       return $provider;
-               });
-               $this->invokePrivate($manager, 'getProvider', ['foo']);
+               $this->factoryProviders([]);
+               $this->invokePrivate($this->manager, 'getProvider', ['foo']);
        }
 
        /**
@@ -1744,21 +1625,9 @@ class ManagerTest extends \Test\TestCase {
         * @expectedExceptionMessage No share provider registered for share type 1
         */
        public function testGetProviderForTypeUnkownType() {
-               $manager = new Manager(
-                       $this->logger,
-                       $this->config,
-                       $this->secureRandom,
-                       $this->hasher,
-                       $this->mountManager,
-                       $this->groupManager,
-                       $this->l
-               );
-
-               $provider = $this->getMock('OC\Share20\IShareProvider');
-               $manager->registerProvider('foo', [\OCP\Share::SHARE_TYPE_USER], function() use ($provider) {
-                       return $provider;
-               });
-               $this->invokePrivate($manager, 'getProviderForType', [\OCP\SHARE::SHARE_TYPE_GROUP]);
+               $provider = $this->createShareProvider([\OCP\Share::SHARE_TYPE_USER]);
+               $this->factoryProviders([$provider]);
+               $this->invokePrivate($this->manager, 'getProviderForType', [\OCP\SHARE::SHARE_TYPE_GROUP]);
        }
 }