From 7a4f368c21d09f7045fd27465318bbfca71cf8aa Mon Sep 17 00:00:00 2001 From: korelstar Date: Mon, 10 Apr 2017 20:55:37 +0200 Subject: [PATCH 1/3] add API to change the category (move note to subdirectory) --- controller/notesapicontroller.php | 18 +++++---- service/notesservice.php | 37 +++++++++++++++++-- .../controller/NotesApiControllerTest.php | 2 +- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/controller/notesapicontroller.php b/controller/notesapicontroller.php index 4f55b3f93..31f733f0c 100644 --- a/controller/notesapicontroller.php +++ b/controller/notesapicontroller.php @@ -108,14 +108,15 @@ public function get($id, $exclude='') { * @NoCSRFRequired * * @param string $content + * @param string $category * @param int $modified * @param boolean $favorite * @return DataResponse */ - public function create($content, $modified=0, $favorite=null) { - return $this->respond(function () use ($content, $modified, $favorite) { + public function create($content, $category=null, $modified=0, $favorite=null) { + return $this->respond(function () use ($content, $category, $modified, $favorite) { $note = $this->service->create($this->userId); - return $this->updateData($note->getId(), $content, $modified, $favorite); + return $this->updateData($note->getId(), $content, $category, $modified, $favorite); }); } @@ -127,13 +128,14 @@ public function create($content, $modified=0, $favorite=null) { * * @param int $id * @param string $content + * @param string $category * @param int $modified * @param boolean $favorite * @return DataResponse */ - public function update($id, $content=null, $modified=0, $favorite=null) { - return $this->respond(function () use ($id, $content, $modified, $favorite) { - return $this->updateData($id, $content, $modified, $favorite); + public function update($id, $content=null, $category=null, $modified=0, $favorite=null) { + return $this->respond(function () use ($id, $content, $category, $modified, $favorite) { + return $this->updateData($id, $content, $category, $modified, $favorite); }); } @@ -145,14 +147,14 @@ public function update($id, $content=null, $modified=0, $favorite=null) { * @param boolean $favorite * @return Note */ - private function updateData($id, $content, $modified, $favorite) { + private function updateData($id, $content, $category, $modified, $favorite) { if($favorite!==null) { $this->service->favorite($id, $favorite, $this->userId); } if($content===null) { return $this->service->get($id, $this->userId); } else { - return $this->service->update($id, $content, $this->userId, $modified); + return $this->service->update($id, $content, $this->userId, $category, $modified); } } diff --git a/service/notesservice.php b/service/notesservice.php index b14006b14..3e50cd08c 100644 --- a/service/notesservice.php +++ b/service/notesservice.php @@ -117,7 +117,7 @@ public function create ($userId) { * @throws NoteDoesNotExistException if note does not exist * @return \OCA\Notes\Db\Note the updated note */ - public function update ($id, $content, $userId, $mtime=0) { + public function update ($id, $content, $userId, $category=null, $mtime=0) { $notesFolder = $this->getFolderForUser($userId); $file = $this->getFileById($notesFolder, $id); $folder = $file->getParent(); @@ -140,7 +140,15 @@ public function update ($id, $content, $userId, $mtime=0) { // generate filename if there were collisions $currentFilePath = $file->getPath(); - $basePath = pathinfo($file->getPath(), PATHINFO_DIRNAME); + if($category===null) { + $basePath = pathinfo($file->getPath(), PATHINFO_DIRNAME); + } else { + $basePath = $notesFolder->getPath(); + $categoryPath = $this->getCategoryPath($category); + if(!empty($categoryPath)) + $basePath .= '/'.$categoryPath; + $this->getOrCreateFolder($basePath); + } $fileExtension = pathinfo($file->getName(), PATHINFO_EXTENSION); $newFilePath = $basePath . '/' . $this->generateFileName($folder, $title, $fileExtension, $id); @@ -179,7 +187,7 @@ public function favorite ($id, $favorite, $userId){ $tagger->removeFromFavorites($id); $tags = $tagger->getTagsForObjects([$id]); - return in_array(\OC\Tags::TAG_FAVORITE, $tags[$id]); + return array_key_exists($id, $tags) && in_array(\OC\Tags::TAG_FAVORITE, $tags[$id]); } @@ -219,6 +227,16 @@ private function getFileById ($folder, $id) { */ private function getFolderForUser ($userId) { $path = '/' . $userId . '/files/Notes'; + return $this->getOrCreateFolder($path); + } + + + /** + * Finds a folder and creates it if non-existent + * @param string $path path to the folder + * @return Folder + */ + private function getOrCreateFolder($path) { if ($this->root->nodeExists($path)) { $folder = $this->root->get($path); } else { @@ -262,6 +280,19 @@ private function generateFileName (Folder $folder, $title, $extension, $id) { } } + private function getCategoryPath($category) { + $category = str_replace('\\', '/', $category); + $folders = explode('/', $category); + $cleanedFolders = []; + foreach($folders as $folder) { + $folder = trim($folder); + $folder = preg_replace('/^\.+\s*/', '', $folder); + if(!empty($folder)) { + $cleanedFolders[] = $folder; + } + } + return implode('/', $cleanedFolders); + } /** * gather note files in given directory and all subdirectories diff --git a/tests/integration/controller/NotesApiControllerTest.php b/tests/integration/controller/NotesApiControllerTest.php index 1d101d27a..9f272f7d3 100644 --- a/tests/integration/controller/NotesApiControllerTest.php +++ b/tests/integration/controller/NotesApiControllerTest.php @@ -54,7 +54,7 @@ public function testUpdate() { $this->assertEquals($note->getId(), $note2->getId()); $this->assertNotEquals($t, $note2->getModified()); - $note3 = $this->controller->update($note->getId(), 'test3', $t)->getData(); + $note3 = $this->controller->update($note->getId(), 'test3', null, $t)->getData(); $this->assertEquals('test3', $note3->getContent()); $this->assertEquals($note->getId(), $note3->getId()); $this->assertEquals($t, $note3->getModified()); From 3b56e4ed39f040bc25581ba63b65f6b8a3da85ab Mon Sep 17 00:00:00 2001 From: korelstar Date: Fri, 19 May 2017 08:34:13 +0200 Subject: [PATCH 2/3] don't prepare category name --- service/notesservice.php | 54 ++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/service/notesservice.php b/service/notesservice.php index 3e50cd08c..9b30613f3 100644 --- a/service/notesservice.php +++ b/service/notesservice.php @@ -138,23 +138,31 @@ public function update ($id, $content, $userId, $category=null, $mtime=0) { // using a maximum of 100 chars should be enough $title = mb_substr($title, 0, 100, "UTF-8"); - // generate filename if there were collisions - $currentFilePath = $file->getPath(); - if($category===null) { - $basePath = pathinfo($file->getPath(), PATHINFO_DIRNAME); - } else { - $basePath = $notesFolder->getPath(); - $categoryPath = $this->getCategoryPath($category); - if(!empty($categoryPath)) - $basePath .= '/'.$categoryPath; - $this->getOrCreateFolder($basePath); - } - $fileExtension = pathinfo($file->getName(), PATHINFO_EXTENSION); - $newFilePath = $basePath . '/' . $this->generateFileName($folder, $title, $fileExtension, $id); - // if the current path is not the new path, the file has to be renamed - if($currentFilePath !== $newFilePath) { - $file->move($newFilePath); + // rename/move file with respect to title/category + // this can fail if access rights are not sufficient or category name is illegal + try { + $currentFilePath = $file->getPath(); + $fileExtension = pathinfo($file->getName(), PATHINFO_EXTENSION); + + // detect (new) folder path based on category name + if($category===null) { + $basePath = pathinfo($file->getPath(), PATHINFO_DIRNAME); + } else { + $basePath = $notesFolder->getPath(); + if(!empty($category)) + $basePath .= '/'.$category; + $this->getOrCreateFolder($basePath); + } + + // assemble new file path + $newFilePath = $basePath . '/' . $this->generateFileName($folder, $title, $fileExtension, $id); + + // if the current path is not the new path, the file has to be renamed + if($currentFilePath !== $newFilePath) { + $file->move($newFilePath); + } + } catch(\Exception $e) { } $file->putContent($content); @@ -280,20 +288,6 @@ private function generateFileName (Folder $folder, $title, $extension, $id) { } } - private function getCategoryPath($category) { - $category = str_replace('\\', '/', $category); - $folders = explode('/', $category); - $cleanedFolders = []; - foreach($folders as $folder) { - $folder = trim($folder); - $folder = preg_replace('/^\.+\s*/', '', $folder); - if(!empty($folder)) { - $cleanedFolders[] = $folder; - } - } - return implode('/', $cleanedFolders); - } - /** * gather note files in given directory and all subdirectories * @param Folder $folder From 8f2ba891b97d64123b179f5d57d21d0796596b99 Mon Sep 17 00:00:00 2001 From: korelstar Date: Tue, 6 Jun 2017 08:02:17 +0200 Subject: [PATCH 3/3] log (specific) exception on file movement --- service/notesservice.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/service/notesservice.php b/service/notesservice.php index 9b30613f3..06b3149a6 100644 --- a/service/notesservice.php +++ b/service/notesservice.php @@ -15,6 +15,7 @@ use OCP\IL10N; use OCP\Files\IRootFolder; use OCP\Files\Folder; +use OCP\ILogger; use OCA\Notes\Db\Note; @@ -27,14 +28,20 @@ class NotesService { private $l10n; private $root; + private $logger; + private $appName; /** * @param IRootFolder $root * @param IL10N $l10n + * @param ILogger $logger + * @param String $appName */ - public function __construct (IRootFolder $root, IL10N $l10n) { + public function __construct (IRootFolder $root, IL10N $l10n, ILogger $logger, $appName) { $this->root = $root; $this->l10n = $l10n; + $this->logger = $logger; + $this->appName = $appName; } @@ -162,7 +169,8 @@ public function update ($id, $content, $userId, $category=null, $mtime=0) { if($currentFilePath !== $newFilePath) { $file->move($newFilePath); } - } catch(\Exception $e) { + } catch(\OCP\Files\NotPermittedException $e) { + $this->logger->error('Moving this note to the desired target is not allowed. Please check the note\'s target category.', array('app' => $this->appName)); } $file->putContent($content);