Signed-off-by: Joas Schilling <coding@schilljs.com>tags/v28.0.0beta1
@@ -29,12 +29,14 @@ use OCP\EventDispatcher\IEventDispatcher; | |||
use OCP\Server; | |||
use OCP\Collaboration\Resources\IManager; | |||
use OCP\Share\Events\ShareCreatedEvent; | |||
use OCP\Share\Events\ShareDeletedEvent; | |||
use OCP\Share\Events\ShareDeletedFromSelfEvent; | |||
class Listener { | |||
public static function register(IEventDispatcher $dispatcher): void { | |||
$dispatcher->addListener(ShareCreatedEvent::class, [self::class, 'shareModification']); | |||
$dispatcher->addListener('OCP\Share::postUnshare', [self::class, 'shareModification']); | |||
$dispatcher->addListener('OCP\Share::postUnshareFromSelf', [self::class, 'shareModification']); | |||
$dispatcher->addListener(ShareDeletedEvent::class, [self::class, 'shareModification']); | |||
$dispatcher->addListener(ShareDeletedFromSelfEvent::class, [self::class, 'shareModification']); | |||
} | |||
public static function shareModification(): void { |
@@ -586,8 +586,10 @@ return array( | |||
'OCP\\Settings\\ISubAdminSettings' => $baseDir . '/lib/public/Settings/ISubAdminSettings.php', | |||
'OCP\\Share' => $baseDir . '/lib/public/Share.php', | |||
'OCP\\Share\\Events\\BeforeShareCreatedEvent' => $baseDir . '/lib/public/Share/Events/BeforeShareCreatedEvent.php', | |||
'OCP\\Share\\Events\\BeforeShareDeletedEvent' => $baseDir . '/lib/public/Share/Events/BeforeShareDeletedEvent.php', | |||
'OCP\\Share\\Events\\ShareCreatedEvent' => $baseDir . '/lib/public/Share/Events/ShareCreatedEvent.php', | |||
'OCP\\Share\\Events\\ShareDeletedEvent' => $baseDir . '/lib/public/Share/Events/ShareDeletedEvent.php', | |||
'OCP\\Share\\Events\\ShareDeletedFromSelfEvent' => $baseDir . '/lib/public/Share/Events/ShareDeletedFromSelfEvent.php', | |||
'OCP\\Share\\Events\\VerifyMountPointEvent' => $baseDir . '/lib/public/Share/Events/VerifyMountPointEvent.php', | |||
'OCP\\Share\\Exceptions\\AlreadySharedException' => $baseDir . '/lib/public/Share/Exceptions/AlreadySharedException.php', | |||
'OCP\\Share\\Exceptions\\GenericShareException' => $baseDir . '/lib/public/Share/Exceptions/GenericShareException.php', |
@@ -619,8 +619,10 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 | |||
'OCP\\Settings\\ISubAdminSettings' => __DIR__ . '/../../..' . '/lib/public/Settings/ISubAdminSettings.php', | |||
'OCP\\Share' => __DIR__ . '/../../..' . '/lib/public/Share.php', | |||
'OCP\\Share\\Events\\BeforeShareCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/BeforeShareCreatedEvent.php', | |||
'OCP\\Share\\Events\\BeforeShareDeletedEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/BeforeShareDeletedEvent.php', | |||
'OCP\\Share\\Events\\ShareCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/ShareCreatedEvent.php', | |||
'OCP\\Share\\Events\\ShareDeletedEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/ShareDeletedEvent.php', | |||
'OCP\\Share\\Events\\ShareDeletedFromSelfEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/ShareDeletedFromSelfEvent.php', | |||
'OCP\\Share\\Events\\VerifyMountPointEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/VerifyMountPointEvent.php', | |||
'OCP\\Share\\Exceptions\\AlreadySharedException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/AlreadySharedException.php', | |||
'OCP\\Share\\Exceptions\\GenericShareException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/GenericShareException.php', |
@@ -30,7 +30,10 @@ use OCP\EventDispatcher\IEventDispatcher; | |||
use OCP\Files\File; | |||
use OCP\Share; | |||
use OCP\Share\Events\BeforeShareCreatedEvent; | |||
use OCP\Share\Events\BeforeShareDeletedEvent; | |||
use OCP\Share\Events\ShareCreatedEvent; | |||
use OCP\Share\Events\ShareDeletedEvent; | |||
use OCP\Share\Events\ShareDeletedFromSelfEvent; | |||
use OCP\Share\IShare; | |||
use Symfony\Component\EventDispatcher\GenericEvent; | |||
@@ -41,20 +44,14 @@ class LegacyHooks { | |||
public function __construct(IEventDispatcher $eventDispatcher) { | |||
$this->eventDispatcher = $eventDispatcher; | |||
$this->eventDispatcher->addListener('OCP\Share::preUnshare', function ($event) { | |||
if ($event instanceof GenericEvent) { | |||
$this->preUnshare($event); | |||
} | |||
$this->eventDispatcher->addListener(BeforeShareDeletedEvent::class, function (BeforeShareDeletedEvent $event) { | |||
$this->preUnshare($event); | |||
}); | |||
$this->eventDispatcher->addListener('OCP\Share::postUnshare', function ($event) { | |||
if ($event instanceof GenericEvent) { | |||
$this->postUnshare($event); | |||
} | |||
$this->eventDispatcher->addListener(ShareDeletedEvent::class, function (ShareDeletedEvent $event) { | |||
$this->postUnshare($event); | |||
}); | |||
$this->eventDispatcher->addListener('OCP\Share::postUnshareFromSelf', function ($event) { | |||
if ($event instanceof GenericEvent) { | |||
$this->postUnshareFromSelf($event); | |||
} | |||
$this->eventDispatcher->addListener(ShareDeletedFromSelfEvent::class, function (ShareDeletedFromSelfEvent $event) { | |||
$this->postUnshareFromSelf($event); | |||
}); | |||
$this->eventDispatcher->addListener(BeforeShareCreatedEvent::class, function (BeforeShareCreatedEvent $event) { | |||
$this->preShare($event); | |||
@@ -64,35 +61,24 @@ class LegacyHooks { | |||
}); | |||
} | |||
public function preUnshare(GenericEvent $e) { | |||
/** @var IShare $share */ | |||
$share = $e->getSubject(); | |||
public function preUnshare(BeforeShareDeletedEvent $e) { | |||
$share = $e->getShare(); | |||
$formatted = $this->formatHookParams($share); | |||
\OC_Hook::emit(Share::class, 'pre_unshare', $formatted); | |||
} | |||
public function postUnshare(GenericEvent $e) { | |||
/** @var IShare $share */ | |||
$share = $e->getSubject(); | |||
public function postUnshare(ShareDeletedEvent $e) { | |||
$share = $e->getShare(); | |||
$formatted = $this->formatHookParams($share); | |||
/** @var IShare[] $deletedShares */ | |||
$deletedShares = $e->getArgument('deletedShares'); | |||
$formattedDeletedShares = array_map(function ($share) { | |||
return $this->formatHookParams($share); | |||
}, $deletedShares); | |||
$formatted['deletedShares'] = $formattedDeletedShares; | |||
$formatted['deletedShares'] = [$formatted]; | |||
\OC_Hook::emit(Share::class, 'post_unshare', $formatted); | |||
} | |||
public function postUnshareFromSelf(GenericEvent $e) { | |||
/** @var IShare $share */ | |||
$share = $e->getSubject(); | |||
public function postUnshareFromSelf(ShareDeletedFromSelfEvent $e) { | |||
$share = $e->getShare(); | |||
$formatted = $this->formatHookParams($share); | |||
$formatted['itemTarget'] = $formatted['fileTarget']; |
@@ -67,7 +67,10 @@ use OCP\Security\Events\ValidatePasswordPolicyEvent; | |||
use OCP\Security\IHasher; | |||
use OCP\Security\ISecureRandom; | |||
use OCP\Share; | |||
use OCP\Share\Events\BeforeShareDeletedEvent; | |||
use OCP\Share\Events\ShareCreatedEvent; | |||
use OCP\Share\Events\ShareDeletedEvent; | |||
use OCP\Share\Events\ShareDeletedFromSelfEvent; | |||
use OCP\Share\Exceptions\AlreadySharedException; | |||
use OCP\Share\Exceptions\GenericShareException; | |||
use OCP\Share\Exceptions\ShareNotFound; | |||
@@ -1204,11 +1207,13 @@ class Manager implements IManager { | |||
$provider = $this->factory->getProviderForType($share->getShareType()); | |||
foreach ($provider->getChildren($share) as $child) { | |||
$this->dispatcher->dispatchTyped(new BeforeShareDeletedEvent($child)); | |||
$deletedChildren = $this->deleteChildren($child); | |||
$deletedShares = array_merge($deletedShares, $deletedChildren); | |||
$provider->delete($child); | |||
$this->dispatcher->dispatchTyped(new Share\Events\ShareDeletedEvent($child)); | |||
$this->dispatcher->dispatchTyped(new ShareDeletedEvent($child)); | |||
$deletedShares[] = $child; | |||
} | |||
@@ -1229,24 +1234,16 @@ class Manager implements IManager { | |||
throw new \InvalidArgumentException('Share does not have a full id'); | |||
} | |||
$event = new GenericEvent($share); | |||
$this->legacyDispatcher->dispatch('OCP\Share::preUnshare', $event); | |||
$this->dispatcher->dispatchTyped(new BeforeShareDeletedEvent($share)); | |||
// Get all children and delete them as well | |||
$deletedShares = $this->deleteChildren($share); | |||
$this->deleteChildren($share); | |||
// Do the actual delete | |||
$provider = $this->factory->getProviderForType($share->getShareType()); | |||
$provider->delete($share); | |||
$this->dispatcher->dispatchTyped(new Share\Events\ShareDeletedEvent($share)); | |||
// All the deleted shares caused by this delete | |||
$deletedShares[] = $share; | |||
// Emit post hook | |||
$event->setArgument('deletedShares', $deletedShares); | |||
$this->legacyDispatcher->dispatch('OCP\Share::postUnshare', $event); | |||
$this->dispatcher->dispatchTyped(new ShareDeletedEvent($share)); | |||
} | |||
@@ -1264,8 +1261,8 @@ class Manager implements IManager { | |||
$provider = $this->factory->getProvider($providerId); | |||
$provider->deleteFromSelf($share, $recipientId); | |||
$event = new GenericEvent($share); | |||
$this->legacyDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event); | |||
$event = new ShareDeletedFromSelfEvent($share); | |||
$this->dispatcher->dispatchTyped($event); | |||
} | |||
public function restoreShare(IShare $share, string $recipientId): IShare { |
@@ -0,0 +1,50 @@ | |||
<?php | |||
declare(strict_types=1); | |||
/** | |||
* @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com> | |||
* | |||
* @author Joas Schilling <coding@schilljs.com> | |||
* | |||
* @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 <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
namespace OCP\Share\Events; | |||
use OCP\EventDispatcher\Event; | |||
use OCP\Share\IShare; | |||
/** | |||
* @since 28.0.0 | |||
*/ | |||
class BeforeShareDeletedEvent extends Event { | |||
/** | |||
* @since 28.0.0 | |||
*/ | |||
public function __construct( | |||
private IShare $share, | |||
) { | |||
parent::__construct(); | |||
} | |||
/** | |||
* @since 28.0.0 | |||
*/ | |||
public function getShare(): IShare { | |||
return $this->share; | |||
} | |||
} |
@@ -0,0 +1,50 @@ | |||
<?php | |||
declare(strict_types=1); | |||
/** | |||
* @copyright Copyright (c) 2023 Joas Schilling <coding@schilljs.com> | |||
* | |||
* @author Joas Schilling <coding@schilljs.com> | |||
* | |||
* @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 <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
namespace OCP\Share\Events; | |||
use OCP\EventDispatcher\Event; | |||
use OCP\Share\IShare; | |||
/** | |||
* @since 28.0.0 | |||
*/ | |||
class ShareDeletedFromSelfEvent extends Event { | |||
/** | |||
* @since 28.0.0 | |||
*/ | |||
public function __construct( | |||
private IShare $share, | |||
) { | |||
parent::__construct(); | |||
} | |||
/** | |||
* @since 28.0.0 | |||
*/ | |||
public function getShare(): IShare { | |||
return $this->share; | |||
} | |||
} |
@@ -32,7 +32,10 @@ use OCP\Files\Cache\ICacheEntry; | |||
use OCP\Files\File; | |||
use OCP\IServerContainer; | |||
use OCP\Share\Events\BeforeShareCreatedEvent; | |||
use OCP\Share\Events\BeforeShareDeletedEvent; | |||
use OCP\Share\Events\ShareCreatedEvent; | |||
use OCP\Share\Events\ShareDeletedEvent; | |||
use OCP\Share\Events\ShareDeletedFromSelfEvent; | |||
use OCP\Share\IShare; | |||
use Psr\Log\LoggerInterface; | |||
use Symfony\Component\EventDispatcher\GenericEvent; | |||
@@ -95,8 +98,8 @@ class LegacyHooksTest extends TestCase { | |||
->method('pre') | |||
->with($hookListnerExpectsPre); | |||
$event = new GenericEvent($share); | |||
$this->eventDispatcher->dispatch('OCP\Share::preUnshare', $event); | |||
$event = new BeforeShareDeletedEvent($share); | |||
$this->eventDispatcher->dispatchTyped($event); | |||
} | |||
public function testPostUnshare() { | |||
@@ -149,9 +152,8 @@ class LegacyHooksTest extends TestCase { | |||
->method('post') | |||
->with($hookListnerExpectsPost); | |||
$event = new GenericEvent($share); | |||
$event->setArgument('deletedShares', [$share]); | |||
$this->eventDispatcher->dispatch('OCP\Share::postUnshare', $event); | |||
$event = new ShareDeletedEvent($share); | |||
$this->eventDispatcher->dispatchTyped($event); | |||
} | |||
public function testPostUnshareFromSelf() { | |||
@@ -206,8 +208,8 @@ class LegacyHooksTest extends TestCase { | |||
->method('postFromSelf') | |||
->with($hookListnerExpectsPostFromSelf); | |||
$event = new GenericEvent($share); | |||
$this->eventDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event); | |||
$event = new ShareDeletedFromSelfEvent($share); | |||
$this->eventDispatcher->dispatchTyped($event); | |||
} | |||
public function testPreShare() { |
@@ -52,7 +52,10 @@ use OCP\Security\Events\ValidatePasswordPolicyEvent; | |||
use OCP\Security\IHasher; | |||
use OCP\Security\ISecureRandom; | |||
use OCP\Share\Events\BeforeShareCreatedEvent; | |||
use OCP\Share\Events\BeforeShareDeletedEvent; | |||
use OCP\Share\Events\ShareCreatedEvent; | |||
use OCP\Share\Events\ShareDeletedEvent; | |||
use OCP\Share\Events\ShareDeletedFromSelfEvent; | |||
use OCP\Share\Exceptions\AlreadySharedException; | |||
use OCP\Share\Exceptions\ShareNotFound; | |||
use OCP\Share\IManager; | |||
@@ -249,17 +252,16 @@ class ManagerTest extends \Test\TestCase { | |||
->method('delete') | |||
->with($share); | |||
$this->eventDispatcher->expects($this->exactly(2)) | |||
->method('dispatch') | |||
$this->dispatcher->expects($this->exactly(2)) | |||
->method('dispatchTyped') | |||
->withConsecutive( | |||
['OCP\Share::preUnshare', | |||
$this->callBack(function (GenericEvent $e) use ($share) { | |||
return $e->getSubject() === $share; | |||
[ | |||
$this->callBack(function (BeforeShareDeletedEvent $e) use ($share) { | |||
return $e->getShare() === $share; | |||
})], | |||
['OCP\Share::postUnshare', | |||
$this->callBack(function (GenericEvent $e) use ($share) { | |||
return $e->getSubject() === $share && | |||
$e->getArgument('deletedShares') === [$share]; | |||
[ | |||
$this->callBack(function (ShareDeletedEvent $e) use ($share) { | |||
return $e->getShare() === $share; | |||
})] | |||
); | |||
@@ -293,17 +295,16 @@ class ManagerTest extends \Test\TestCase { | |||
->method('delete') | |||
->with($share); | |||
$this->eventDispatcher->expects($this->exactly(2)) | |||
->method('dispatch') | |||
$this->dispatcher->expects($this->exactly(2)) | |||
->method('dispatchTyped') | |||
->withConsecutive( | |||
['OCP\Share::preUnshare', | |||
$this->callBack(function (GenericEvent $e) use ($share) { | |||
return $e->getSubject() === $share; | |||
[ | |||
$this->callBack(function (BeforeShareDeletedEvent $e) use ($share) { | |||
return $e->getShare() === $share; | |||
})], | |||
['OCP\Share::postUnshare', | |||
$this->callBack(function (GenericEvent $e) use ($share) { | |||
return $e->getSubject() === $share && | |||
$e->getArgument('deletedShares') === [$share]; | |||
[ | |||
$this->callBack(function (ShareDeletedEvent $e) use ($share) { | |||
return $e->getShare() === $share; | |||
})] | |||
); | |||
@@ -358,18 +359,39 @@ class ManagerTest extends \Test\TestCase { | |||
->method('delete') | |||
->withConsecutive([$share3], [$share2], [$share1]); | |||
$this->eventDispatcher->expects($this->exactly(2)) | |||
->method('dispatch') | |||
$this->dispatcher->expects($this->exactly(6)) | |||
->method('dispatchTyped') | |||
->withConsecutive( | |||
['OCP\Share::preUnshare', | |||
$this->callBack(function (GenericEvent $e) use ($share1) { | |||
return $e->getSubject() === $share1; | |||
})], | |||
['OCP\Share::postUnshare', | |||
$this->callBack(function (GenericEvent $e) use ($share1, $share2, $share3) { | |||
return $e->getSubject() === $share1 && | |||
$e->getArgument('deletedShares') === [$share3, $share2, $share1]; | |||
})] | |||
[ | |||
$this->callBack(function (BeforeShareDeletedEvent $e) use ($share1) { | |||
return $e->getShare()->getId() === $share1->getId(); | |||
}) | |||
], | |||
[ | |||
$this->callBack(function (BeforeShareDeletedEvent $e) use ($share2) { | |||
return $e->getShare()->getId() === $share2->getId(); | |||
}) | |||
], | |||
[ | |||
$this->callBack(function (BeforeShareDeletedEvent $e) use ($share3) { | |||
return $e->getShare()->getId() === $share3->getId(); | |||
}) | |||
], | |||
[ | |||
$this->callBack(function (ShareDeletedEvent $e) use ($share3) { | |||
return $e->getShare()->getId() === $share3->getId(); | |||
}) | |||
], | |||
[ | |||
$this->callBack(function (ShareDeletedEvent $e) use ($share2) { | |||
return $e->getShare()->getId() === $share2->getId(); | |||
}) | |||
], | |||
[ | |||
$this->callBack(function (ShareDeletedEvent $e) use ($share1) { | |||
return $e->getShare()->getId() === $share1->getId(); | |||
}) | |||
], | |||
); | |||
$manager->deleteShare($share1); | |||
@@ -397,12 +419,11 @@ class ManagerTest extends \Test\TestCase { | |||
->method('deleteFromSelf') | |||
->with($share, $recipientId); | |||
$this->eventDispatcher->expects($this->once()) | |||
->method('dispatch') | |||
$this->dispatcher->expects($this->once()) | |||
->method('dispatchTyped') | |||
->with( | |||
'OCP\Share::postUnshareFromSelf', | |||
$this->callBack(function (GenericEvent $e) use ($share) { | |||
return $e->getSubject() === $share; | |||
$this->callBack(function (ShareDeletedFromSelfEvent $e) use ($share) { | |||
return $e->getShare() === $share; | |||
}) | |||
); | |||