diff options
-rw-r--r-- | lib/Controller/FolderApiV2Controller.php | 130 | ||||
-rw-r--r-- | lib/Db/FolderMapperV2.php | 21 | ||||
-rw-r--r-- | lib/Service/FolderServiceV2.php | 11 | ||||
-rw-r--r-- | tests/Unit/Controller/FolderApiV2ControllerTest.php | 289 |
4 files changed, 451 insertions, 0 deletions
diff --git a/lib/Controller/FolderApiV2Controller.php b/lib/Controller/FolderApiV2Controller.php new file mode 100644 index 000000000..ea788c686 --- /dev/null +++ b/lib/Controller/FolderApiV2Controller.php @@ -0,0 +1,130 @@ +<?php +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Paul Tirk <paultirk@paultirk.com> + * @copyright 2020 Paul Tirk + */ + +namespace OCA\News\Controller; + +use \OCP\IRequest; +use \OCP\IUserSession; +use \OCP\AppFramework\Http; + +use \OCA\News\Service\FolderServiceV2; +use \OCA\News\Service\ItemServiceV2; +use \OCA\News\Service\Exceptions\ServiceNotFoundException; +use \OCA\News\Service\Exceptions\ServiceConflictException; +use \OCA\News\Service\Exceptions\ServiceValidationException; + +class FolderApiV2Controller extends ApiController +{ + use ApiV2ResponseTrait; + + private $folderService; + private $itemService; + + public function __construct( + IRequest $request, + IUserSession $userSession, + FolderServiceV2 $folderService, + ItemServiceV2 $itemService + ) { + parent::__construct($request, $userSession); + + $this->folderService = $folderService; + $this->itemService = $itemService; + } + + /** + * @NoAdminRequired + * @NoCSRFRequired + * @CORS + * + * @param string $name + * @return array|mixed|\OCP\AppFramework\Http\JSONResponse + */ + public function createFolder($name) + { + try { + $this->folderService->purgeDeleted($this->getUserId(), false); + $responseData = $this->serialize( + $this->folderService->create($this->getUserId(), $name) + ); + return $this->response([ + 'folder' => $responseData + ]); + } catch (ServiceValidationException $ex) { + return $this->errorResponse($ex, Http::STATUS_BAD_REQUEST); + } catch (ServiceConflictException $ex) { + $responseData = $this->serialize( + $this->folderService->findByName($this->getUserId(), $name) + ); + return $this->response([ + 'folder' => $responseData + ], Http::STATUS_CONFLICT); + } + } + + /** + * @NoAdminRequired + * @NoCSRFRequired + * @CORS + * @param int $folderId + * @param string $name + * @return array|\OCP\AppFramework\Http\JSONResponse + */ + public function updateFolder($folderId, $name) + { + $response = null; + try { + $response = $this->folderService->rename($this->getUserId(), $folderId, $name); + } catch (ServiceValidationException $ex) { + return $this->errorResponse($ex, Http::STATUS_UNPROCESSABLE_ENTITY); + } catch (ServiceConflictException $ex) { + $responseData = $this->serialize( + $this->folderService->findByName($this->getUserId(), $name) + ); + return $this->response( + [ + 'folder' => $responseData + ], + Http::STATUS_CONFLICT + ); + } catch (ServiceNotFoundException $ex) { + return $this->errorResponse($ex, Http::STATUS_NOT_FOUND); + } + + return $this->response([ + 'folder' => $response + ]); + } + + + /** + * @NoAdminRequired + * @NoCSRFRequired + * @CORS + * + * @param int $folderId + * @return array|\OCP\AppFramework\Http\JSONResponse + */ + public function deleteFolder($folderId) + { + try { + $responseData = $this->serialize( + $this->folderService->delete($this->getUserId(), $folderId) + ); + return $this->response([ + 'folder' => $responseData + ]); + } catch (ServiceNotFoundException $ex) { + return $this->errorResponse($ex, Http::STATUS_NOT_FOUND); + } + } + +} diff --git a/lib/Db/FolderMapperV2.php b/lib/Db/FolderMapperV2.php index d0d0cbec1..3b71460e4 100644 --- a/lib/Db/FolderMapperV2.php +++ b/lib/Db/FolderMapperV2.php @@ -40,6 +40,27 @@ class FolderMapperV2 extends NewsMapperV2 } /** + * Find feed by name + * + * @param string $userId The user identifier + * @param string $folderName The folder name + * + * @return Folder + */ + public function findByName(string $userId, string $folderName): Folder + { + $builder = $this->db->getQueryBuilder(); + $builder->select('*') + ->from($this->tableName) + ->where('name = :folder_name') + ->andWhere('user_id = :user_id') + ->setParameter(':folder_name', $folderName) + ->setParameter(':user_id', $userId); + + return $this->findEntity($builder); + } + + /** * Find all feeds for a user. * * @param string $userId The user identifier diff --git a/lib/Service/FolderServiceV2.php b/lib/Service/FolderServiceV2.php index 17d955876..827ca4bfb 100644 --- a/lib/Service/FolderServiceV2.php +++ b/lib/Service/FolderServiceV2.php @@ -49,6 +49,17 @@ class FolderServiceV2 extends Service } /** + * @param $userId + * @param $folderName + * + * @return Folder + */ + public function findByName($userId, $folderName) + { + return $this->mapper->findByName($userId, $folderName); + } + + /** * Finds all folders of a user * * @param string $userId The name/ID of the user diff --git a/tests/Unit/Controller/FolderApiV2ControllerTest.php b/tests/Unit/Controller/FolderApiV2ControllerTest.php new file mode 100644 index 000000000..10c18040c --- /dev/null +++ b/tests/Unit/Controller/FolderApiV2ControllerTest.php @@ -0,0 +1,289 @@ +<?php +/** + * Nextcloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Alessandro Cosentino <cosenal@gmail.com> + * @author Bernhard Posselt <dev@bernhard-posselt.com> + * @author David Guillot <david@guillot.me> + * @copyright 2012 Alessandro Cosentino + * @copyright 2012-2014 Bernhard Posselt + * @copyright 2018 David Guillot + */ + +namespace OCA\News\Tests\Unit\Controller; + +use OCA\News\Controller\FolderApiV2Controller; +use OCA\News\Service\FolderServiceV2; +use OCA\News\Service\ItemServiceV2; +use \OCP\AppFramework\Http; + +use \OCA\News\Service\Exceptions\ServiceNotFoundException; +use \OCA\News\Service\Exceptions\ServiceConflictException; +use \OCA\News\Service\Exceptions\ServiceValidationException; + +use \OCA\News\Db\Folder; +use OCP\IRequest; +use OCP\IUser; +use OCP\IUserSession; + +use PHPUnit\Framework\TestCase; + + +class FolderApiV2ControllerTest extends TestCase +{ + + private $folderService; + private $itemService; + private $folderAPI; + private $userSession; + private $user; + private $request; + private $msg; + + protected function setUp(): void + { + $this->request = $this->getMockBuilder(IRequest::class) + ->disableOriginalConstructor() + ->getMock(); + $this->userSession = $this->getMockBuilder(IUserSession::class) + ->disableOriginalConstructor() + ->getMock(); + $this->user = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $this->userSession->expects($this->any()) + ->method('getUser') + ->will($this->returnValue($this->user)); + $this->user->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('123')); + $this->folderService = $this->getMockBuilder(FolderServiceV2::class) + ->disableOriginalConstructor() + ->getMock(); + $this->itemService = $this->getMockBuilder(ItemServiceV2::class) + ->disableOriginalConstructor() + ->getMock(); + $this->folderAPI = new FolderApiV2Controller( + $this->request, + $this->userSession, + $this->folderService, + $this->itemService + ); + $this->msg = 'test'; + } + + public function testCreate() + { + $folderName = 'test'; + $folder = new Folder(); + $folder->setName($folderName); + + $this->folderService->expects($this->once()) + ->method('purgeDeleted') + ->with($this->equalTo($this->user->getUID()), $this->equalTo(false)); + $this->folderService->expects($this->once()) + ->method('create') + ->with($this->equalTo($this->user->getUID()), $this->equalTo($folderName)) + ->will($this->returnValue($folder)); + + $response = $this->folderAPI->createFolder($folderName); + + $data = $response->getData(); + $this->assertEquals( + [ + 'folder' => $folder->toAPI2() + ], + $data + ); + } + + + public function testCreateAlreadyExists() + { + $existingFolder = new Folder(); + $folderName = 'hi'; + + $this->folderService->expects($this->once()) + ->method('purgeDeleted') + ->with($this->equalTo($this->user->getUID()), $this->equalTo(false)); + $this->folderService->expects($this->once()) + ->method('create') + ->will($this->throwException(new ServiceConflictException('exists'))); + $this->folderService->expects($this->once()) + ->method('findByName') + ->with($this->equalTo(($this->user->getUID()), $this->equalTo($folderName))) + ->will($this->returnValue($existingFolder)); + + $response = $this->folderAPI->createFolder('hi'); + + $data = $response->getData(); + $this->assertEquals( + [ + 'folder' => $existingFolder->toAPI2() + ], + $data + ); + $this->assertEquals(Http::STATUS_CONFLICT, $response->getStatus()); + } + + + public function testCreateInvalidFolderName() + { + $msg = 'exists'; + + $this->folderService->expects($this->once()) + ->method('purgeDeleted') + ->with($this->equalTo($this->user->getUID()), $this->equalTo(false)); + $this->folderService->expects($this->once()) + ->method('create') + ->will($this->throwException(new ServiceValidationException($msg))); + + $response = $this->folderAPI->createFolder('hi'); + + $data = $response->getData(); + $this->assertEquals($msg, $data['error']['message']); + $this->assertEquals( + Http::STATUS_BAD_REQUEST, $response->getStatus() + ); + } + + + public function testDelete() + { + $folderId = 23; + $folder = new Folder(); + + $this->folderService->expects($this->once()) + ->method('delete') + ->with($this->equalTo($this->user->getUID()), $this->equalTo($folderId)) + ->will($this->returnValue($folder)); + + $response = $this->folderAPI->deleteFolder(23); + + $data = $response->getData(); + $this->assertEquals( + [ + 'folder' => $folder->toAPI2() + ], + $data + ); + } + + + public function testDeleteDoesNotExist() + { + $folderId = 23; + + $this->folderService->expects($this->once()) + ->method('delete') + ->will( + $this->throwException( + new ServiceNotFoundException($this->msg) + ) + ); + + $response = $this->folderAPI->deleteFolder($folderId); + + $data = $response->getData(); + $this->assertEquals($this->msg, $data['error']['message']); + $this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus()); + } + + + public function testUpdate() + { + $folderId = 23; + $folderName = 'test'; + + $this->folderService->expects($this->once()) + ->method('rename') + ->with( + $this->equalTo($this->user->getUID(), + $this->equalTo($folderId), + $this->equalTo($folderName)) + ); + + $this->folderAPI->updateFolder($folderId, $folderName); + } + + public function testUpdateDoesNotExist() + { + $folderId = 23; + $folderName = 'test'; + + $this->folderService->expects($this->once()) + ->method('rename') + ->will( + $this->throwException( + new ServiceNotFoundException($this->msg) + ) + ); + + $response = $this->folderAPI->updateFolder($folderId, $folderName); + + $data = $response->getData(); + $this->assertEquals($this->msg, $data['error']['message']); + $this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus()); + } + + + public function testUpdateExists() + { + $folderId = 23; + $folderName = 'test'; + $existingFolder = new Folder(); + + $this->folderService->expects($this->once()) + ->method('rename') + ->will( + $this->throwException( + new ServiceConflictException($this->msg) + ) + ); + $this->folderService->expects($this->once()) + ->method('findByName') + ->with( + $this->equalTo($this->user->getUID()), + $this->equalTo($folderName) + ) + ->will($this->returnValue($existingFolder)); + + $response = $this->folderAPI->updateFolder($folderId, $folderName); + + $data = $response->getData(); + $this->assertEquals( + [ + 'folder' => $existingFolder->toAPI2() + ], + $data + ); + $this->assertEquals(Http::STATUS_CONFLICT, $response->getStatus()); + } + + + public function testUpdateInvalidFolderName() + { + $folderId = 23; + $folderName = ''; + + $this->folderService->expects($this->once()) + ->method('rename') + ->will( + $this->throwException( + new ServiceValidationException($this->msg) + ) + ); + + $response = $this->folderAPI->updateFolder($folderId, $folderName); + + $data = $response->getData(); + $this->assertEquals($this->msg, $data['error']['message']); + $this->assertEquals( + Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus() + ); + } + +} |