Add hook connector to connect view and node hooks

This commit is contained in:
Robin Appelman 2015-09-28 17:16:49 +02:00
parent 72024ad201
commit 1e5a41f008
2 changed files with 328 additions and 0 deletions

View File

@ -0,0 +1,151 @@
<?php
/**
* @author Robin Appelman <icewind@owncloud.com>
*
* @copyright Copyright (c) 2015, 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\Files\Node;
use OC\Files\Filesystem;
use OC\Files\View;
use OCP\Files\FileInfo;
use OCP\Util;
class HookConnector {
/**
* @var Root
*/
private $root;
/**
* @var View
*/
private $view;
/**
* HookConnector constructor.
*
* @param Root $root
* @param View $view
*/
public function __construct(Root $root, View $view) {
$this->root = $root;
$this->view = $view;
}
public function viewToNode() {
Util::connectHook('OC_Filesystem', 'write', $this, 'write');
Util::connectHook('OC_Filesystem', 'post_write', $this, 'postWrite');
Util::connectHook('OC_Filesystem', 'create', $this, 'create');
Util::connectHook('OC_Filesystem', 'post_create', $this, 'postCreate');
Util::connectHook('OC_Filesystem', 'delete', $this, 'delete');
Util::connectHook('OC_Filesystem', 'post_delete', $this, 'postDelete');
Util::connectHook('OC_Filesystem', 'rename', $this, 'rename');
Util::connectHook('OC_Filesystem', 'post_rename', $this, 'postRename');
Util::connectHook('OC_Filesystem', 'copy', $this, 'copy');
Util::connectHook('OC_Filesystem', 'post_copy', $this, 'postCopy');
Util::connectHook('OC_Filesystem', 'touch', $this, 'touch');
Util::connectHook('OC_Filesystem', 'post_touch', $this, 'postTouch');
}
public function write($arguments) {
$node = $this->getNodeForPath($arguments['path']);
$this->root->emit('\OC\Files', 'preWrite', [$node]);
}
public function postWrite($arguments) {
$node = $this->getNodeForPath($arguments['path']);
$this->root->emit('\OC\Files', 'postWrite', [$node]);
}
public function create($arguments) {
$node = $this->getNodeForPath($arguments['path']);
$this->root->emit('\OC\Files', 'preCreate', [$node]);
}
public function postCreate($arguments) {
$node = $this->getNodeForPath($arguments['path']);
$this->root->emit('\OC\Files', 'postCreate', [$node]);
}
public function delete($arguments) {
$node = $this->getNodeForPath($arguments['path']);
$this->root->emit('\OC\Files', 'preDelete', [$node]);
}
public function postDelete($arguments) {
$node = $this->getNodeForPath($arguments['path']);
$this->root->emit('\OC\Files', 'postDelete', [$node]);
}
public function touch($arguments) {
$node = $this->getNodeForPath($arguments['path']);
$this->root->emit('\OC\Files', 'preTouch', [$node]);
}
public function postTouch($arguments) {
$node = $this->getNodeForPath($arguments['path']);
$this->root->emit('\OC\Files', 'postTouch', [$node]);
}
public function rename($arguments) {
$source = $this->getNodeForPath($arguments['oldpath']);
$target = $this->getNodeForPath($arguments['newpath']);
$this->root->emit('\OC\Files', 'preRename', [$source, $target]);
}
public function postRename($arguments) {
$source = $this->getNodeForPath($arguments['oldpath']);
$target = $this->getNodeForPath($arguments['newpath']);
$this->root->emit('\OC\Files', 'postRename', [$source, $target]);
}
public function copy($arguments) {
$source = $this->getNodeForPath($arguments['oldpath']);
$target = $this->getNodeForPath($arguments['newpath']);
$this->root->emit('\OC\Files', 'preCopy', [$source, $target]);
}
public function postCopy($arguments) {
$source = $this->getNodeForPath($arguments['oldpath']);
$target = $this->getNodeForPath($arguments['newpath']);
$this->root->emit('\OC\Files', 'postCopy', [$source, $target]);
}
private function getNodeForPath($path) {
$info = Filesystem::getView()->getFileInfo($path);
if (!$info) {
$fullPath = Filesystem::getView()->getAbsolutePath($path);
if (Filesystem::is_dir($path)) {
return new NonExistingFolder($this->root, $this->view, $fullPath);
} else {
return new NonExistingFile($this->root, $this->view, $fullPath);
}
}
if ($info->getType() === FileInfo::TYPE_FILE) {
return new File($this->root, $this->view, $info->getPath(), $info);
} else {
return new Folder($this->root, $this->view, $info->getPath(), $info);
}
}
}

