Whenever a rename or copy operation failed on the view, we must throw an exception instead of just ignoring. Signed-off-by: Vincent Petry <pvince81@owncloud.com>tags/v12.0.0beta1
@@ -29,6 +29,16 @@ namespace OC\Files\Node; | |||
use OCP\Files\NotPermittedException; | |||
class File extends Node implements \OCP\Files\File { | |||
/** | |||
* Creates a Folder that represents a non-existing path | |||
* | |||
* @param string $path path | |||
* @return string non-existing node class | |||
*/ | |||
protected function createNonExistingNode($path) { | |||
return new NonExistingFile($this->root, $this->view, $path); | |||
} | |||
/** | |||
* @return string | |||
* @throws \OCP\Files\NotPermittedException | |||
@@ -113,52 +123,6 @@ class File extends Node implements \OCP\Files\File { | |||
} | |||
} | |||
/** | |||
* @param string $targetPath | |||
* @throws \OCP\Files\NotPermittedException | |||
* @return \OC\Files\Node\Node | |||
*/ | |||
public function copy($targetPath) { | |||
$targetPath = $this->normalizePath($targetPath); | |||
$parent = $this->root->get(dirname($targetPath)); | |||
if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) { | |||
$nonExisting = new NonExistingFile($this->root, $this->view, $targetPath); | |||
$this->root->emit('\OC\Files', 'preCopy', array($this, $nonExisting)); | |||
$this->root->emit('\OC\Files', 'preWrite', array($nonExisting)); | |||
$this->view->copy($this->path, $targetPath); | |||
$targetNode = $this->root->get($targetPath); | |||
$this->root->emit('\OC\Files', 'postCopy', array($this, $targetNode)); | |||
$this->root->emit('\OC\Files', 'postWrite', array($targetNode)); | |||
return $targetNode; | |||
} else { | |||
throw new NotPermittedException(); | |||
} | |||
} | |||
/** | |||
* @param string $targetPath | |||
* @throws \OCP\Files\NotPermittedException | |||
* @return \OC\Files\Node\Node | |||
*/ | |||
public function move($targetPath) { | |||
$targetPath = $this->normalizePath($targetPath); | |||
$parent = $this->root->get(dirname($targetPath)); | |||
if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) { | |||
$nonExisting = new NonExistingFile($this->root, $this->view, $targetPath); | |||
$this->root->emit('\OC\Files', 'preRename', array($this, $nonExisting)); | |||
$this->root->emit('\OC\Files', 'preWrite', array($nonExisting)); | |||
$this->view->rename($this->path, $targetPath); | |||
$targetNode = $this->root->get($targetPath); | |||
$this->root->emit('\OC\Files', 'postRename', array($this, $targetNode)); | |||
$this->root->emit('\OC\Files', 'postWrite', array($targetNode)); | |||
$this->path = $targetPath; | |||
$this->fileInfo = null; | |||
return $targetNode; | |||
} else { | |||
throw new NotPermittedException(); | |||
} | |||
} | |||
/** | |||
* @param string $type | |||
* @param bool $raw |
@@ -35,6 +35,16 @@ use OCP\Files\NotFoundException; | |||
use OCP\Files\NotPermittedException; | |||
class Folder extends Node implements \OCP\Files\Folder { | |||
/** | |||
* Creates a Folder that represents a non-existing path | |||
* | |||
* @param string $path path | |||
* @return string non-existing node class | |||
*/ | |||
protected function createNonExistingNode($path) { | |||
return new NonExistingFolder($this->root, $this->view, $path); | |||
} | |||
/** | |||
* @param string $path path relative to the folder | |||
* @return string | |||
@@ -325,51 +335,6 @@ class Folder extends Node implements \OCP\Files\Folder { | |||
} | |||
} | |||
/** | |||
* @param string $targetPath | |||
* @throws \OCP\Files\NotPermittedException | |||
* @return \OC\Files\Node\Node | |||
*/ | |||
public function copy($targetPath) { | |||
$targetPath = $this->normalizePath($targetPath); | |||
$parent = $this->root->get(dirname($targetPath)); | |||
if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) { | |||
$nonExisting = new NonExistingFolder($this->root, $this->view, $targetPath); | |||
$this->root->emit('\OC\Files', 'preCopy', array($this, $nonExisting)); | |||
$this->root->emit('\OC\Files', 'preWrite', array($nonExisting)); | |||
$this->view->copy($this->path, $targetPath); | |||
$targetNode = $this->root->get($targetPath); | |||
$this->root->emit('\OC\Files', 'postCopy', array($this, $targetNode)); | |||
$this->root->emit('\OC\Files', 'postWrite', array($targetNode)); | |||
return $targetNode; | |||
} else { | |||
throw new NotPermittedException('No permission to copy to path'); | |||
} | |||
} | |||
/** | |||
* @param string $targetPath | |||
* @throws \OCP\Files\NotPermittedException | |||
* @return \OC\Files\Node\Node | |||
*/ | |||
public function move($targetPath) { | |||
$targetPath = $this->normalizePath($targetPath); | |||
$parent = $this->root->get(dirname($targetPath)); | |||
if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) { | |||
$nonExisting = new NonExistingFolder($this->root, $this->view, $targetPath); | |||
$this->root->emit('\OC\Files', 'preRename', array($this, $nonExisting)); | |||
$this->root->emit('\OC\Files', 'preWrite', array($nonExisting)); | |||
$this->view->rename($this->path, $targetPath); | |||
$targetNode = $this->root->get($targetPath); | |||
$this->root->emit('\OC\Files', 'postRename', array($this, $targetNode)); | |||
$this->root->emit('\OC\Files', 'postWrite', array($targetNode)); | |||
$this->path = $targetPath; | |||
return $targetNode; | |||
} else { | |||
throw new NotPermittedException('No permission to move to path'); | |||
} | |||
} | |||
/** | |||
* Add a suffix to the name in case the file exists | |||
* |
@@ -33,6 +33,7 @@ use OCP\Files\InvalidPathException; | |||
use OCP\Files\NotFoundException; | |||
use OCP\Files\NotPermittedException; | |||
// FIXME: this class really should be abstract | |||
class Node implements \OCP\Files\Node { | |||
/** | |||
* @var \OC\Files\View $view | |||
@@ -67,6 +68,16 @@ class Node implements \OCP\Files\Node { | |||
$this->fileInfo = $fileInfo; | |||
} | |||
/** | |||
* Creates a Node of the same type that represents a non-existing path | |||
* | |||
* @param string $path path | |||
* @return string non-existing node class | |||
*/ | |||
protected function createNonExistingNode($path) { | |||
throw new \Exception('Must be implemented by subclasses'); | |||
} | |||
/** | |||
* Returns the matching file info | |||
* | |||
@@ -106,27 +117,10 @@ class Node implements \OCP\Files\Node { | |||
return ($this->getPermissions() & $permissions) === $permissions; | |||
} | |||
/** | |||
* @param string $targetPath | |||
* @throws \OCP\Files\NotPermittedException | |||
* @return \OC\Files\Node\Node | |||
*/ | |||
public function move($targetPath) { | |||
return; | |||
} | |||
public function delete() { | |||
return; | |||
} | |||
/** | |||
* @param string $targetPath | |||
* @return \OC\Files\Node\Node | |||
*/ | |||
public function copy($targetPath) { | |||
return; | |||
} | |||
/** | |||
* @param int $mtime | |||
* @throws \OCP\Files\NotPermittedException | |||
@@ -381,4 +375,54 @@ class Node implements \OCP\Files\Node { | |||
public function unlock($type) { | |||
$this->view->unlockFile($this->path, $type); | |||
} | |||
/** | |||
* @param string $targetPath | |||
* @throws \OCP\Files\NotPermittedException if copy not allowed or failed | |||
* @return \OC\Files\Node\Node | |||
*/ | |||
public function copy($targetPath) { | |||
$targetPath = $this->normalizePath($targetPath); | |||
$parent = $this->root->get(dirname($targetPath)); | |||
if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) { | |||
$nonExisting = $this->createNonExistingNode($targetPath); | |||
$this->root->emit('\OC\Files', 'preCopy', [$this, $nonExisting]); | |||
$this->root->emit('\OC\Files', 'preWrite', [$nonExisting]); | |||
if (!$this->view->copy($this->path, $targetPath)) { | |||
throw new NotPermittedException('Could not copy ' . $this->path . ' to ' . $targetPath); | |||
} | |||
$targetNode = $this->root->get($targetPath); | |||
$this->root->emit('\OC\Files', 'postCopy', [$this, $targetNode]); | |||
$this->root->emit('\OC\Files', 'postWrite', [$targetNode]); | |||
return $targetNode; | |||
} else { | |||
throw new NotPermittedException('No permission to copy to path ' . $targetPath); | |||
} | |||
} | |||
/** | |||
* @param string $targetPath | |||
* @throws \OCP\Files\NotPermittedException if move not allowed or failed | |||
* @return \OC\Files\Node\Node | |||
*/ | |||
public function move($targetPath) { | |||
$targetPath = $this->normalizePath($targetPath); | |||
$parent = $this->root->get(dirname($targetPath)); | |||
if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) { | |||
$nonExisting = $this->createNonExistingNode($targetPath); | |||
$this->root->emit('\OC\Files', 'preRename', [$this, $nonExisting]); | |||
$this->root->emit('\OC\Files', 'preWrite', [$nonExisting]); | |||
if (!$this->view->rename($this->path, $targetPath)) { | |||
throw new NotPermittedException('Could not move ' . $this->path . ' to ' . $targetPath); | |||
} | |||
$targetNode = $this->root->get($targetPath); | |||
$this->root->emit('\OC\Files', 'postRename', [$this, $targetNode]); | |||
$this->root->emit('\OC\Files', 'postWrite', [$targetNode]); | |||
$this->path = $targetPath; | |||
return $targetNode; | |||
} else { | |||
throw new NotPermittedException('No permission to move to path ' . $targetPath); | |||
} | |||
} | |||
} |
@@ -16,9 +16,6 @@ namespace Test\Files\Node; | |||
* @package Test\Files\Node | |||
*/ | |||
class FileTest extends NodeTest { | |||
public $viewDeleteMethod = 'unlink'; | |||
protected function createTestNode($root, $view, $path) { | |||
return new \OC\Files\Node\File($root, $view, $path); | |||
} |
@@ -614,7 +614,6 @@ abstract class NodeTest extends \Test\TestCase { | |||
->method('rename'); | |||
$node = $this->createTestNode($this->root, $this->view, '/bar/foo'); | |||
$parentNode = new \OC\Files\Node\Folder($this->root, $this->view, '/bar'); | |||
$this->root->expects($this->once()) | |||
->method('get') | |||
@@ -641,4 +640,50 @@ abstract class NodeTest extends \Test\TestCase { | |||
$node->move('/bar/asd'); | |||
} | |||
/** | |||
* @expectedException \OCP\Files\NotPermittedException | |||
*/ | |||
public function testMoveFailed() { | |||
$this->view->expects($this->any()) | |||
->method('rename') | |||
->with('/bar/foo', '/bar/asd') | |||
->will($this->returnValue(false)); | |||
$this->view->expects($this->any()) | |||
->method('getFileInfo') | |||
->will($this->returnValue($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL, 'fileid' => 1]))); | |||
$node = $this->createTestNode($this->root, $this->view, '/bar/foo'); | |||
$parentNode = new \OC\Files\Node\Folder($this->root, $this->view, '/bar'); | |||
$this->root->expects($this->any()) | |||
->method('get') | |||
->will($this->returnValueMap([['/bar', $parentNode], ['/bar/asd', $node]])); | |||
$node->move('/bar/asd'); | |||
} | |||
/** | |||
* @expectedException \OCP\Files\NotPermittedException | |||
*/ | |||
public function testCopyFailed() { | |||
$this->view->expects($this->any()) | |||
->method('copy') | |||
->with('/bar/foo', '/bar/asd') | |||
->will($this->returnValue(false)); | |||
$this->view->expects($this->any()) | |||
->method('getFileInfo') | |||
->will($this->returnValue($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL, 'fileid' => 1]))); | |||
$node = $this->createTestNode($this->root, $this->view, '/bar/foo'); | |||
$parentNode = new \OC\Files\Node\Folder($this->root, $this->view, '/bar'); | |||
$this->root->expects($this->any()) | |||
->method('get') | |||
->will($this->returnValueMap([['/bar', $parentNode], ['/bar/asd', $node]])); | |||
$node->copy('/bar/asd'); | |||
} | |||
} |