From ceaac03bb5512f925e43bdf8574977ea8e056e62 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Wed, 11 May 2016 19:41:36 +0200 Subject: [PATCH] Make permalinks work for trashed files (#24537) Opening a permalink that points to a trashed file will now display the file within the "Deleted Files" section in the files web UI. --- apps/files/appinfo/application.php | 3 +- apps/files/controller/viewcontroller.php | 52 +++++--- .../tests/controller/ViewControllerTest.php | 114 ++++++++++++++++-- 3 files changed, 139 insertions(+), 30 deletions(-) diff --git a/apps/files/appinfo/application.php b/apps/files/appinfo/application.php index 3dd7303787..b2faa43cc3 100644 --- a/apps/files/appinfo/application.php +++ b/apps/files/appinfo/application.php @@ -59,7 +59,8 @@ class Application extends App { $server->getConfig(), $server->getEventDispatcher(), $server->getUserSession(), - $server->getUserFolder() + $server->getAppManager(), + $server->getRootFolder() ); }); diff --git a/apps/files/controller/viewcontroller.php b/apps/files/controller/viewcontroller.php index 6ee924e2f0..7539a3ab64 100644 --- a/apps/files/controller/viewcontroller.php +++ b/apps/files/controller/viewcontroller.php @@ -39,6 +39,7 @@ use OCP\IUserSession; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use OCP\AppFramework\Http\NotFoundResponse; use OCP\Files\Folder; +use OCP\App\IAppManager; /** * Class ViewController @@ -62,8 +63,10 @@ class ViewController extends Controller { protected $eventDispatcher; /** @var IUserSession */ protected $userSession; + /** @var IAppManager */ + protected $appManager; /** @var \OCP\Files\Folder */ - protected $userFolder; + protected $rootFolder; /** * @param string $appName @@ -74,7 +77,8 @@ class ViewController extends Controller { * @param IConfig $config * @param EventDispatcherInterface $eventDispatcherInterface * @param IUserSession $userSession - * @param Folder $userFolder + * @param IAppManager $appManager + * @param Folder $rootFolder */ public function __construct($appName, IRequest $request, @@ -84,7 +88,8 @@ class ViewController extends Controller { IConfig $config, EventDispatcherInterface $eventDispatcherInterface, IUserSession $userSession, - Folder $userFolder + IAppManager $appManager, + Folder $rootFolder ) { parent::__construct($appName, $request); $this->appName = $appName; @@ -95,7 +100,8 @@ class ViewController extends Controller { $this->config = $config; $this->eventDispatcher = $eventDispatcherInterface; $this->userSession = $userSession; - $this->userFolder = $userFolder; + $this->appManager = $appManager; + $this->rootFolder = $rootFolder; } /** @@ -265,21 +271,33 @@ class ViewController extends Controller { * @NoAdminRequired */ public function showFile($fileId) { - $files = $this->userFolder->getById($fileId); - $params = []; + try { + $uid = $this->userSession->getUser()->getUID(); + $baseFolder = $this->rootFolder->get($uid . '/files/'); + $files = $baseFolder->getById($fileId); + $params = []; - if (!empty($files)) { - $file = current($files); - if ($file instanceof Folder) { - // set the full path to enter the folder - $params['dir'] = $this->userFolder->getRelativePath($file->getPath()); - } else { - // set parent path as dir - $params['dir'] = $this->userFolder->getRelativePath($file->getParent()->getPath()); - // and scroll to the entry - $params['scrollto'] = $file->getName(); + if (empty($files) && $this->appManager->isEnabledForUser('files_trashbin')) { + $baseFolder = $this->rootFolder->get($uid . '/files_trashbin/files/'); + $files = $baseFolder->getById($fileId); + $params['view'] = 'trashbin'; } - return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index', $params)); + + if (!empty($files)) { + $file = current($files); + if ($file instanceof Folder) { + // set the full path to enter the folder + $params['dir'] = $baseFolder->getRelativePath($file->getPath()); + } else { + // set parent path as dir + $params['dir'] = $baseFolder->getRelativePath($file->getParent()->getPath()); + // and scroll to the entry + $params['scrollto'] = $file->getName(); + } + return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index', $params)); + } + } catch (\OCP\Files\NotFoundException $e) { + return new NotFoundResponse(); } return new NotFoundResponse(); } diff --git a/apps/files/tests/controller/ViewControllerTest.php b/apps/files/tests/controller/ViewControllerTest.php index 797702def6..4e4e88043e 100644 --- a/apps/files/tests/controller/ViewControllerTest.php +++ b/apps/files/tests/controller/ViewControllerTest.php @@ -37,6 +37,7 @@ use OCP\IConfig; use OCP\IUserSession; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use OCP\Files\Folder; +use OCP\App\IAppManager; /** * Class ViewControllerTest @@ -62,8 +63,10 @@ class ViewControllerTest extends TestCase { private $user; /** @var IUserSession */ private $userSession; + /** @var IAppManager */ + private $appManager; /** @var Folder */ - private $userFolder; + private $rootFolder; public function setUp() { parent::setUp(); @@ -74,11 +77,15 @@ class ViewControllerTest extends TestCase { $this->config = $this->getMock('\OCP\IConfig'); $this->eventDispatcher = $this->getMock('\Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->userSession = $this->getMock('\OCP\IUserSession'); + $this->appManager = $this->getMock('\OCP\App\IAppManager'); $this->user = $this->getMock('\OCP\IUser'); + $this->user->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('testuser1')); $this->userSession->expects($this->any()) ->method('getUser') ->will($this->returnValue($this->user)); - $this->userFolder = $this->getMock('\OCP\Files\Folder'); + $this->rootFolder = $this->getMock('\OCP\Files\Folder'); $this->viewController = $this->getMockBuilder('\OCA\Files\Controller\ViewController') ->setConstructorArgs([ 'files', @@ -89,7 +96,8 @@ class ViewControllerTest extends TestCase { $this->config, $this->eventDispatcher, $this->userSession, - $this->userFolder + $this->appManager, + $this->rootFolder ]) ->setMethods([ 'getStorageInfo', @@ -307,15 +315,22 @@ class ViewControllerTest extends TestCase { $node = $this->getMock('\OCP\Files\Folder'); $node->expects($this->once()) ->method('getPath') - ->will($this->returnValue('/user/files/test/sub')); + ->will($this->returnValue('/testuser1/files/test/sub')); - $this->userFolder->expects($this->at(0)) + $baseFolder = $this->getMock('\OCP\Files\Folder'); + + $this->rootFolder->expects($this->once()) + ->method('get') + ->with('testuser1/files/') + ->will($this->returnValue($baseFolder)); + + $baseFolder->expects($this->at(0)) ->method('getById') ->with(123) ->will($this->returnValue([$node])); - $this->userFolder->expects($this->at(1)) + $baseFolder->expects($this->at(1)) ->method('getRelativePath') - ->with('/user/files/test/sub') + ->with('/testuser1/files/test/sub') ->will($this->returnValue('/test/sub')); $this->urlGenerator @@ -339,7 +354,14 @@ class ViewControllerTest extends TestCase { $parentNode = $this->getMock('\OCP\Files\Folder'); $parentNode->expects($this->once()) ->method('getPath') - ->will($this->returnValue('/user/files/test')); + ->will($this->returnValue('testuser1/files/test')); + + $baseFolder = $this->getMock('\OCP\Files\Folder'); + + $this->rootFolder->expects($this->once()) + ->method('get') + ->with('testuser1/files/') + ->will($this->returnValue($baseFolder)); $node = $this->getMock('\OCP\Files\File'); $node->expects($this->once()) @@ -349,13 +371,13 @@ class ViewControllerTest extends TestCase { ->method('getName') ->will($this->returnValue('somefile.txt')); - $this->userFolder->expects($this->at(0)) + $baseFolder->expects($this->at(0)) ->method('getById') ->with(123) ->will($this->returnValue([$node])); - $this->userFolder->expects($this->at(1)) + $baseFolder->expects($this->at(1)) ->method('getRelativePath') - ->with('/user/files/test') + ->with('testuser1/files/test') ->will($this->returnValue('/test')); $this->urlGenerator @@ -376,7 +398,13 @@ class ViewControllerTest extends TestCase { * @dataProvider showFileMethodProvider */ public function testShowFileRouteWithInvalidFileId($useShowFile) { - $this->userFolder->expects($this->at(0)) + $baseFolder = $this->getMock('\OCP\Files\Folder'); + $this->rootFolder->expects($this->once()) + ->method('get') + ->with('testuser1/files/') + ->will($this->returnValue($baseFolder)); + + $baseFolder->expects($this->at(0)) ->method('getById') ->with(123) ->will($this->returnValue([])); @@ -388,4 +416,66 @@ class ViewControllerTest extends TestCase { $this->assertEquals($expected, $this->viewController->index('/whatever', '', '123')); } } + + /** + * @dataProvider showFileMethodProvider + */ + public function testShowFileRouteWithTrashedFile($useShowFile) { + $this->appManager->expects($this->once()) + ->method('isEnabledForUser') + ->with('files_trashbin') + ->will($this->returnValue(true)); + + $parentNode = $this->getMock('\OCP\Files\Folder'); + $parentNode->expects($this->once()) + ->method('getPath') + ->will($this->returnValue('testuser1/files_trashbin/files/test.d1462861890/sub')); + + $baseFolderFiles = $this->getMock('\OCP\Files\Folder'); + $baseFolderTrash = $this->getMock('\OCP\Files\Folder'); + + $this->rootFolder->expects($this->at(0)) + ->method('get') + ->with('testuser1/files/') + ->will($this->returnValue($baseFolderFiles)); + $this->rootFolder->expects($this->at(1)) + ->method('get') + ->with('testuser1/files_trashbin/files/') + ->will($this->returnValue($baseFolderTrash)); + + $baseFolderFiles->expects($this->once()) + ->method('getById') + ->with(123) + ->will($this->returnValue([])); + + $node = $this->getMock('\OCP\Files\File'); + $node->expects($this->once()) + ->method('getParent') + ->will($this->returnValue($parentNode)); + $node->expects($this->once()) + ->method('getName') + ->will($this->returnValue('somefile.txt')); + + $baseFolderTrash->expects($this->at(0)) + ->method('getById') + ->with(123) + ->will($this->returnValue([$node])); + $baseFolderTrash->expects($this->at(1)) + ->method('getRelativePath') + ->with('testuser1/files_trashbin/files/test.d1462861890/sub') + ->will($this->returnValue('/test.d1462861890/sub')); + + $this->urlGenerator + ->expects($this->once()) + ->method('linkToRoute') + ->with('files.view.index', ['view' => 'trashbin', 'dir' => '/test.d1462861890/sub', 'scrollto' => 'somefile.txt']) + ->will($this->returnValue('/apps/files/?view=trashbin&dir=/test.d1462861890/sub&scrollto=somefile.txt')); + + $expected = new Http\RedirectResponse('/apps/files/?view=trashbin&dir=/test.d1462861890/sub&scrollto=somefile.txt'); + if ($useShowFile) { + $this->assertEquals($expected, $this->viewController->showFile(123)); + } else { + $this->assertEquals($expected, $this->viewController->index('/whatever', '', '123')); + } + } }