From 85601259fba4a336adff45e1a450a88fdfb63cc6 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Tue, 14 Mar 2017 19:18:20 +0100 Subject: [PATCH] Add LegacyHooks Use a helper class to listen to the eventDispatcher calls from the share manager to emit the old \OC_Hooks Signed-off-by: Roeland Jago Douma --- lib/private/Share20/LegacyHooks.php | 100 ++++++++++++ lib/private/Share20/Manager.php | 42 +---- tests/lib/Share20/LegacyHooksTest.php | 138 ++++++++++++++++ tests/lib/Share20/ManagerTest.php | 222 ++++++-------------------- 4 files changed, 292 insertions(+), 210 deletions(-) create mode 100644 lib/private/Share20/LegacyHooks.php create mode 100644 tests/lib/Share20/LegacyHooksTest.php diff --git a/lib/private/Share20/LegacyHooks.php b/lib/private/Share20/LegacyHooks.php new file mode 100644 index 0000000000..728ea78a8a --- /dev/null +++ b/lib/private/Share20/LegacyHooks.php @@ -0,0 +1,100 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OC\Share20; + +use OCP\Share\IShare; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\GenericEvent; + +class LegacyHooks { + /** @var EventDispatcher */ + private $eventDispatcher; + + /** + * LegacyHooks constructor. + * + * @param EventDispatcher $eventDispatcher + */ + public function __construct(EventDispatcher $eventDispatcher) { + $this->eventDispatcher = $eventDispatcher; + + $this->eventDispatcher->addListener('OCP\Share::preUnshare', [$this, 'preUnshare']); + $this->eventDispatcher->addListener('OCP\Share::postUnshare', [$this, 'postUnshare']); + } + + /** + * @param GenericEvent $e + */ + public function preUnshare(GenericEvent $e) { + /** @var IShare $share */ + $share = $e->getSubject(); + + $formatted = $this->formatHookParams($share); + \OC_Hook::emit('OCP\Share', 'pre_unshare', $formatted); + } + + /** + * @param GenericEvent $e + */ + public function postUnshare(GenericEvent $e) { + /** @var IShare $share */ + $share = $e->getSubject(); + + $formatted = $this->formatHookParams($share); + + /** @var IShare[] $deletedShares */ + $deletedShares = $e->getArgument('deletedShares'); + + $formattedDeletedShares = array_map(function($share) { + return $this->formatHookParams($share); + }, $deletedShares); + + $formatted['deletedShares'] = $formattedDeletedShares; + + \OC_Hook::emit('OCP\Share', 'pre_unshare', $formatted); + } + + private function formatHookParams(IShare $share) { + // Prepare hook + $shareType = $share->getShareType(); + $sharedWith = ''; + if ($shareType === \OCP\Share::SHARE_TYPE_USER || + $shareType === \OCP\Share::SHARE_TYPE_GROUP || + $shareType === \OCP\Share::SHARE_TYPE_REMOTE) { + $sharedWith = $share->getSharedWith(); + } + + $hookParams = [ + 'id' => $share->getId(), + 'itemType' => $share->getNodeType(), + 'itemSource' => $share->getNodeId(), + 'shareType' => $shareType, + 'shareWith' => $sharedWith, + 'itemparent' => method_exists($share, 'getParent') ? $share->getParent() : '', + 'uidOwner' => $share->getSharedBy(), + 'fileSource' => $share->getNodeId(), + 'fileTarget' => $share->getTarget() + ]; + return $hookParams; + } +} diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index d257b64bee..68842775ab 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -81,6 +81,8 @@ class Manager implements IManager { private $sharingDisabledForUsersCache; /** @var EventDispatcher */ private $eventDispatcher; + /** @var LegacyHooks */ + private $legacyHooks; /** @@ -123,6 +125,7 @@ class Manager implements IManager { $this->rootFolder = $rootFolder; $this->eventDispatcher = $eventDispatcher; $this->sharingDisabledForUsersCache = new CappedMemoryCache(); + $this->legacyHooks = new LegacyHooks($this->eventDispatcher); } /** @@ -806,37 +809,6 @@ class Manager implements IManager { $event = new GenericEvent($share); $this->eventDispatcher->dispatch('OCP\Share::preUnshare', $event); - $formatHookParams = function(\OCP\Share\IShare $share) { - // Prepare hook - $shareType = $share->getShareType(); - $sharedWith = ''; - if ($shareType === \OCP\Share::SHARE_TYPE_USER) { - $sharedWith = $share->getSharedWith(); - } else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) { - $sharedWith = $share->getSharedWith(); - } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) { - $sharedWith = $share->getSharedWith(); - } - - $hookParams = [ - 'id' => $share->getId(), - 'itemType' => $share->getNodeType(), - 'itemSource' => $share->getNodeId(), - 'shareType' => $shareType, - 'shareWith' => $sharedWith, - 'itemparent' => method_exists($share, 'getParent') ? $share->getParent() : '', - 'uidOwner' => $share->getSharedBy(), - 'fileSource' => $share->getNodeId(), - 'fileTarget' => $share->getTarget() - ]; - return $hookParams; - }; - - $hookParams = $formatHookParams($share); - - // Emit pre-hook - \OC_Hook::emit('OCP\Share', 'pre_unshare', $hookParams); - // Get all children and delete them as well $deletedShares = $this->deleteChildren($share); @@ -847,17 +819,9 @@ class Manager implements IManager { // All the deleted shares caused by this delete $deletedShares[] = $share; - //Format hook info - $formattedDeletedShares = array_map(function($share) use ($formatHookParams) { - return $formatHookParams($share); - }, $deletedShares); - - $hookParams['deletedShares'] = $formattedDeletedShares; - // Emit post hook $event->setArgument('deletedShares', $deletedShares); $this->eventDispatcher->dispatch('OCP\Share::postUnshare', $event); - \OC_Hook::emit('OCP\Share', 'post_unshare', $hookParams); } diff --git a/tests/lib/Share20/LegacyHooksTest.php b/tests/lib/Share20/LegacyHooksTest.php new file mode 100644 index 0000000000..d3a538f1d8 --- /dev/null +++ b/tests/lib/Share20/LegacyHooksTest.php @@ -0,0 +1,138 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace Test\Share20; + +use OC\Share20\LegacyHooks; +use OC\Share20\Manager; +use OCP\Files\File; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\GenericEvent; +use Test\TestCase; + +class LegacyHooksTest extends TestCase { + + /** @var LegacyHooks */ + private $hooks; + + /** @var EventDispatcher */ + private $eventDispatcher; + + /** @var Manager */ + private $manager; + + public function setUp() { + parent::setUp(); + + $this->eventDispatcher = new EventDispatcher(); + $this->hooks = new LegacyHooks($this->eventDispatcher); + $this->manager = \OC::$server->getShareManager(); + } + + public function testPreUnshare() { + $path = $this->createMock(File::class); + $path->method('getId')->willReturn(1); + + $share = $this->manager->newShare(); + $share->setId(42) + ->setProviderId('prov') + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith('awesomeUser') + ->setSharedBy('sharedBy') + ->setNode($path) + ->setTarget('myTarget'); + + $hookListner = $this->getMockBuilder('Dummy')->setMethods(['pre'])->getMock(); + \OCP\Util::connectHook('OCP\Share', 'pre_unshare', $hookListner, 'pre'); + + $hookListnerExpectsPre = [ + 'id' => 42, + 'itemType' => 'file', + 'itemSource' => 1, + 'shareType' => \OCP\Share::SHARE_TYPE_USER, + 'shareWith' => 'awesomeUser', + 'itemparent' => null, + 'uidOwner' => 'sharedBy', + 'fileSource' => 1, + 'fileTarget' => 'myTarget', + ]; + + $hookListner + ->expects($this->exactly(1)) + ->method('pre') + ->with($hookListnerExpectsPre); + + $event = new GenericEvent($share); + $this->eventDispatcher->dispatch('OCP\Share::preUnshare', $event); + } + + public function testPostUnshare() { + $path = $this->createMock(File::class); + $path->method('getId')->willReturn(1); + + $share = $this->manager->newShare(); + $share->setId(42) + ->setProviderId('prov') + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith('awesomeUser') + ->setSharedBy('sharedBy') + ->setNode($path) + ->setTarget('myTarget'); + + $hookListner = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); + \OCP\Util::connectHook('OCP\Share', 'pre_unshare', $hookListner, 'post'); + + $hookListnerExpectsPost = [ + 'id' => 42, + 'itemType' => 'file', + 'itemSource' => 1, + 'shareType' => \OCP\Share::SHARE_TYPE_USER, + 'shareWith' => 'awesomeUser', + 'itemparent' => null, + 'uidOwner' => 'sharedBy', + 'fileSource' => 1, + 'fileTarget' => 'myTarget', + 'deletedShares' => [ + [ + 'id' => 42, + 'itemType' => 'file', + 'itemSource' => 1, + 'shareType' => \OCP\Share::SHARE_TYPE_USER, + 'shareWith' => 'awesomeUser', + 'itemparent' => null, + 'uidOwner' => 'sharedBy', + 'fileSource' => 1, + 'fileTarget' => 'myTarget', + ], + ], + ]; + + $hookListner + ->expects($this->exactly(1)) + ->method('post') + ->with($hookListnerExpectsPost); + + $event = new GenericEvent($share); + $event->setArgument('deletedShares', [$share]); + $this->eventDispatcher->dispatch('OCP\Share::postUnshare', $event); + } +} diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php index 7b01a8f9e7..6fcf324dc5 100644 --- a/tests/lib/Share20/ManagerTest.php +++ b/tests/lib/Share20/ManagerTest.php @@ -196,56 +196,23 @@ class ManagerTest extends \Test\TestCase { ->method('delete') ->with($share); - $hookListner = $this->getMockBuilder('Dummy')->setMethods(['pre', 'post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'pre_unshare', $hookListner, 'pre'); - \OCP\Util::connectHook('OCP\Share', 'post_unshare', $hookListner, 'post'); - - $hookListnerExpectsPre = [ - 'id' => 42, - 'itemType' => 'file', - 'itemSource' => 1, - 'shareType' => $shareType, - 'shareWith' => $sharedWith, - 'itemparent' => null, - 'uidOwner' => 'sharedBy', - 'fileSource' => 1, - 'fileTarget' => 'myTarget', - ]; - - $hookListnerExpectsPost = [ - 'id' => 42, - 'itemType' => 'file', - 'itemSource' => 1, - 'shareType' => $shareType, - 'shareWith' => $sharedWith, - 'itemparent' => null, - 'uidOwner' => 'sharedBy', - 'fileSource' => 1, - 'fileTarget' => 'myTarget', - 'deletedShares' => [ - [ - 'id' => 42, - 'itemType' => 'file', - 'itemSource' => 1, - 'shareType' => $shareType, - 'shareWith' => $sharedWith, - 'itemparent' => null, - 'uidOwner' => 'sharedBy', - 'fileSource' => 1, - 'fileTarget' => 'myTarget', - ], - ], - ]; - - - $hookListner - ->expects($this->exactly(1)) - ->method('pre') - ->with($hookListnerExpectsPre); - $hookListner - ->expects($this->exactly(1)) - ->method('post') - ->with($hookListnerExpectsPost); + $this->eventDispatcher->expects($this->at(0)) + ->method('dispatch') + ->with( + 'OCP\Share::preUnshare', + $this->callBack(function(GenericEvent $e) use ($share) { + return $e->getSubject() === $share; + }) + ); + $this->eventDispatcher->expects($this->at(1)) + ->method('dispatch') + ->with( + 'OCP\Share::postUnshare', + $this->callBack(function(GenericEvent $e) use ($share) { + return $e->getSubject() === $share && + $e->getArgument('deletedShares') === [$share]; + }) + ); $manager->deleteShare($share); } @@ -275,56 +242,23 @@ class ManagerTest extends \Test\TestCase { ->method('delete') ->with($share); - $hookListner = $this->getMockBuilder('Dummy')->setMethods(['pre', 'post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'pre_unshare', $hookListner, 'pre'); - \OCP\Util::connectHook('OCP\Share', 'post_unshare', $hookListner, 'post'); - - $hookListnerExpectsPre = [ - 'id' => 42, - 'itemType' => 'file', - 'itemSource' => 1, - 'shareType' => \OCP\Share::SHARE_TYPE_USER, - 'shareWith' => 'sharedWith', - 'itemparent' => null, - 'uidOwner' => 'sharedBy', - 'fileSource' => 1, - 'fileTarget' => 'myTarget', - ]; - - $hookListnerExpectsPost = [ - 'id' => 42, - 'itemType' => 'file', - 'itemSource' => 1, - 'shareType' => \OCP\Share::SHARE_TYPE_USER, - 'shareWith' => 'sharedWith', - 'itemparent' => null, - 'uidOwner' => 'sharedBy', - 'fileSource' => 1, - 'fileTarget' => 'myTarget', - 'deletedShares' => [ - [ - 'id' => 42, - 'itemType' => 'file', - 'itemSource' => 1, - 'shareType' => \OCP\Share::SHARE_TYPE_USER, - 'shareWith' => 'sharedWith', - 'itemparent' => null, - 'uidOwner' => 'sharedBy', - 'fileSource' => 1, - 'fileTarget' => 'myTarget', - ], - ], - ]; - - - $hookListner - ->expects($this->exactly(1)) - ->method('pre') - ->with($hookListnerExpectsPre); - $hookListner - ->expects($this->exactly(1)) - ->method('post') - ->with($hookListnerExpectsPost); + $this->eventDispatcher->expects($this->at(0)) + ->method('dispatch') + ->with( + 'OCP\Share::preUnshare', + $this->callBack(function(GenericEvent $e) use ($share) { + return $e->getSubject() === $share; + }) + ); + $this->eventDispatcher->expects($this->at(1)) + ->method('dispatch') + ->with( + 'OCP\Share::postUnshare', + $this->callBack(function(GenericEvent $e) use ($share) { + return $e->getSubject() === $share && + $e->getArgument('deletedShares') === [$share]; + }) + ); $manager->deleteShare($share); } @@ -377,77 +311,23 @@ class ManagerTest extends \Test\TestCase { ->method('delete') ->withConsecutive($share3, $share2, $share1); - $hookListner = $this->getMockBuilder('Dummy')->setMethods(['pre', 'post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'pre_unshare', $hookListner, 'pre'); - \OCP\Util::connectHook('OCP\Share', 'post_unshare', $hookListner, 'post'); - - $hookListnerExpectsPre = [ - 'id' => 42, - 'itemType' => 'file', - 'itemSource' => 1, - 'shareType' => \OCP\Share::SHARE_TYPE_USER, - 'shareWith' => 'sharedWith1', - 'itemparent' => null, - 'uidOwner' => 'sharedBy1', - 'fileSource' => 1, - 'fileTarget' => 'myTarget1', - ]; - - $hookListnerExpectsPost = [ - 'id' => 42, - 'itemType' => 'file', - 'itemSource' => 1, - 'shareType' => \OCP\Share::SHARE_TYPE_USER, - 'shareWith' => 'sharedWith1', - 'itemparent' => null, - 'uidOwner' => 'sharedBy1', - 'fileSource' => 1, - 'fileTarget' => 'myTarget1', - 'deletedShares' => [ - [ - 'id' => 44, - 'itemType' => 'file', - 'itemSource' => 1, - 'shareType' => \OCP\Share::SHARE_TYPE_LINK, - 'shareWith' => '', - 'itemparent' => 43, - 'uidOwner' => 'sharedBy3', - 'fileSource' => 1, - 'fileTarget' => 'myTarget3', - ], - [ - 'id' => 43, - 'itemType' => 'file', - 'itemSource' => 1, - 'shareType' => \OCP\Share::SHARE_TYPE_GROUP, - 'shareWith' => 'sharedWith2', - 'itemparent' => 42, - 'uidOwner' => 'sharedBy2', - 'fileSource' => 1, - 'fileTarget' => 'myTarget2', - ], - [ - 'id' => 42, - 'itemType' => 'file', - 'itemSource' => 1, - 'shareType' => \OCP\Share::SHARE_TYPE_USER, - 'shareWith' => 'sharedWith1', - 'itemparent' => null, - 'uidOwner' => 'sharedBy1', - 'fileSource' => 1, - 'fileTarget' => 'myTarget1', - ], - ], - ]; - - $hookListner - ->expects($this->exactly(1)) - ->method('pre') - ->with($hookListnerExpectsPre); - $hookListner - ->expects($this->exactly(1)) - ->method('post') - ->with($hookListnerExpectsPost); + $this->eventDispatcher->expects($this->at(0)) + ->method('dispatch') + ->with( + 'OCP\Share::preUnshare', + $this->callBack(function(GenericEvent $e) use ($share1) { + return $e->getSubject() === $share1; + }) + ); + $this->eventDispatcher->expects($this->at(1)) + ->method('dispatch') + ->with( + 'OCP\Share::postUnshare', + $this->callBack(function(GenericEvent $e) use ($share1, $share2, $share3) { + return $e->getSubject() === $share1 && + $e->getArgument('deletedShares') === [$share3, $share2, $share1]; + }) + ); $manager->deleteShare($share1); }