diff --git a/lib/base.php b/lib/base.php index b1f9569926..3ac6d978e4 100644 --- a/lib/base.php +++ b/lib/base.php @@ -597,6 +597,7 @@ class OC { // setup the basic server self::$server = new \OC\Server(\OC::$WEBROOT, self::$config); + self::$server->boot(); \OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd); \OC::$server->getEventLogger()->start('boot', 'Initialize'); diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 2c701643c1..520d9426d8 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -231,6 +231,21 @@ return array( 'OCP\\Files\\Events\\FolderScannedEvent' => $baseDir . '/lib/public/Files/Events/FolderScannedEvent.php', 'OCP\\Files\\Events\\NodeAddedToCache' => $baseDir . '/lib/public/Files/Events/NodeAddedToCache.php', 'OCP\\Files\\Events\\NodeRemovedFromCache' => $baseDir . '/lib/public/Files/Events/NodeRemovedFromCache.php', + 'OCP\\Files\\Events\\Node\\AbstractNodeEvent' => $baseDir . '/lib/public/Files/Events/Node/AbstractNodeEvent.php', + 'OCP\\Files\\Events\\Node\\AbstractNodesEvent' => $baseDir . '/lib/public/Files/Events/Node/AbstractNodesEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeCopiedEvent' => $baseDir . '/lib/public/Files/Events/Node/BeforeNodeCopiedEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeCreatedEvent' => $baseDir . '/lib/public/Files/Events/Node/BeforeNodeCreatedEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeDeletedEvent' => $baseDir . '/lib/public/Files/Events/Node/BeforeNodeDeletedEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeReadEvent' => $baseDir . '/lib/public/Files/Events/Node/BeforeNodeReadEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeRenamedEvent' => $baseDir . '/lib/public/Files/Events/Node/BeforeNodeRenamedEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeTouchedEvent' => $baseDir . '/lib/public/Files/Events/Node/BeforeNodeTouchedEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeWrittenEvent' => $baseDir . '/lib/public/Files/Events/Node/BeforeNodeWrittenEvent.php', + 'OCP\\Files\\Events\\Node\\NodeCopiedEvent' => $baseDir . '/lib/public/Files/Events/Node/NodeCopiedEvent.php', + 'OCP\\Files\\Events\\Node\\NodeCreatedEvent' => $baseDir . '/lib/public/Files/Events/Node/NodeCreatedEvent.php', + 'OCP\\Files\\Events\\Node\\NodeDeletedEvent' => $baseDir . '/lib/public/Files/Events/Node/NodeDeletedEvent.php', + 'OCP\\Files\\Events\\Node\\NodeRenamedEvent' => $baseDir . '/lib/public/Files/Events/Node/NodeRenamedEvent.php', + 'OCP\\Files\\Events\\Node\\NodeTouchedEvent' => $baseDir . '/lib/public/Files/Events/Node/NodeTouchedEvent.php', + 'OCP\\Files\\Events\\Node\\NodeWrittenEvent' => $baseDir . '/lib/public/Files/Events/Node/NodeWrittenEvent.php', 'OCP\\Files\\File' => $baseDir . '/lib/public/Files/File.php', 'OCP\\Files\\FileInfo' => $baseDir . '/lib/public/Files/FileInfo.php', 'OCP\\Files\\FileNameTooLongException' => $baseDir . '/lib/public/Files/FileNameTooLongException.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 3046aea4a9..36212bca1f 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -260,6 +260,21 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\Files\\Events\\FolderScannedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/FolderScannedEvent.php', 'OCP\\Files\\Events\\NodeAddedToCache' => __DIR__ . '/../../..' . '/lib/public/Files/Events/NodeAddedToCache.php', 'OCP\\Files\\Events\\NodeRemovedFromCache' => __DIR__ . '/../../..' . '/lib/public/Files/Events/NodeRemovedFromCache.php', + 'OCP\\Files\\Events\\Node\\AbstractNodeEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/AbstractNodeEvent.php', + 'OCP\\Files\\Events\\Node\\AbstractNodesEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/AbstractNodesEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeCopiedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/BeforeNodeCopiedEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/BeforeNodeCreatedEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeDeletedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/BeforeNodeDeletedEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeReadEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/BeforeNodeReadEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeRenamedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/BeforeNodeRenamedEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeTouchedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/BeforeNodeTouchedEvent.php', + 'OCP\\Files\\Events\\Node\\BeforeNodeWrittenEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/BeforeNodeWrittenEvent.php', + 'OCP\\Files\\Events\\Node\\NodeCopiedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/NodeCopiedEvent.php', + 'OCP\\Files\\Events\\Node\\NodeCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/NodeCreatedEvent.php', + 'OCP\\Files\\Events\\Node\\NodeDeletedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/NodeDeletedEvent.php', + 'OCP\\Files\\Events\\Node\\NodeRenamedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/NodeRenamedEvent.php', + 'OCP\\Files\\Events\\Node\\NodeTouchedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/NodeTouchedEvent.php', + 'OCP\\Files\\Events\\Node\\NodeWrittenEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/NodeWrittenEvent.php', 'OCP\\Files\\File' => __DIR__ . '/../../..' . '/lib/public/Files/File.php', 'OCP\\Files\\FileInfo' => __DIR__ . '/../../..' . '/lib/public/Files/FileInfo.php', 'OCP\\Files\\FileNameTooLongException' => __DIR__ . '/../../..' . '/lib/public/Files/FileNameTooLongException.php', diff --git a/lib/private/Files/Node/HookConnector.php b/lib/private/Files/Node/HookConnector.php index 1f7f194c5f..2f2641868a 100644 --- a/lib/private/Files/Node/HookConnector.php +++ b/lib/private/Files/Node/HookConnector.php @@ -27,26 +27,39 @@ namespace OC\Files\Node; use OC\Files\Filesystem; use OC\Files\View; use OCP\EventDispatcher\GenericEvent; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Events\Node\BeforeNodeCopiedEvent; +use OCP\Files\Events\Node\BeforeNodeCreatedEvent; +use OCP\Files\Events\Node\BeforeNodeDeletedEvent; +use OCP\Files\Events\Node\BeforeNodeReadEvent; +use OCP\Files\Events\Node\BeforeNodeRenamedEvent; +use OCP\Files\Events\Node\BeforeNodeTouchedEvent; +use OCP\Files\Events\Node\BeforeNodeWrittenEvent; +use OCP\Files\Events\Node\NodeCopiedEvent; +use OCP\Files\Events\Node\NodeCreatedEvent; +use OCP\Files\Events\Node\NodeDeletedEvent; +use OCP\Files\Events\Node\NodeRenamedEvent; +use OCP\Files\Events\Node\NodeTouchedEvent; +use OCP\Files\Events\Node\NodeWrittenEvent; use OCP\Files\FileInfo; +use OCP\Files\IRootFolder; use OCP\Util; use Symfony\Component\EventDispatcher\EventDispatcherInterface; class HookConnector { - /** - * @var Root - */ + /** @var IRootFolder */ private $root; - /** - * @var View - */ + /** @var View */ private $view; - /** - * @var FileInfo[] - */ + /** @var FileInfo[] */ private $deleteMetaCache = []; + /** @var EventDispatcherInterface */ + private $legacyDispatcher; + + /** @var IEventDispatcher */ private $dispatcher; /** @@ -55,9 +68,14 @@ class HookConnector { * @param Root $root * @param View $view */ - public function __construct(Root $root, View $view, EventDispatcherInterface $dispatcher) { + public function __construct( + IRootFolder $root, + View $view, + EventDispatcherInterface $legacyDispatcher, + IEventDispatcher $dispatcher) { $this->root = $root; $this->view = $view; + $this->legacyDispatcher = $legacyDispatcher; $this->dispatcher = $dispatcher; } @@ -86,85 +104,124 @@ class HookConnector { public function write($arguments) { $node = $this->getNodeForPath($arguments['path']); $this->root->emit('\OC\Files', 'preWrite', [$node]); - $this->dispatcher->dispatch('\OCP\Files::preWrite', new GenericEvent($node)); + $this->legacyDispatcher->dispatch('\OCP\Files::preWrite', new GenericEvent($node)); + + $event = new BeforeNodeWrittenEvent($node); + $this->dispatcher->dispatchTyped($event); } public function postWrite($arguments) { $node = $this->getNodeForPath($arguments['path']); $this->root->emit('\OC\Files', 'postWrite', [$node]); - $this->dispatcher->dispatch('\OCP\Files::postWrite', new GenericEvent($node)); + $this->legacyDispatcher->dispatch('\OCP\Files::postWrite', new GenericEvent($node)); + + $event = new NodeWrittenEvent($node); + $this->dispatcher->dispatchTyped($event); } public function create($arguments) { $node = $this->getNodeForPath($arguments['path']); $this->root->emit('\OC\Files', 'preCreate', [$node]); - $this->dispatcher->dispatch('\OCP\Files::preCreate', new GenericEvent($node)); + $this->legacyDispatcher->dispatch('\OCP\Files::preCreate', new GenericEvent($node)); + + $event = new BeforeNodeCreatedEvent($node); + $this->dispatcher->dispatchTyped($event); } public function postCreate($arguments) { $node = $this->getNodeForPath($arguments['path']); $this->root->emit('\OC\Files', 'postCreate', [$node]); - $this->dispatcher->dispatch('\OCP\Files::postCreate', new GenericEvent($node)); + $this->legacyDispatcher->dispatch('\OCP\Files::postCreate', new GenericEvent($node)); + + $event = new NodeCreatedEvent($node); + $this->dispatcher->dispatchTyped($event); } public function delete($arguments) { $node = $this->getNodeForPath($arguments['path']); $this->deleteMetaCache[$node->getPath()] = $node->getFileInfo(); $this->root->emit('\OC\Files', 'preDelete', [$node]); - $this->dispatcher->dispatch('\OCP\Files::preDelete', new GenericEvent($node)); + $this->legacyDispatcher->dispatch('\OCP\Files::preDelete', new GenericEvent($node)); + + $event = new BeforeNodeDeletedEvent($node); + $this->dispatcher->dispatchTyped($event); } public function postDelete($arguments) { $node = $this->getNodeForPath($arguments['path']); unset($this->deleteMetaCache[$node->getPath()]); $this->root->emit('\OC\Files', 'postDelete', [$node]); - $this->dispatcher->dispatch('\OCP\Files::postDelete', new GenericEvent($node)); + $this->legacyDispatcher->dispatch('\OCP\Files::postDelete', new GenericEvent($node)); + + $event = new NodeDeletedEvent($node); + $this->dispatcher->dispatchTyped($event); } public function touch($arguments) { $node = $this->getNodeForPath($arguments['path']); $this->root->emit('\OC\Files', 'preTouch', [$node]); - $this->dispatcher->dispatch('\OCP\Files::preTouch', new GenericEvent($node)); + $this->legacyDispatcher->dispatch('\OCP\Files::preTouch', new GenericEvent($node)); + + $event = new BeforeNodeTouchedEvent($node); + $this->dispatcher->dispatchTyped($event); } public function postTouch($arguments) { $node = $this->getNodeForPath($arguments['path']); $this->root->emit('\OC\Files', 'postTouch', [$node]); - $this->dispatcher->dispatch('\OCP\Files::postTouch', new GenericEvent($node)); + $this->legacyDispatcher->dispatch('\OCP\Files::postTouch', new GenericEvent($node)); + + $event = new NodeTouchedEvent($node); + $this->dispatcher->dispatchTyped($event); } public function rename($arguments) { $source = $this->getNodeForPath($arguments['oldpath']); $target = $this->getNodeForPath($arguments['newpath']); $this->root->emit('\OC\Files', 'preRename', [$source, $target]); - $this->dispatcher->dispatch('\OCP\Files::preRename', new GenericEvent([$source, $target])); + $this->legacyDispatcher->dispatch('\OCP\Files::preRename', new GenericEvent([$source, $target])); + + $event = new BeforeNodeRenamedEvent($source, $target); + $this->dispatcher->dispatchTyped($event); } public function postRename($arguments) { $source = $this->getNodeForPath($arguments['oldpath']); $target = $this->getNodeForPath($arguments['newpath']); $this->root->emit('\OC\Files', 'postRename', [$source, $target]); - $this->dispatcher->dispatch('\OCP\Files::postRename', new GenericEvent([$source, $target])); + $this->legacyDispatcher->dispatch('\OCP\Files::postRename', new GenericEvent([$source, $target])); + + $event = new NodeRenamedEvent($source, $target); + $this->dispatcher->dispatchTyped($event); } public function copy($arguments) { $source = $this->getNodeForPath($arguments['oldpath']); $target = $this->getNodeForPath($arguments['newpath']); $this->root->emit('\OC\Files', 'preCopy', [$source, $target]); - $this->dispatcher->dispatch('\OCP\Files::preCopy', new GenericEvent([$source, $target])); + $this->legacyDispatcher->dispatch('\OCP\Files::preCopy', new GenericEvent([$source, $target])); + + $event = new BeforeNodeCopiedEvent($source, $target); + $this->dispatcher->dispatchTyped($event); } public function postCopy($arguments) { $source = $this->getNodeForPath($arguments['oldpath']); $target = $this->getNodeForPath($arguments['newpath']); $this->root->emit('\OC\Files', 'postCopy', [$source, $target]); - $this->dispatcher->dispatch('\OCP\Files::postCopy', new GenericEvent([$source, $target])); + $this->legacyDispatcher->dispatch('\OCP\Files::postCopy', new GenericEvent([$source, $target])); + + $event = new NodeCopiedEvent($source, $target); + $this->dispatcher->dispatchTyped($event); } public function read($arguments) { $node = $this->getNodeForPath($arguments['path']); $this->root->emit('\OC\Files', 'read', [$node]); - $this->dispatcher->dispatch('\OCP\Files::read', new GenericEvent([$node])); + $this->legacyDispatcher->dispatch('\OCP\Files::read', new GenericEvent([$node])); + + $event = new BeforeNodeReadEvent($node); + $this->dispatcher->dispatchTyped($event); } private function getNodeForPath($path) { diff --git a/lib/private/Server.php b/lib/private/Server.php index 9c3c6391c3..ba628d1269 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -373,14 +373,21 @@ class Server extends ServerContainer implements IServerContainer { $this->getLogger(), $this->getUserManager() ); - $connector = new HookConnector($root, $view, $c->getEventDispatcher()); - $connector->viewToNode(); $previewConnector = new \OC\Preview\WatcherConnector($root, $c->getSystemConfig()); $previewConnector->connectWatcher(); return $root; }); + $this->registerService(HookConnector::class, function (Server $c) { + return new HookConnector( + $c->query(IRootFolder::class), + new View(), + $c->query(\OC\EventDispatcher\SymfonyAdapter::class), + $c->query(IEventDispatcher::class) + ); + }); + $this->registerDeprecatedAlias('SystemTagObjectMapper', ISystemTagObjectMapper::class); $this->registerService(IRootFolder::class, function (Server $c) { @@ -1359,6 +1366,12 @@ class Server extends ServerContainer implements IServerContainer { $this->connectDispatcher(); } + public function boot() { + /** @var HookConnector $hookConnector */ + $hookConnector = $this->query(HookConnector::class); + $hookConnector->viewToNode(); + } + /** * @return \OCP\Calendar\IManager */ diff --git a/lib/public/Files/Events/Node/AbstractNodeEvent.php b/lib/public/Files/Events/Node/AbstractNodeEvent.php new file mode 100644 index 0000000000..a6976e3639 --- /dev/null +++ b/lib/public/Files/Events/Node/AbstractNodeEvent.php @@ -0,0 +1,52 @@ + + * + * @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 OCP\Files\Events\Node; + +use OCP\EventDispatcher\Event; +use OCP\Files\Node; + +/** + * @since 20.0.0 + */ +abstract class AbstractNodeEvent extends Event { + + /** @var Node */ + private $node; + + /** + * @since 20.0.0 + */ + public function __construct(Node $node) { + $this->node = $node; + } + + /** + * @since 20.0.0 + */ + public function getNode(): Node { + return $this->node; + } +} diff --git a/lib/public/Files/Events/Node/AbstractNodesEvent.php b/lib/public/Files/Events/Node/AbstractNodesEvent.php new file mode 100644 index 0000000000..b5500143d7 --- /dev/null +++ b/lib/public/Files/Events/Node/AbstractNodesEvent.php @@ -0,0 +1,62 @@ + + * + * @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 OCP\Files\Events\Node; + +use OCP\EventDispatcher\Event; +use OCP\Files\Node; + +/** + * @since 20.0.0 + */ +abstract class AbstractNodesEvent extends Event { + + /** @var Node */ + private $source; + /** @var Node */ + private $target; + + /** + * @since 20.0.0 + */ + public function __construct(Node $source, Node $target) { + $this->source = $source; + $this->target = $target; + } + + /** + * @since 20.0.0 + */ + public function getSource(): Node { + return $this->source; + } + + /** + * @since 20.0.0 + */ + public function getTarget(): Node { + return $this->target; + } +} diff --git a/lib/public/Files/Events/Node/BeforeNodeCopiedEvent.php b/lib/public/Files/Events/Node/BeforeNodeCopiedEvent.php new file mode 100644 index 0000000000..258d8b61bf --- /dev/null +++ b/lib/public/Files/Events/Node/BeforeNodeCopiedEvent.php @@ -0,0 +1,32 @@ + + * + * @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 OCP\Files\Events\Node; + +/** + * @since 20.0.0 + */ +class BeforeNodeCopiedEvent extends AbstractNodesEvent { +} diff --git a/lib/public/Files/Events/Node/BeforeNodeCreatedEvent.php b/lib/public/Files/Events/Node/BeforeNodeCreatedEvent.php new file mode 100644 index 0000000000..645ea26a74 --- /dev/null +++ b/lib/public/Files/Events/Node/BeforeNodeCreatedEvent.php @@ -0,0 +1,32 @@ + + * + * @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 OCP\Files\Events\Node; + +/** + * @since 20.0.0 + */ +class BeforeNodeCreatedEvent extends AbstractNodeEvent { +} diff --git a/lib/public/Files/Events/Node/BeforeNodeDeletedEvent.php b/lib/public/Files/Events/Node/BeforeNodeDeletedEvent.php new file mode 100644 index 0000000000..cd71de981a --- /dev/null +++ b/lib/public/Files/Events/Node/BeforeNodeDeletedEvent.php @@ -0,0 +1,32 @@ + + * + * @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 OCP\Files\Events\Node; + +/** + * @since 20.0.0 + */ +class BeforeNodeDeletedEvent extends AbstractNodeEvent { +} diff --git a/lib/public/Files/Events/Node/BeforeNodeReadEvent.php b/lib/public/Files/Events/Node/BeforeNodeReadEvent.php new file mode 100644 index 0000000000..59bb8a0711 --- /dev/null +++ b/lib/public/Files/Events/Node/BeforeNodeReadEvent.php @@ -0,0 +1,32 @@ + + * + * @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 OCP\Files\Events\Node; + +/** + * @since 20.0.0 + */ +class BeforeNodeReadEvent extends AbstractNodeEvent { +} diff --git a/lib/public/Files/Events/Node/BeforeNodeRenamedEvent.php b/lib/public/Files/Events/Node/BeforeNodeRenamedEvent.php new file mode 100644 index 0000000000..f4eeff0ce5 --- /dev/null +++ b/lib/public/Files/Events/Node/BeforeNodeRenamedEvent.php @@ -0,0 +1,32 @@ + + * + * @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 OCP\Files\Events\Node; + +/** + * @since 20.0.0 + */ +class BeforeNodeRenamedEvent extends AbstractNodesEvent { +} diff --git a/lib/public/Files/Events/Node/BeforeNodeTouchedEvent.php b/lib/public/Files/Events/Node/BeforeNodeTouchedEvent.php new file mode 100644 index 0000000000..690c2ebe13 --- /dev/null +++ b/lib/public/Files/Events/Node/BeforeNodeTouchedEvent.php @@ -0,0 +1,32 @@ + + * + * @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 OCP\Files\Events\Node; + +/** + * @since 20.0.0 + */ +class BeforeNodeTouchedEvent extends AbstractNodeEvent { +} diff --git a/lib/public/Files/Events/Node/BeforeNodeWrittenEvent.php b/lib/public/Files/Events/Node/BeforeNodeWrittenEvent.php new file mode 100644 index 0000000000..03c458d9fc --- /dev/null +++ b/lib/public/Files/Events/Node/BeforeNodeWrittenEvent.php @@ -0,0 +1,32 @@ + + * + * @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 OCP\Files\Events\Node; + +/** + * @since 20.0.0 + */ +class BeforeNodeWrittenEvent extends AbstractNodeEvent { +} diff --git a/lib/public/Files/Events/Node/NodeCopiedEvent.php b/lib/public/Files/Events/Node/NodeCopiedEvent.php new file mode 100644 index 0000000000..3b607caa2c --- /dev/null +++ b/lib/public/Files/Events/Node/NodeCopiedEvent.php @@ -0,0 +1,32 @@ + + * + * @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 OCP\Files\Events\Node; + +/** + * @since 20.0.0 + */ +class NodeCopiedEvent extends AbstractNodesEvent { +} diff --git a/lib/public/Files/Events/Node/NodeCreatedEvent.php b/lib/public/Files/Events/Node/NodeCreatedEvent.php new file mode 100644 index 0000000000..2b2bfa4ea9 --- /dev/null +++ b/lib/public/Files/Events/Node/NodeCreatedEvent.php @@ -0,0 +1,32 @@ + + * + * @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 OCP\Files\Events\Node; + +/** + * @since 20.0.0 + */ +class NodeCreatedEvent extends AbstractNodeEvent { +} diff --git a/lib/public/Files/Events/Node/NodeDeletedEvent.php b/lib/public/Files/Events/Node/NodeDeletedEvent.php new file mode 100644 index 0000000000..473c66bcbb --- /dev/null +++ b/lib/public/Files/Events/Node/NodeDeletedEvent.php @@ -0,0 +1,32 @@ + + * + * @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 OCP\Files\Events\Node; + +/** + * @since 20.0.0 + */ +class NodeDeletedEvent extends AbstractNodeEvent { +} diff --git a/lib/public/Files/Events/Node/NodeRenamedEvent.php b/lib/public/Files/Events/Node/NodeRenamedEvent.php new file mode 100644 index 0000000000..e82e0b0a32 --- /dev/null +++ b/lib/public/Files/Events/Node/NodeRenamedEvent.php @@ -0,0 +1,32 @@ + + * + * @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 OCP\Files\Events\Node; + +/** + * @since 20.0.0 + */ +class NodeRenamedEvent extends AbstractNodesEvent { +} diff --git a/lib/public/Files/Events/Node/NodeTouchedEvent.php b/lib/public/Files/Events/Node/NodeTouchedEvent.php new file mode 100644 index 0000000000..7ac53266f3 --- /dev/null +++ b/lib/public/Files/Events/Node/NodeTouchedEvent.php @@ -0,0 +1,32 @@ + + * + * @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 OCP\Files\Events\Node; + +/** + * @since 20.0.0 + */ +class NodeTouchedEvent extends AbstractNodeEvent { +} diff --git a/lib/public/Files/Events/Node/NodeWrittenEvent.php b/lib/public/Files/Events/Node/NodeWrittenEvent.php new file mode 100644 index 0000000000..f8eafe54bb --- /dev/null +++ b/lib/public/Files/Events/Node/NodeWrittenEvent.php @@ -0,0 +1,32 @@ + + * + * @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 OCP\Files\Events\Node; + +/** + * @since 20.0.0 + */ +class NodeWrittenEvent extends AbstractNodeEvent { +} diff --git a/tests/lib/Files/Node/HookConnectorTest.php b/tests/lib/Files/Node/HookConnectorTest.php index 4c747a562b..004b74e755 100644 --- a/tests/lib/Files/Node/HookConnectorTest.php +++ b/tests/lib/Files/Node/HookConnectorTest.php @@ -15,9 +15,25 @@ use OC\Files\Storage\Temporary; use OC\Files\View; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\GenericEvent as APIGenericEvent; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Events\Node\AbstractNodeEvent; +use OCP\Files\Events\Node\AbstractNodesEvent; +use OCP\Files\Events\Node\BeforeNodeCopiedEvent; +use OCP\Files\Events\Node\BeforeNodeCreatedEvent; +use OCP\Files\Events\Node\BeforeNodeDeletedEvent; +use OCP\Files\Events\Node\BeforeNodeRenamedEvent; +use OCP\Files\Events\Node\BeforeNodeTouchedEvent; +use OCP\Files\Events\Node\BeforeNodeWrittenEvent; +use OCP\Files\Events\Node\NodeCopiedEvent; +use OCP\Files\Events\Node\NodeCreatedEvent; +use OCP\Files\Events\Node\NodeDeletedEvent; +use OCP\Files\Events\Node\NodeRenamedEvent; +use OCP\Files\Events\Node\NodeTouchedEvent; +use OCP\Files\Events\Node\NodeWrittenEvent; use OCP\Files\Node; use OCP\ILogger; use OCP\IUserManager; +use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\GenericEvent; use Test\TestCase; @@ -34,23 +50,20 @@ use Test\Traits\UserTrait; class HookConnectorTest extends TestCase { use UserTrait; use MountProviderTrait; - /** @var \PHPUnit\Framework\MockObject\MockObject */ - /** @var EventDispatcherInterface */ + + /** @var EventDispatcherInterface|MockObject */ + protected $legacyDispatcher; + + /** @var IEventDispatcher */ protected $eventDispatcher; - /** - * @var View - */ + /** @var View */ private $view; - /** - * @var Root - */ + /** @var Root */ private $root; - /** - * @var string - */ + /** @var string */ private $userId; protected function setUp(): void { @@ -68,7 +81,8 @@ class HookConnectorTest extends TestCase { $this->createMock(ILogger::class), $this->createMock(IUserManager::class) ); - $this->eventDispatcher = \OC::$server->getEventDispatcher(); + $this->legacyDispatcher = \OC::$server->getEventDispatcher(); + $this->eventDispatcher = \OC::$server->query(IEventDispatcher::class); } protected function tearDown(): void { @@ -81,50 +95,50 @@ class HookConnectorTest extends TestCase { return [ [function () { Filesystem::file_put_contents('test.txt', 'asd'); - }, 'preWrite', '\OCP\Files::preWrite'], + }, 'preWrite', '\OCP\Files::preWrite', BeforeNodeWrittenEvent::class], [function () { Filesystem::file_put_contents('test.txt', 'asd'); - }, 'postWrite', '\OCP\Files::postWrite'], + }, 'postWrite', '\OCP\Files::postWrite', NodeWrittenEvent::class], [function () { Filesystem::file_put_contents('test.txt', 'asd'); - }, 'preCreate', '\OCP\Files::preCreate'], + }, 'preCreate', '\OCP\Files::preCreate', BeforeNodeCreatedEvent::class], [function () { Filesystem::file_put_contents('test.txt', 'asd'); - }, 'postCreate', '\OCP\Files::postCreate'], + }, 'postCreate', '\OCP\Files::postCreate', NodeCreatedEvent::class], [function () { Filesystem::mkdir('test.txt'); - }, 'preCreate', '\OCP\Files::preCreate'], + }, 'preCreate', '\OCP\Files::preCreate', BeforeNodeCreatedEvent::class], [function () { Filesystem::mkdir('test.txt'); - }, 'postCreate', '\OCP\Files::postCreate'], + }, 'postCreate', '\OCP\Files::postCreate', NodeCreatedEvent::class], [function () { Filesystem::touch('test.txt'); - }, 'preTouch', '\OCP\Files::preTouch'], + }, 'preTouch', '\OCP\Files::preTouch', BeforeNodeTouchedEvent::class], [function () { Filesystem::touch('test.txt'); - }, 'postTouch', '\OCP\Files::postTouch'], + }, 'postTouch', '\OCP\Files::postTouch', NodeTouchedEvent::class], [function () { Filesystem::touch('test.txt'); - }, 'preCreate', '\OCP\Files::preCreate'], + }, 'preCreate', '\OCP\Files::preCreate', BeforeNodeCreatedEvent::class], [function () { Filesystem::touch('test.txt'); - }, 'postCreate', '\OCP\Files::postCreate'], + }, 'postCreate', '\OCP\Files::postCreate', NodeCreatedEvent::class], [function () { Filesystem::file_put_contents('test.txt', 'asd'); Filesystem::unlink('test.txt'); - }, 'preDelete', '\OCP\Files::preDelete'], + }, 'preDelete', '\OCP\Files::preDelete', BeforeNodeDeletedEvent::class], [function () { Filesystem::file_put_contents('test.txt', 'asd'); Filesystem::unlink('test.txt'); - }, 'postDelete', '\OCP\Files::postDelete'], + }, 'postDelete', '\OCP\Files::postDelete', NodeDeletedEvent::class], [function () { Filesystem::mkdir('test.txt'); Filesystem::rmdir('test.txt'); - }, 'preDelete', '\OCP\Files::preDelete'], + }, 'preDelete', '\OCP\Files::preDelete', BeforeNodeDeletedEvent::class], [function () { Filesystem::mkdir('test.txt'); Filesystem::rmdir('test.txt'); - }, 'postDelete', '\OCP\Files::postDelete'], + }, 'postDelete', '\OCP\Files::postDelete', NodeDeletedEvent::class], ]; } @@ -133,8 +147,8 @@ class HookConnectorTest extends TestCase { * @param string $expectedHook * @dataProvider viewToNodeProvider */ - public function testViewToNode(callable $operation, $expectedHook, $expectedEvent) { - $connector = new HookConnector($this->root, $this->view, $this->eventDispatcher); + public function testViewToNode(callable $operation, $expectedHook, $expectedLegacyEvent, $expectedEvent) { + $connector = new HookConnector($this->root, $this->view, $this->legacyDispatcher, $this->eventDispatcher); $connector->viewToNode(); $hookCalled = false; /** @var Node $hookNode */ @@ -148,12 +162,22 @@ class HookConnectorTest extends TestCase { $dispatcherCalled = false; /** @var Node $dispatcherNode */ $dispatcherNode = null; - $this->eventDispatcher->addListener($expectedEvent, function ($event) use (&$dispatcherCalled, &$dispatcherNode) { + $this->legacyDispatcher->addListener($expectedLegacyEvent, function ($event) use (&$dispatcherCalled, &$dispatcherNode) { /** @var GenericEvent|APIGenericEvent $event */ $dispatcherCalled = true; $dispatcherNode = $event->getSubject(); }); + $newDispatcherCalled = false; + $newDispatcherNode = null; + $this->eventDispatcher->addListener($expectedEvent, function ($event) use ($expectedEvent, &$newDispatcherCalled, &$newDispatcherNode) { + if ($event instanceof $expectedEvent) { + /** @var AbstractNodeEvent $event */ + $newDispatcherCalled = true; + $newDispatcherNode = $event->getNode(); + } + }); + $operation(); $this->assertTrue($hookCalled); @@ -161,6 +185,9 @@ class HookConnectorTest extends TestCase { $this->assertTrue($dispatcherCalled); $this->assertEquals('/' . $this->userId . '/files/test.txt', $dispatcherNode->getPath()); + + $this->assertTrue($newDispatcherCalled); + $this->assertEquals('/' . $this->userId . '/files/test.txt', $newDispatcherNode->getPath()); } public function viewToNodeProviderCopyRename() { @@ -168,19 +195,19 @@ class HookConnectorTest extends TestCase { [function () { Filesystem::file_put_contents('source', 'asd'); Filesystem::rename('source', 'target'); - }, 'preRename', '\OCP\Files::preRename'], + }, 'preRename', '\OCP\Files::preRename', BeforeNodeRenamedEvent::class], [function () { Filesystem::file_put_contents('source', 'asd'); Filesystem::rename('source', 'target'); - }, 'postRename', '\OCP\Files::postRename'], + }, 'postRename', '\OCP\Files::postRename', NodeRenamedEvent::class], [function () { Filesystem::file_put_contents('source', 'asd'); Filesystem::copy('source', 'target'); - }, 'preCopy', '\OCP\Files::preCopy'], + }, 'preCopy', '\OCP\Files::preCopy', BeforeNodeCopiedEvent::class], [function () { Filesystem::file_put_contents('source', 'asd'); Filesystem::copy('source', 'target'); - }, 'postCopy', '\OCP\Files::postCopy'], + }, 'postCopy', '\OCP\Files::postCopy', NodeCopiedEvent::class], ]; } @@ -189,8 +216,8 @@ class HookConnectorTest extends TestCase { * @param string $expectedHook * @dataProvider viewToNodeProviderCopyRename */ - public function testViewToNodeCopyRename(callable $operation, $expectedHook, $expectedEvent) { - $connector = new HookConnector($this->root, $this->view, $this->eventDispatcher); + public function testViewToNodeCopyRename(callable $operation, $expectedHook, $expectedLegacyEvent, $expectedEvent) { + $connector = new HookConnector($this->root, $this->view, $this->legacyDispatcher, $this->eventDispatcher); $connector->viewToNode(); $hookCalled = false; /** @var Node $hookSourceNode */ @@ -209,12 +236,26 @@ class HookConnectorTest extends TestCase { $dispatcherSourceNode = null; /** @var Node $dispatcherTargetNode */ $dispatcherTargetNode = null; - $this->eventDispatcher->addListener($expectedEvent, function ($event) use (&$dispatcherSourceNode, &$dispatcherTargetNode, &$dispatcherCalled) { + $this->legacyDispatcher->addListener($expectedLegacyEvent, function ($event) use (&$dispatcherSourceNode, &$dispatcherTargetNode, &$dispatcherCalled) { /** @var GenericEvent|APIGenericEvent $event */ $dispatcherCalled = true; list($dispatcherSourceNode, $dispatcherTargetNode) = $event->getSubject(); }); + $newDispatcherCalled = false; + /** @var Node $dispatcherSourceNode */ + $newDispatcherSourceNode = null; + /** @var Node $dispatcherTargetNode */ + $newDispatcherTargetNode = null; + $this->eventDispatcher->addListener($expectedEvent, function ($event) use ($expectedEvent, &$newDispatcherSourceNode, &$newDispatcherTargetNode, &$newDispatcherCalled) { + if ($event instanceof $expectedEvent) { + /** @var AbstractNodesEvent$event */ + $newDispatcherCalled = true; + $newDispatcherSourceNode = $event->getSource(); + $newDispatcherTargetNode = $event->getTarget(); + } + }); + $operation(); $this->assertTrue($hookCalled); @@ -224,10 +265,14 @@ class HookConnectorTest extends TestCase { $this->assertTrue($dispatcherCalled); $this->assertEquals('/' . $this->userId . '/files/source', $dispatcherSourceNode->getPath()); $this->assertEquals('/' . $this->userId . '/files/target', $dispatcherTargetNode->getPath()); + + $this->assertTrue($newDispatcherCalled); + $this->assertEquals('/' . $this->userId . '/files/source', $newDispatcherSourceNode->getPath()); + $this->assertEquals('/' . $this->userId . '/files/target', $newDispatcherTargetNode->getPath()); } public function testPostDeleteMeta() { - $connector = new HookConnector($this->root, $this->view, $this->eventDispatcher); + $connector = new HookConnector($this->root, $this->view, $this->legacyDispatcher, $this->eventDispatcher); $connector->viewToNode(); $hookCalled = false; /** @var Node $hookNode */ @@ -241,12 +286,23 @@ class HookConnectorTest extends TestCase { $dispatcherCalled = false; /** @var Node $dispatcherNode */ $dispatcherNode = null; - $this->eventDispatcher->addListener('\OCP\Files::postDelete', function ($event) use (&$dispatcherCalled, &$dispatcherNode) { + $this->legacyDispatcher->addListener('\OCP\Files::postDelete', function ($event) use (&$dispatcherCalled, &$dispatcherNode) { /** @var GenericEvent|APIGenericEvent $event */ $dispatcherCalled = true; $dispatcherNode = $event->getSubject(); }); + $newDispatcherCalled = false; + /** @var Node $dispatcherNode */ + $newDispatcherNode = null; + $this->eventDispatcher->addListener(NodeDeletedEvent::class, function ($event) use (&$newDispatcherCalled, &$newDispatcherNode) { + if ($event instanceof NodeDeletedEvent) { + /** @var AbstractNodeEvent $event */ + $newDispatcherCalled = true; + $newDispatcherNode = $event->getNode(); + } + }); + Filesystem::file_put_contents('test.txt', 'asd'); $info = Filesystem::getFileInfo('test.txt'); Filesystem::unlink('test.txt'); @@ -256,5 +312,8 @@ class HookConnectorTest extends TestCase { $this->assertTrue($dispatcherCalled); $this->assertEquals($dispatcherNode->getId(), $info->getId()); + + $this->assertTrue($newDispatcherCalled); + $this->assertEquals($newDispatcherNode->getId(), $info->getId()); } }