From f169bef0eb2f9dd72819a82032c75977e64be93b Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Sat, 25 Oct 2014 23:04:43 +0200 Subject: [PATCH] Added note CRUD to backend --- data/config.ini | 4 + public_html/js/Auth.js | 4 + src/Controllers/PostNotesController.php | 77 +++++++++++++++++ src/Controllers/ViewProxies/PostViewProxy.php | 2 +- src/Dao/PostNoteDao.php | 21 ++++- src/Entities/PostNote.php | 13 +++ src/FormData/PostNoteFormData.php | 30 +++++++ src/Privilege.php | 4 + src/Services/PostNotesService.php | 85 ++++++++++++++++++- src/di.php | 1 + tests/Dao/PostNoteDaoTest.php | 17 +++- 11 files changed, 251 insertions(+), 7 deletions(-) create mode 100644 src/Controllers/PostNotesController.php create mode 100644 src/FormData/PostNoteFormData.php diff --git a/data/config.ini b/data/config.ini index bc911e44..d17520ed 100644 --- a/data/config.ini +++ b/data/config.ini @@ -57,6 +57,10 @@ changePostThumbnail = powerUser, moderator, administrator changePostRelations = regularUser, powerUser, moderator, administrator changePostFlags = regularUser, powerUser, moderator, administrator +addPostNotes = powerUser, moderator, administrator +editPostNotes = powerUser, moderator, administrator +deletePostNotes = powerUser, moderator, administrator + listTags = regularUser, powerUser, moderator, administrator massTag = powerUser, moderator, administrator changeTagName = moderator, administrator diff --git a/public_html/js/Auth.js b/public_html/js/Auth.js index 986be93b..e2d9ed05 100644 --- a/public_html/js/Auth.js +++ b/public_html/js/Auth.js @@ -35,6 +35,10 @@ App.Auth = function(_, jQuery, util, api, appState, promise) { changePostRelations: 'changePostRelations', changePostFlags: 'changePostFlags', + addPostNotes: 'addPostNotes', + editPostNotes: 'editPostNotes', + deletePostNotes: 'deletePostNotes', + listComments: 'listComments', addComments: 'addComments', editOwnComments: 'editOwnComments', diff --git a/src/Controllers/PostNotesController.php b/src/Controllers/PostNotesController.php new file mode 100644 index 00000000..83124ded --- /dev/null +++ b/src/Controllers/PostNotesController.php @@ -0,0 +1,77 @@ +inputReader = $inputReader; + $this->postService = $postService; + $this->postNotesService = $postNotesService; + $this->privilegeService = $privilegeService; + $this->postNoteViewProxy = $postNoteViewProxy; + } + + public function registerRoutes(Router $router) + { + $router->get('/api/notes/:postNameOrId', [$this, 'getPostNotes']); + $router->post('/api/notes/:postNameOrId', [$this, 'addPostNote']); + $router->put('/api/notes/:postNoteId', [$this, 'editPostNote']); + $router->delete('/api/notes/:postNoteId', [$this, 'deletePostNote']); + } + + public function getPostNotes($postNameOrId) + { + $post = $this->postService->getByNameOrId($postNameOrId); + $postNotes = $this->postNotesService->getByPost($post); + return $this->postNoteViewProxy->fromArray($postNotes); + } + + public function addPostNote($postNameOrId) + { + $post = $this->postService->getByNameOrId($postNameOrId); + + $this->privilegeService->assertPrivilege(Privilege::ADD_POST_NOTES); + + $formData = new PostNoteFormData($this->inputReader); + $postNote = $this->postNotesService->createPostNote($post, $formData); + return $this->postNoteViewProxy->fromEntity($postNote); + } + + public function editPostNote($postNoteId) + { + $postNote = $this->postNotesService->getById($postNoteId); + + $this->privilegeService->assertPrivilege(Privilege::EDIT_POST_NOTES); + + $formData = new PostNoteFormData($this->inputReader); + $postNote = $this->postNotesService->updatePostNote($postNote, $formData); + return $this->postNoteViewProxy->fromEntity($postNote); + } + + public function deletePostNote($postNoteId) + { + $postNote = $this->postNotesService->getById($postNoteId); + $this->privilegeService->assertPrivilege(Privilege::DELETE_POST_NOTES); + return $this->postNotesService->deletePostNote($postNote); + } +} diff --git a/src/Controllers/ViewProxies/PostViewProxy.php b/src/Controllers/ViewProxies/PostViewProxy.php index d674b3e2..94e27ff0 100644 --- a/src/Controllers/ViewProxies/PostViewProxy.php +++ b/src/Controllers/ViewProxies/PostViewProxy.php @@ -114,7 +114,7 @@ class PostViewProxy extends AbstractViewProxy $result->favorites = $this->userViewProxy->fromArray($this->favoritesService->getFavoriteUsers($post)); if (!empty($config[self::FETCH_NOTES])) - $result->notes = $this->postNoteViewProxy->fromArray($this->postNotesService->getPostNotes($post)); + $result->notes = $this->postNoteViewProxy->fromArray($this->postNotesService->getByPost($post)); return $result; } diff --git a/src/Dao/PostNoteDao.php b/src/Dao/PostNoteDao.php index eb199c9c..939fec90 100644 --- a/src/Dao/PostNoteDao.php +++ b/src/Dao/PostNoteDao.php @@ -2,19 +2,38 @@ namespace Szurubooru\Dao; use Szurubooru\Dao\EntityConverters\PostNoteEntityConverter; use Szurubooru\DatabaseConnection; +use Szurubooru\Dao\PostDao; +use Szurubooru\Entities\Entity; +use Szurubooru\Entities\PostNote; class PostNoteDao extends AbstractDao implements ICrudDao { - public function __construct(DatabaseConnection $databaseConnection) + private $postDao; + + public function __construct( + DatabaseConnection $databaseConnection, + PostDao $postDao) { parent::__construct( $databaseConnection, 'postNotes', new PostNoteEntityConverter()); + + $this->postDao = $postDao; } public function findByPostId($postId) { return $this->findBy('postId', $postId); } + + protected function afterLoad(Entity $postNote) + { + $postNote->setLazyLoader( + PostNote::LAZY_LOADER_POST, + function (PostNote $postNote) + { + return $this->postDao->findById($postNote->getPostId()); + }); + } } diff --git a/src/Entities/PostNote.php b/src/Entities/PostNote.php index 56843e71..2fa85bc6 100644 --- a/src/Entities/PostNote.php +++ b/src/Entities/PostNote.php @@ -10,6 +10,8 @@ final class PostNote extends Entity private $height; private $text; + const LAZY_LOADER_POST = 'post'; + public function getPostId() { return $this->postId; @@ -69,4 +71,15 @@ final class PostNote extends Entity { $this->text = $text; } + + public function getPost() + { + return $this->lazyLoad(self::LAZY_LOADER_POST, null); + } + + public function setPost(Post $post) + { + $this->lazySave(self::LAZY_LOADER_POST, $post); + $this->postId = $post->getId(); + } } diff --git a/src/FormData/PostNoteFormData.php b/src/FormData/PostNoteFormData.php new file mode 100644 index 00000000..77944764 --- /dev/null +++ b/src/FormData/PostNoteFormData.php @@ -0,0 +1,30 @@ +left = intval($inputReader->left); + $this->top = intval($inputReader->top); + $this->width = intval($inputReader->width); + $this->height = intval($inputReader->height); + $this->text = trim($inputReader->text); + } + } + + public function validate(Validator $validator) + { + $validator->validateMinLength($this->text, 3, 'Post note content'); + } +} diff --git a/src/Privilege.php b/src/Privilege.php index 602fc6fe..9ca3cb9c 100644 --- a/src/Privilege.php +++ b/src/Privilege.php @@ -35,6 +35,10 @@ class Privilege const CHANGE_POST_RELATIONS = 'changePostRelations'; const CHANGE_POST_FLAGS = 'changePostFlags'; + const ADD_POST_NOTES = 'addPostNotes'; + const EDIT_POST_NOTES = 'editPostNotes'; + const DELETE_POST_NOTES = 'deletePostNotes'; + const LIST_TAGS = 'listTags'; const MASS_TAG = 'massTag'; const CHANGE_TAG_NAME = 'changeTagName'; diff --git a/src/Services/PostNotesService.php b/src/Services/PostNotesService.php index 3ceaacff..9040cd34 100644 --- a/src/Services/PostNotesService.php +++ b/src/Services/PostNotesService.php @@ -1,19 +1,98 @@ validator = $validator; + $this->transactionManager = $transactionManager; $this->postNoteDao = $postNoteDao; + $this->historyService = $historyService; } - public function getPostNotes(Post $post) + public function getById($postNoteId) { - return $this->postNoteDao->findByPostId($post->getId()); + $transactionFunc = function() use ($postNoteId) + { + $postNote = $this->postNoteDao->findById($postNoteId); + if (!$postNote) + throw new \InvalidArgumentException('Post note with ID "' . $postNoteId . '" was not found.'); + return $postNote; + }; + return $this->transactionManager->rollback($transactionFunc); + } + + public function getByPost(Post $post) + { + $transactionFunc = function() use ($post) + { + return $this->postNoteDao->findByPostId($post->getId()); + }; + return $this->transactionManager->rollback($transactionFunc); + } + + public function createPostNote(Post $post, PostNoteFormData $formData) + { + $transactionFunc = function() use ($post, $formData) + { + $postNote = new PostNote(); + $postNote->setPostId($post->getId()); + + $this->updatePostNoteWithFormData($postNote, $formData); + $this->postNoteDao->save($postNote); + + $this->historyService->saveSnapshot($this->historyService->getPostChangeSnapshot($post)); + return $postNote; + }; + return $this->transactionManager->commit($transactionFunc); + } + + public function updatePostNote(PostNote $postNote, PostNoteFormData $formData) + { + $transactionFunc = function() use ($postNote, $formData) + { + $this->updatePostNoteWithFormData($postNote, $formData); + $this->postNoteDao->save($postNote); + + $this->historyService->saveSnapshot($this->historyService->getPostChangeSnapshot($postNote->getPost())); + return $postNote; + }; + return $this->transactionManager->commit($transactionFunc); + } + + public function deletePostNote(PostNote $postNote) + { + $transactionFunc = function() use ($postNote) + { + $this->postNoteDao->deleteById($postNote->getId()); + }; + $this->transactionManager->commit($transactionFunc); + } + + private function updatePostNoteWithFormData(PostNote $postNote, PostNoteFormData $formData) + { + $formData->validate($this->validator); + $postNote->setLeft($formData->left); + $postNote->setTop($formData->top); + $postNote->setWidth($formData->width); + $postNote->setHeight($formData->height); + $postNote->setText($formData->text); } } diff --git a/src/di.php b/src/di.php index 5da89260..1b6b3dae 100644 --- a/src/di.php +++ b/src/di.php @@ -53,6 +53,7 @@ return [ $container->get(\Szurubooru\Controllers\UserAvatarController::class), $container->get(\Szurubooru\Controllers\PostController::class), $container->get(\Szurubooru\Controllers\PostContentController::class), + $container->get(\Szurubooru\Controllers\PostNotesController::class), $container->get(\Szurubooru\Controllers\GlobalParamController::class), $container->get(\Szurubooru\Controllers\HistoryController::class), $container->get(\Szurubooru\Controllers\FavoritesController::class), diff --git a/tests/Dao/PostNoteDaoTest.php b/tests/Dao/PostNoteDaoTest.php index 45887e41..9486273d 100644 --- a/tests/Dao/PostNoteDaoTest.php +++ b/tests/Dao/PostNoteDaoTest.php @@ -1,11 +1,20 @@ postDaoMock = $this->mock(PostDao::class); + } + public function testSettingValues() { $expected = new PostNote(); @@ -21,11 +30,15 @@ final class PostNoteDaoTest extends AbstractDatabaseTestCase $actual = $postNoteDao->findById($expected->getId()); $this->assertEntitiesEqual($actual, $expected); + + $this->postDaoMock->expects($this->once())->method('findById')->with(5)->willReturn('lazy post'); + $this->assertEquals('lazy post', $actual->getPost()); } private function getPostNoteDao() { - return new PostNoteDao($this->databaseConnection); + return new PostNoteDao( + $this->databaseConnection, + $this->postDaoMock); } } -