320 lines
11 KiB
PHP
320 lines
11 KiB
PHP
<?php
|
|
/**
|
|
* Copyright (c) 2015 Robin Appelman <icewind@owncloud.com>
|
|
* This file is licensed under the Affero General Public License version 3 or
|
|
* later.
|
|
* See the COPYING-README file.
|
|
*/
|
|
|
|
namespace Test\Files\Node;
|
|
|
|
use OC\Files\Filesystem;
|
|
use OC\Files\Node\HookConnector;
|
|
use OC\Files\Node\Root;
|
|
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;
|
|
use Test\Traits\MountProviderTrait;
|
|
use Test\Traits\UserTrait;
|
|
|
|
/**
|
|
* Class HookConnectorTest
|
|
*
|
|
* @group DB
|
|
*
|
|
* @package Test\Files\Node
|
|
*/
|
|
class HookConnectorTest extends TestCase {
|
|
use UserTrait;
|
|
use MountProviderTrait;
|
|
|
|
/** @var EventDispatcherInterface|MockObject */
|
|
protected $legacyDispatcher;
|
|
|
|
/** @var IEventDispatcher */
|
|
protected $eventDispatcher;
|
|
|
|
/** @var View */
|
|
private $view;
|
|
|
|
/** @var Root */
|
|
private $root;
|
|
|
|
/** @var string */
|
|
private $userId;
|
|
|
|
protected function setUp(): void {
|
|
parent::setUp();
|
|
$this->userId = $this->getUniqueID();
|
|
$this->createUser($this->userId, 'pass');
|
|
$this->registerMount($this->userId, new Temporary(), '/' . $this->userId . '/files/');
|
|
\OC_Util::setupFS($this->userId);
|
|
$this->view = new View();
|
|
$this->root = new Root(
|
|
Filesystem::getMountManager(),
|
|
$this->view,
|
|
\OC::$server->getUserManager()->get($this->userId),
|
|
\OC::$server->getUserMountCache(),
|
|
$this->createMock(ILogger::class),
|
|
$this->createMock(IUserManager::class)
|
|
);
|
|
$this->legacyDispatcher = \OC::$server->getEventDispatcher();
|
|
$this->eventDispatcher = \OC::$server->query(IEventDispatcher::class);
|
|
}
|
|
|
|
protected function tearDown(): void {
|
|
parent::tearDown();
|
|
\OC_Hook::clear('OC_Filesystem');
|
|
\OC_Util::tearDownFS();
|
|
}
|
|
|
|
public function viewToNodeProvider() {
|
|
return [
|
|
[function () {
|
|
Filesystem::file_put_contents('test.txt', 'asd');
|
|
}, 'preWrite', '\OCP\Files::preWrite', BeforeNodeWrittenEvent::class],
|
|
[function () {
|
|
Filesystem::file_put_contents('test.txt', 'asd');
|
|
}, 'postWrite', '\OCP\Files::postWrite', NodeWrittenEvent::class],
|
|
[function () {
|
|
Filesystem::file_put_contents('test.txt', 'asd');
|
|
}, 'preCreate', '\OCP\Files::preCreate', BeforeNodeCreatedEvent::class],
|
|
[function () {
|
|
Filesystem::file_put_contents('test.txt', 'asd');
|
|
}, 'postCreate', '\OCP\Files::postCreate', NodeCreatedEvent::class],
|
|
[function () {
|
|
Filesystem::mkdir('test.txt');
|
|
}, 'preCreate', '\OCP\Files::preCreate', BeforeNodeCreatedEvent::class],
|
|
[function () {
|
|
Filesystem::mkdir('test.txt');
|
|
}, 'postCreate', '\OCP\Files::postCreate', NodeCreatedEvent::class],
|
|
[function () {
|
|
Filesystem::touch('test.txt');
|
|
}, 'preTouch', '\OCP\Files::preTouch', BeforeNodeTouchedEvent::class],
|
|
[function () {
|
|
Filesystem::touch('test.txt');
|
|
}, 'postTouch', '\OCP\Files::postTouch', NodeTouchedEvent::class],
|
|
[function () {
|
|
Filesystem::touch('test.txt');
|
|
}, 'preCreate', '\OCP\Files::preCreate', BeforeNodeCreatedEvent::class],
|
|
[function () {
|
|
Filesystem::touch('test.txt');
|
|
}, 'postCreate', '\OCP\Files::postCreate', NodeCreatedEvent::class],
|
|
[function () {
|
|
Filesystem::file_put_contents('test.txt', 'asd');
|
|
Filesystem::unlink('test.txt');
|
|
}, 'preDelete', '\OCP\Files::preDelete', BeforeNodeDeletedEvent::class],
|
|
[function () {
|
|
Filesystem::file_put_contents('test.txt', 'asd');
|
|
Filesystem::unlink('test.txt');
|
|
}, 'postDelete', '\OCP\Files::postDelete', NodeDeletedEvent::class],
|
|
[function () {
|
|
Filesystem::mkdir('test.txt');
|
|
Filesystem::rmdir('test.txt');
|
|
}, 'preDelete', '\OCP\Files::preDelete', BeforeNodeDeletedEvent::class],
|
|
[function () {
|
|
Filesystem::mkdir('test.txt');
|
|
Filesystem::rmdir('test.txt');
|
|
}, 'postDelete', '\OCP\Files::postDelete', NodeDeletedEvent::class],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param callable $operation
|
|
* @param string $expectedHook
|
|
* @dataProvider viewToNodeProvider
|
|
*/
|
|
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 */
|
|
$hookNode = null;
|
|
|
|
$this->root->listen('\OC\Files', $expectedHook, function ($node) use (&$hookNode, &$hookCalled) {
|
|
$hookCalled = true;
|
|
$hookNode = $node;
|
|
});
|
|
|
|
$dispatcherCalled = false;
|
|
/** @var Node $dispatcherNode */
|
|
$dispatcherNode = null;
|
|
$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);
|
|
$this->assertEquals('/' . $this->userId . '/files/test.txt', $hookNode->getPath());
|
|
|
|
$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() {
|
|
return [
|
|
[function () {
|
|
Filesystem::file_put_contents('source', 'asd');
|
|
Filesystem::rename('source', 'target');
|
|
}, 'preRename', '\OCP\Files::preRename', BeforeNodeRenamedEvent::class],
|
|
[function () {
|
|
Filesystem::file_put_contents('source', 'asd');
|
|
Filesystem::rename('source', 'target');
|
|
}, 'postRename', '\OCP\Files::postRename', NodeRenamedEvent::class],
|
|
[function () {
|
|
Filesystem::file_put_contents('source', 'asd');
|
|
Filesystem::copy('source', 'target');
|
|
}, 'preCopy', '\OCP\Files::preCopy', BeforeNodeCopiedEvent::class],
|
|
[function () {
|
|
Filesystem::file_put_contents('source', 'asd');
|
|
Filesystem::copy('source', 'target');
|
|
}, 'postCopy', '\OCP\Files::postCopy', NodeCopiedEvent::class],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param callable $operation
|
|
* @param string $expectedHook
|
|
* @dataProvider viewToNodeProviderCopyRename
|
|
*/
|
|
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 */
|
|
$hookSourceNode = null;
|
|
/** @var Node $hookTargetNode */
|
|
$hookTargetNode = null;
|
|
|
|
$this->root->listen('\OC\Files', $expectedHook, function ($sourceNode, $targetNode) use (&$hookCalled, &$hookSourceNode, &$hookTargetNode) {
|
|
$hookCalled = true;
|
|
$hookSourceNode = $sourceNode;
|
|
$hookTargetNode = $targetNode;
|
|
});
|
|
|
|
$dispatcherCalled = false;
|
|
/** @var Node $dispatcherSourceNode */
|
|
$dispatcherSourceNode = null;
|
|
/** @var Node $dispatcherTargetNode */
|
|
$dispatcherTargetNode = null;
|
|
$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);
|
|
$this->assertEquals('/' . $this->userId . '/files/source', $hookSourceNode->getPath());
|
|
$this->assertEquals('/' . $this->userId . '/files/target', $hookTargetNode->getPath());
|
|
|
|
$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->legacyDispatcher, $this->eventDispatcher);
|
|
$connector->viewToNode();
|
|
$hookCalled = false;
|
|
/** @var Node $hookNode */
|
|
$hookNode = null;
|
|
|
|
$this->root->listen('\OC\Files', 'postDelete', function ($node) use (&$hookNode, &$hookCalled) {
|
|
$hookCalled = true;
|
|
$hookNode = $node;
|
|
});
|
|
|
|
$dispatcherCalled = false;
|
|
/** @var Node $dispatcherNode */
|
|
$dispatcherNode = null;
|
|
$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');
|
|
|
|
$this->assertTrue($hookCalled);
|
|
$this->assertEquals($hookNode->getId(), $info->getId());
|
|
|
|
$this->assertTrue($dispatcherCalled);
|
|
$this->assertEquals($dispatcherNode->getId(), $info->getId());
|
|
|
|
$this->assertTrue($newDispatcherCalled);
|
|
$this->assertEquals($newDispatcherNode->getId(), $info->getId());
|
|
}
|
|
}
|