View File

@ -0,0 +1,177 @@
<?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\Connector\Sabre\File;
use OC\Files\Filesystem;
use OC\Files\Node\Root;
use OC\Files\Storage\Temporary;
use OC\Files\View;
use OCP\Files\Node;
use Test\TestCase;
use Test\Traits\MountProviderTrait;
use Test\Traits\UserTrait;
class HookConnector extends TestCase {
use UserTrait;
use MountProviderTrait;
/**
* @var View
*/
private $view;
/**
* @var Root
*/
private $root;
/**
* @var string
*/
private $userId;
public function setUp() {
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));
}
public function tearDown() {
parent::tearDown();
\OC_Hook::clear('OC_Filesystem');
\OC_Util::tearDownFS();
}
public function viewToNodeProvider() {
return [
[function () {
Filesystem::file_put_contents('test.txt', 'asd');
}, 'preWrite'],
[function () {
Filesystem::file_put_contents('test.txt', 'asd');
}, 'postWrite'],
[function () {
Filesystem::file_put_contents('test.txt', 'asd');
}, 'preCreate'],
[function () {
Filesystem::file_put_contents('test.txt', 'asd');
}, 'postCreate'],
[function () {
Filesystem::mkdir('test.txt');
}, 'preCreate'],
[function () {
Filesystem::mkdir('test.txt');
}, 'postCreate'],
[function () {
Filesystem::touch('test.txt');
}, 'preTouch'],
[function () {
Filesystem::touch('test.txt');
}, 'postTouch'],
[function () {
Filesystem::touch('test.txt');
}, 'preCreate'],
[function () {
Filesystem::touch('test.txt');
}, 'postCreate'],
[function () {
Filesystem::file_put_contents('test.txt', 'asd');
Filesystem::unlink('test.txt');
}, 'preDelete'],
[function () {
Filesystem::file_put_contents('test.txt', 'asd');
Filesystem::unlink('test.txt');
}, 'postDelete'],
[function () {
Filesystem::mkdir('test.txt');
Filesystem::rmdir('test.txt');
}, 'preDelete'],
[function () {
Filesystem::mkdir('test.txt');
Filesystem::rmdir('test.txt');
}, 'postDelete'],
];
}
/**
* @param callable $operation
* @param string $expectedHook
* @dataProvider viewToNodeProvider
*/
public function testViewToNode(callable $operation, $expectedHook) {
$connector = new \OC\Files\Node\HookConnector($this->root, $this->view);
$connector->viewToNode();
$hookCalled = false;
/** @var Node $hookNode */
$hookNode = null;
$this->root->listen('\OC\Files', $expectedHook, function ($node) use (&$hookNode, &$hookCalled) {
$hookCalled = true;
$hookNode = $node;
});
$operation();
$this->assertTrue($hookCalled);
$this->assertEquals('/' . $this->userId . '/files/test.txt', $hookNode->getPath());
}
public function viewToNodeProviderCopyRename() {
return [
[function () {
Filesystem::file_put_contents('source', 'asd');
Filesystem::rename('source', 'target');
}, 'preRename'],
[function () {
Filesystem::file_put_contents('source', 'asd');
Filesystem::rename('source', 'target');
}, 'postRename'],
[function () {
Filesystem::file_put_contents('source', 'asd');
Filesystem::copy('source', 'target');
}, 'preCopy'],
[function () {
Filesystem::file_put_contents('source', 'asd');
Filesystem::copy('source', 'target');
}, 'postCopy'],
];
}
/**
* @param callable $operation
* @param string $expectedHook
* @dataProvider viewToNodeProviderCopyRename
*/
public function testViewToNodeCopyRename(callable $operation, $expectedHook) {
$connector = new \OC\Files\Node\HookConnector($this->root, $this->view);
$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;
});
$operation();
$this->assertTrue($hookCalled);
$this->assertEquals('/' . $this->userId . '/files/source', $hookSourceNode->getPath());
$this->assertEquals('/' . $this->userId . '/files/target', $hookTargetNode->getPath());
}
}