diff --git a/TODO b/TODO index b1bb6ccd..7a10969a 100644 --- a/TODO +++ b/TODO @@ -3,7 +3,7 @@ first major release. everything related to posts: - single post view - - score + - reduce requests to server - editing - ability to loop video posts - previous and next post (difficult) @@ -21,7 +21,6 @@ everything related to posts: - post listing - better thumbnail loading - - score - comment count - regard safety settings - regard disliked settings diff --git a/public_html/js/Presenters/PostPresenter.js b/public_html/js/Presenters/PostPresenter.js index 341722ef..c82e3b39 100644 --- a/public_html/js/Presenters/PostPresenter.js +++ b/public_html/js/Presenters/PostPresenter.js @@ -22,6 +22,7 @@ App.Presenters.PostPresenter = function( var historyTemplate; var post; + var postScore; var postFavorites; var postHistory; var postNameOrId; @@ -73,28 +74,42 @@ App.Presenters.PostPresenter = function( function reinit(args, loaded) { postNameOrId = args.postNameOrId; - promise.waitAll( - api.get('/posts/' + postNameOrId), - api.get('/posts/' + postNameOrId + '/favorites'), - privileges.canViewHistory ? - api.get('/posts/' + postNameOrId + '/history') : - null) - .then(function( - postResponse, - postFavoritesResponse, - postHistoryResponse) { - post = postResponse.json; - postFavorites = postFavoritesResponse && postFavoritesResponse.json && postFavoritesResponse.json.data; - postHistory = postHistoryResponse && postHistoryResponse.json && postHistoryResponse.json.data; + refreshPost() + .then(function() { topNavigationPresenter.changeTitle('@' + post.id); render(); loaded(); - }).fail(function(response) { - showGenericError(response); - loaded(); }); } + function refreshPost() { + return promise.make(function(resolve, reject) { + promise.waitAll( + api.get('/posts/' + postNameOrId), + api.get('/posts/' + postNameOrId + '/favorites'), + auth.isLoggedIn() ? + api.get('/posts/' + postNameOrId + '/score') : + null, + privileges.canViewHistory ? + api.get('/posts/' + postNameOrId + '/history') : + null) + .then(function( + postResponse, + postFavoritesResponse, + postScoreResponse, + postHistoryResponse) { + post = postResponse.json; + postScore = postScoreResponse && postScoreResponse.json && postScoreResponse.json.score; + postFavorites = postFavoritesResponse && postFavoritesResponse.json && postFavoritesResponse.json.data; + postHistory = postHistoryResponse && postHistoryResponse.json && postHistoryResponse.json.data; + resolve(); + }).fail(function(response) { + showGenericError(response); + reject(); + }); + }); + } + function render() { $el.html(renderPostTemplate()); $messages = $el.find('.messages'); @@ -129,6 +144,7 @@ App.Presenters.PostPresenter = function( function renderPostTemplate() { return postTemplate({ post: post, + ownScore: postScore, postFavorites: postFavorites, postHistory: postHistory, @@ -153,6 +169,8 @@ App.Presenters.PostPresenter = function( $el.find('#sidebar .history').click(historyButtonClicked); $el.find('#sidebar .add-favorite').click(addFavoriteButtonClicked); $el.find('#sidebar .delete-favorite').click(deleteFavoriteButtonClicked); + $el.find('#sidebar .score-up').click(scoreUpButtonClicked); + $el.find('#sidebar .score-down').click(scoreDownButtonClicked); } function deleteButtonClicked(e) { @@ -300,8 +318,7 @@ App.Presenters.PostPresenter = function( function addFavorite() { api.post('/posts/' + post.id + '/favorites') .then(function(response) { - postFavorites = response.json.data; - renderSidebar(); + refreshPost().then(renderSidebar); }) .fail(showGenericError); } @@ -309,8 +326,27 @@ App.Presenters.PostPresenter = function( function deleteFavorite() { api.delete('/posts/' + post.id + '/favorites') .then(function(response) { - postFavorites = response.json.data; - renderSidebar(); + refreshPost().then(renderSidebar); + }) + .fail(showGenericError); + } + + function scoreUpButtonClicked(e) { + e.preventDefault(); + var $target = jQuery(this); + score($target.hasClass('active') ? 0 : 1); + } + + function scoreDownButtonClicked(e) { + e.preventDefault(); + var $target = jQuery(this); + score($target.hasClass('active') ? 0 : -1); + } + + function score(scoreValue) { + api.post('/posts/' + post.id + '/score', {score: scoreValue}) + .then(function() { + refreshPost().then(renderSidebar); }) .fail(showGenericError); } diff --git a/public_html/templates/post-list-item.tpl b/public_html/templates/post-list-item.tpl index d31a2e99..1628fc03 100644 --- a/public_html/templates/post-list-item.tpl +++ b/public_html/templates/post-list-item.tpl @@ -5,15 +5,22 @@ <%= post.idMarkdown %> - <% if (post.favoriteCount) { %> + <% if (post.favoriteCount || post.score) { %>
<% } %> diff --git a/public_html/templates/post.tpl b/public_html/templates/post.tpl index f1eb1372..bc2c6d8c 100644 --- a/public_html/templates/post.tpl +++ b/public_html/templates/post.tpl @@ -23,6 +23,26 @@ <% } %> + +
  • + + <% if (ownScore === 1) { %> + + <% } else { %> + + <% } %> + +
  • + +
  • + + <% if (ownScore === -1) { %> + + <% } else { %> + + <% } %> + +
  • <% } %> @@ -112,6 +132,10 @@ --><% } %> <% } %> + +
  • + Score: <%= post.score %> +
  • <% if (_.any(postFavorites)) { %> diff --git a/src/Controllers/PostScoreController.php b/src/Controllers/PostScoreController.php new file mode 100644 index 00000000..205c06a9 --- /dev/null +++ b/src/Controllers/PostScoreController.php @@ -0,0 +1,50 @@ +privilegeService = $privilegeService; + $this->authService = $authService; + $this->postService = $postService; + $this->postScoreService = $postScoreService; + $this->inputReader = $inputReader; + } + + public function registerRoutes(\Szurubooru\Router $router) + { + $router->get('/api/posts/:postNameOrId/score', [$this, 'getScore']); + $router->post('/api/posts/:postNameOrId/score', [$this, 'setScore']); + } + + public function getScore($postNameOrId) + { + $this->privilegeService->assertLoggedIn(); + $user = $this->authService->getLoggedInUser(); + $post = $this->postService->getByNameOrId($postNameOrId); + $result = $this->postScoreService->getScore($user, $post); + return ['score' => $result ? $result->getScore() : 0]; + } + + public function setScore($postNameOrId) + { + $this->privilegeService->assertLoggedIn(); + $score = intval($this->inputReader->score); + $user = $this->authService->getLoggedInUser(); + $post = $this->postService->getByNameOrId($postNameOrId); + $result = $this->postScoreService->setScore($user, $post, $score); + return ['score' => $result->getScore()]; + } +} diff --git a/src/Controllers/ViewProxies/PostViewProxy.php b/src/Controllers/ViewProxies/PostViewProxy.php index 0b0e094d..c8bce8d7 100644 --- a/src/Controllers/ViewProxies/PostViewProxy.php +++ b/src/Controllers/ViewProxies/PostViewProxy.php @@ -40,6 +40,7 @@ class PostViewProxy extends AbstractViewProxy $result->lastFeatureTime = $post->getLastFeatureTime(); $result->originalFileSize = $post->getOriginalFileSize(); $result->favoriteCount = $post->getFavoriteCount(); + $result->score = $post->getScore(); if (!empty($config[self::FETCH_TAGS])) $result->tags = $this->tagViewProxy->fromArray($post->getTags()); diff --git a/src/Dao/EntityConverters/PostEntityConverter.php b/src/Dao/EntityConverters/PostEntityConverter.php index d84fc166..c7899d08 100644 --- a/src/Dao/EntityConverters/PostEntityConverter.php +++ b/src/Dao/EntityConverters/PostEntityConverter.php @@ -46,6 +46,7 @@ class PostEntityConverter extends AbstractEntityConverter implements IEntityConv $entity->setLastFeatureTime($array['lastFeatureTime']); $entity->setMeta(\Szurubooru\Entities\Post::META_TAG_COUNT, intval($array['tagCount'])); $entity->setMeta(\Szurubooru\Entities\Post::META_FAV_COUNT, intval($array['favCount'])); + $entity->setMeta(\Szurubooru\Entities\Post::META_SCORE, intval($array['score'])); return $entity; } } diff --git a/src/Dao/EntityConverters/PostScoreEntityConverter.php b/src/Dao/EntityConverters/PostScoreEntityConverter.php new file mode 100644 index 00000000..28126448 --- /dev/null +++ b/src/Dao/EntityConverters/PostScoreEntityConverter.php @@ -0,0 +1,27 @@ + $entity->getId(), + 'userId' => $entity->getUserId(), + 'postId' => $entity->getPostId(), + 'time' => $entity->getTime(), + 'score' => $entity->getScore(), + ]; + } + + public function toBasicEntity(array $array) + { + $entity = new \Szurubooru\Entities\PostScore($array['id']); + $entity->setUserId($array['userId']); + $entity->setPostId($array['postId']); + $entity->setTime($array['time']); + $entity->setScore(intval($array['score'])); + return $entity; + } +} diff --git a/src/Dao/FavoritesDao.php b/src/Dao/FavoritesDao.php index f07ec235..b76b712d 100644 --- a/src/Dao/FavoritesDao.php +++ b/src/Dao/FavoritesDao.php @@ -5,11 +5,13 @@ class FavoritesDao extends AbstractDao implements ICrudDao { private $userDao; private $postDao; + private $timeService; public function __construct( \Szurubooru\DatabaseConnection $databaseConnection, \Szurubooru\Dao\UserDao $userDao, - \Szurubooru\Dao\PostDao $postDao) + \Szurubooru\Dao\PostDao $postDao, + \Szurubooru\Services\TimeService $timeService) { parent::__construct( $databaseConnection, @@ -18,16 +20,7 @@ class FavoritesDao extends AbstractDao implements ICrudDao $this->userDao = $userDao; $this->postDao = $postDao; - } - - public function findByUserAndPost(\Szurubooru\Entities\User $user, \Szurubooru\Entities\Post $post) - { - $query = $this->fpdo->from($this->tableName) - ->where('userId', $user->getId()) - ->where('postId', $post->getId()); - $arrayEntities = iterator_to_array($query); - $entities = $this->arrayToEntities($arrayEntities); - return array_shift($entities); + $this->timeService = $timeService; } public function findByPost(\Szurubooru\Entities\Post $post) @@ -35,6 +28,27 @@ class FavoritesDao extends AbstractDao implements ICrudDao return $this->findBy('postId', $post->getId()); } + public function set(\Szurubooru\Entities\User $user, \Szurubooru\Entities\Post $post) + { + $favorite = $this->get($user, $post); + if (!$favorite) + { + $favorite = new \Szurubooru\Entities\Favorite(); + $favorite->setUser($user); + $favorite->setPost($post); + $favorite->setTime($this->timeService->getCurrentTime()); + $this->save($favorite); + } + return $favorite; + } + + public function delete(\Szurubooru\Entities\User $user, \Szurubooru\Entities\Post $post) + { + $favorite = $this->get($user, $post); + if ($favorite) + $this->deleteById($favorite->getId()); + } + protected function afterLoad(\Szurubooru\Entities\Entity $favorite) { $favorite->setLazyLoader( @@ -51,4 +65,14 @@ class FavoritesDao extends AbstractDao implements ICrudDao return $this->postDao->findById($favorite->getPostId()); }); } + + private function get(\Szurubooru\Entities\User $user, \Szurubooru\Entities\Post $post) + { + $query = $this->fpdo->from($this->tableName) + ->where('userId', $user->getId()) + ->where('postId', $post->getId()); + $arrayEntities = iterator_to_array($query); + $entities = $this->arrayToEntities($arrayEntities); + return array_shift($entities); + } } diff --git a/src/Dao/PostScoreDao.php b/src/Dao/PostScoreDao.php new file mode 100644 index 00000000..d7179a88 --- /dev/null +++ b/src/Dao/PostScoreDao.php @@ -0,0 +1,67 @@ +userDao = $userDao; + $this->postDao = $postDao; + $this->timeService = $timeService; + } + + public function getScore(\Szurubooru\Entities\User $user, \Szurubooru\Entities\Post $post) + { + $query = $this->fpdo->from($this->tableName) + ->where('userId', $user->getId()) + ->where('postId', $post->getId()); + $arrayEntities = iterator_to_array($query); + $entities = $this->arrayToEntities($arrayEntities); + return array_shift($entities); + } + + public function setScore(\Szurubooru\Entities\User $user, \Szurubooru\Entities\Post $post, $scoreValue) + { + $postScore = $this->getScore($user, $post); + if (!$postScore) + { + $postScore = new \Szurubooru\Entities\PostScore(); + $postScore->setUser($user); + $postScore->setPost($post); + $postScore->setTime($this->timeService->getCurrentTime()); + } + $postScore->setScore($scoreValue); + $this->save($postScore); + return $postScore; + } + + protected function afterLoad(\Szurubooru\Entities\Entity $postScore) + { + $postScore->setLazyLoader( + \Szurubooru\Entities\PostScore::LAZY_LOADER_USER, + function (\Szurubooru\Entities\PostScore $postScore) + { + return $this->userDao->findById($postScore->getUserId()); + }); + + $postScore->setLazyLoader( + \Szurubooru\Entities\PostScore::LAZY_LOADER_POST, + function (\Szurubooru\Entities\PostScore $postScore) + { + return $this->postDao->findById($postScore->getPostId()); + }); + } +} diff --git a/src/Entities/Post.php b/src/Entities/Post.php index 1d4e513c..bbc14005 100644 --- a/src/Entities/Post.php +++ b/src/Entities/Post.php @@ -20,6 +20,7 @@ final class Post extends Entity const META_TAG_COUNT = 'tagCount'; const META_FAV_COUNT = 'favCount'; + const META_SCORE = 'score'; protected $name; protected $userId; @@ -263,4 +264,9 @@ final class Post extends Entity { return $this->getMeta(self::META_FAV_COUNT, 0); } + + public function getScore() + { + return $this->getMeta(self::META_SCORE, 0); + } } diff --git a/src/Entities/PostScore.php b/src/Entities/PostScore.php new file mode 100644 index 00000000..b2691983 --- /dev/null +++ b/src/Entities/PostScore.php @@ -0,0 +1,75 @@ +userId; + } + + public function setUserId($userId) + { + $this->userId = $userId; + } + + public function getPostId() + { + return $this->postId; + } + + public function setPostId($postId) + { + $this->postId = $postId; + } + + public function getTime() + { + return $this->time; + } + + public function setTime($time) + { + $this->time = $time; + } + + public function getScore() + { + return $this->score; + } + + public function setScore($score) + { + $this->score = $score; + } + + public function getUser() + { + return $this->lazyLoad(self::LAZY_LOADER_USER, null); + } + + public function setUser(\Szurubooru\Entities\User $user) + { + $this->lazySave(self::LAZY_LOADER_USER, $user); + $this->userId = $user->getId(); + } + + public function getPost() + { + return $this->lazyLoad(self::LAZY_LOADER_POST, null); + } + + public function setPost(\Szurubooru\Entities\Post $post) + { + $this->lazySave(self::LAZY_LOADER_POST, $post); + $this->postId = $post->getId(); + } +} diff --git a/src/Services/FavoritesService.php b/src/Services/FavoritesService.php index 773befc0..109f4bfe 100644 --- a/src/Services/FavoritesService.php +++ b/src/Services/FavoritesService.php @@ -4,17 +4,20 @@ namespace Szurubooru\Services; class FavoritesService { private $favoritesDao; + private $postScoreDao; private $userDao; private $transactionManager; private $timeService; public function __construct( \Szurubooru\Dao\FavoritesDao $favoritesDao, + \Szurubooru\Dao\PostScoreDao $postScoreDao, \Szurubooru\Dao\UserDao $userDao, \Szurubooru\Dao\TransactionManager $transactionManager, \Szurubooru\Services\TimeService $timeService) { $this->favoritesDao = $favoritesDao; + $this->postScoreDao = $postScoreDao; $this->userDao = $userDao; $this->transactionManager = $transactionManager; $this->timeService = $timeService; @@ -39,15 +42,9 @@ class FavoritesService { $transactionFunc = function() use ($user, $post) { - $favorite = $this->favoritesDao->findByUserAndPost($user, $post); - if (!$favorite) - { - $favorite = new \Szurubooru\Entities\Favorite(); - $favorite->setUser($user); - $favorite->setPost($post); - $favorite->setTime($this->timeService->getCurrentTime()); - $this->favoritesDao->save($favorite); - } + $this->postScoreDao->setScore($user, $post, 1); + + return $this->favoritesDao->set($user, $post); }; return $this->transactionManager->commit($transactionFunc); } @@ -56,9 +53,8 @@ class FavoritesService { $transactionFunc = function() use ($user, $post) { - $favorite = $this->favoritesDao->findByUserAndPost($user, $post); - $this->favoritesDao->deleteById($favorite->getId()); + $this->favoritesDao->delete($user, $post); }; - return $this->transactionManager->commit($transactionFunc); + $this->transactionManager->commit($transactionFunc); } } diff --git a/src/Services/PostScoreService.php b/src/Services/PostScoreService.php new file mode 100644 index 00000000..d016c777 --- /dev/null +++ b/src/Services/PostScoreService.php @@ -0,0 +1,49 @@ +postScoreDao = $postScoreDao; + $this->favoritesDao = $favoritesDao; + $this->userDao = $userDao; + $this->transactionManager = $transactionManager; + $this->timeService = $timeService; + } + + public function getScore(\Szurubooru\Entities\User $user, \Szurubooru\Entities\Post $post) + { + $transactionFunc = function() use ($user, $post) + { + return $this->postScoreDao->getScore($user, $post); + }; + return $this->transactionManager->rollback($transactionFunc); + } + + public function setScore(\Szurubooru\Entities\User $user, \Szurubooru\Entities\Post $post, $scoreValue) + { + if ($scoreValue !== 1 and $scoreValue !== 0 and $scoreValue !== -1) + throw new \DomainException('Bad score'); + + $transactionFunc = function() use ($user, $post, $scoreValue) + { + if ($scoreValue !== 1) + $this->favoritesDao->delete($user, $post); + + return $this->postScoreDao->setScore($user, $post, $scoreValue); + }; + return $this->transactionManager->commit($transactionFunc); + } +} diff --git a/src/Upgrades/Upgrade11.php b/src/Upgrades/Upgrade11.php new file mode 100644 index 00000000..1db7e057 --- /dev/null +++ b/src/Upgrades/Upgrade11.php @@ -0,0 +1,58 @@ +getPDO(); + + $pdo->exec('ALTER TABLE posts ADD COLUMN score INTEGER NOT NULL DEFAULT 0'); + + $pdo->exec('CREATE TABLE postScores + ( + id INTEGER PRIMARY KEY NOT NULL, + userId INTEGER NOT NULL, + postId INTEGER NOT NULL, + time TIMESTAMP NOT NULL, + score INTEGER NOT NULL, + UNIQUE (userId, postId) + )'); + + $pdo->exec(' + CREATE TRIGGER postScoresDelete AFTER DELETE ON postScores + FOR EACH ROW + BEGIN + UPDATE posts SET score = ( + SELECT SUM(score) FROM postScores + WHERE postScores.postId = posts.id) + WHERE posts.id = OLD.postId; + END'); + + $pdo->exec(' + CREATE TRIGGER postScoresInsert AFTER INSERT ON postScores + FOR EACH ROW + BEGIN + UPDATE posts SET score = ( + SELECT SUM(score) FROM postScores + WHERE postScores.postId = posts.id) + WHERE posts.id = NEW.postId; + END'); + + + $pdo->exec(' + CREATE TRIGGER postScoresUpdate AFTER UPDATE ON postScores + FOR EACH ROW + BEGIN + UPDATE posts SET score = ( + SELECT SUM(score) FROM postScores + WHERE postScores.postId = posts.id) + WHERE posts.id = OLD.postId; + + UPDATE posts SET score = ( + SELECT SUM(score) FROM postScores + WHERE postScores.postId = posts.id) + WHERE posts.id = NEW.postId; + END'); + } +} diff --git a/src/di.php b/src/di.php index ed3357a7..41b38339 100644 --- a/src/di.php +++ b/src/di.php @@ -26,6 +26,7 @@ return [ $container->get(\Szurubooru\Upgrades\Upgrade08::class), $container->get(\Szurubooru\Upgrades\Upgrade09::class), $container->get(\Szurubooru\Upgrades\Upgrade10::class), + $container->get(\Szurubooru\Upgrades\Upgrade11::class), ]; }), @@ -39,6 +40,7 @@ return [ $container->get(\Szurubooru\Controllers\GlobalParamController::class), $container->get(\Szurubooru\Controllers\HistoryController::class), $container->get(\Szurubooru\Controllers\FavoritesController::class), + $container->get(\Szurubooru\Controllers\PostScoreController::class), ]; }), ]; diff --git a/tests/Dao/FavoritesDaoTest.php b/tests/Dao/FavoritesDaoTest.php index 68bc57b3..ea673891 100644 --- a/tests/Dao/FavoritesDaoTest.php +++ b/tests/Dao/FavoritesDaoTest.php @@ -5,12 +5,14 @@ class FavoritesDaoTest extends \Szurubooru\Tests\AbstractDatabaseTestCase { private $userDaoMock; private $postDaoMock; + private $timeServiceMock; public function setUp() { parent::setUp(); $this->userDaoMock = $this->mock(\Szurubooru\Dao\UserDao::class); $this->postDaoMock = $this->mock(\Szurubooru\Dao\PostDao::class); + $this->timeServiceMock = $this->mock(\Szurubooru\Services\TimeService::class); } public function testSaving() @@ -39,39 +41,6 @@ class FavoritesDaoTest extends \Szurubooru\Tests\AbstractDatabaseTestCase $this->assertEntitiesEqual($post, $savedFavorite->getPost()); } - public function testFindingByUserAndPost() - { - $post1 = new \Szurubooru\Entities\Post(1); - $post2 = new \Szurubooru\Entities\Post(2); - $user1 = new \Szurubooru\Entities\User(3); - $user2 = new \Szurubooru\Entities\User(4); - - $fav1 = new \Szurubooru\Entities\Favorite(); - $fav1->setUser($user1); - $fav1->setPost($post1); - $fav1->setTime('time1'); - - $fav2 = new \Szurubooru\Entities\Favorite(); - $fav2->setUser($user2); - $fav2->setPost($post2); - $fav2->setTime('time2'); - - $fav3 = new \Szurubooru\Entities\Favorite(); - $fav3->setUser($user1); - $fav3->setPost($post2); - $fav3->setTime('time3'); - - $favoritesDao = $this->getFavoritesDao(); - $favoritesDao->save($fav1); - $favoritesDao->save($fav2); - $favoritesDao->save($fav3); - - $this->assertEntitiesEqual($fav1, $favoritesDao->findByUserAndPost($user1, $post1)); - $this->assertEntitiesEqual($fav2, $favoritesDao->findByUserAndPost($user2, $post2)); - $this->assertEntitiesEqual($fav3, $favoritesDao->findByUserAndPost($user1, $post2)); - $this->assertNull($favoritesDao->findByUserAndPost($user2, $post1)); - } - public function findByPost(\Szurubooru\Entities\Post $post) { return $this->findOneBy('postId', $post->getId()); @@ -82,6 +51,7 @@ class FavoritesDaoTest extends \Szurubooru\Tests\AbstractDatabaseTestCase return new \Szurubooru\Dao\FavoritesDao( $this->databaseConnection, $this->userDaoMock, - $this->postDaoMock); + $this->postDaoMock, + $this->timeServiceMock); } } diff --git a/tests/Dao/PostScoreDaoTest.php b/tests/Dao/PostScoreDaoTest.php new file mode 100644 index 00000000..f4342807 --- /dev/null +++ b/tests/Dao/PostScoreDaoTest.php @@ -0,0 +1,94 @@ +userDaoMock = $this->mock(\Szurubooru\Dao\UserDao::class); + $this->postDaoMock = $this->mock(\Szurubooru\Dao\PostDao::class); + $this->timeServiceMock = $this->mock(\Szurubooru\Services\TimeService::class); + } + + public function testSaving() + { + $user = new \Szurubooru\Entities\User(1); + $user->setName('olivia'); + + $post = new \Szurubooru\Entities\Post(2); + $post->setName('sword'); + + $postScore = new \Szurubooru\Entities\PostScore(); + $postScore->setUser($user); + $postScore->setPost($post); + $postScore->setTime('whatever'); + $postScore->setScore(1); + $postScoreDao = $this->getPostScoreDao(); + $postScoreDao->save($postScore); + + $this->userDaoMock->expects($this->once())->method('findById')->with(1)->willReturn($user); + $this->postDaoMock->expects($this->once())->method('findById')->with(2)->willReturn($post); + + $savedPostScore = $postScoreDao->findById($postScore->getId()); + $this->assertEquals(1, $savedPostScore->getUserId()); + $this->assertEquals(2, $savedPostScore->getPostId()); + $this->assertEquals('whatever', $savedPostScore->getTime()); + $this->assertEntitiesEqual($user, $savedPostScore->getUser()); + $this->assertEntitiesEqual($post, $savedPostScore->getPost()); + } + + public function testFindingByUserAndPost() + { + $post1 = new \Szurubooru\Entities\Post(1); + $post2 = new \Szurubooru\Entities\Post(2); + $user1 = new \Szurubooru\Entities\User(3); + $user2 = new \Szurubooru\Entities\User(4); + + $postScore1 = new \Szurubooru\Entities\PostScore(); + $postScore1->setUser($user1); + $postScore1->setPost($post1); + $postScore1->setTime('time1'); + $postScore1->setScore(1); + + $postScore2 = new \Szurubooru\Entities\PostScore(); + $postScore2->setUser($user2); + $postScore2->setPost($post2); + $postScore2->setTime('time2'); + $postScore2->setScore(0); + + $postScore3 = new \Szurubooru\Entities\PostScore(); + $postScore3->setUser($user1); + $postScore3->setPost($post2); + $postScore3->setTime('time3'); + $postScore3->setScore(-1); + + $postScoreDao = $this->getPostScoreDao(); + $postScoreDao->save($postScore1); + $postScoreDao->save($postScore2); + $postScoreDao->save($postScore3); + + $this->assertEntitiesEqual($postScore1, $postScoreDao->getScore($user1, $post1)); + $this->assertEntitiesEqual($postScore2, $postScoreDao->getScore($user2, $post2)); + $this->assertEntitiesEqual($postScore3, $postScoreDao->getScore($user1, $post2)); + $this->assertNull($postScoreDao->getScore($user2, $post1)); + } + + public function findByPost(\Szurubooru\Entities\Post $post) + { + return $this->findOneBy('postId', $post->getId()); + } + + private function getPostScoreDao() + { + return new \Szurubooru\Dao\PostScoreDao( + $this->databaseConnection, + $this->userDaoMock, + $this->postDaoMock, + $this->timeServiceMock); + } +} diff --git a/tests/Services/FavoritesServiceTest.php b/tests/Services/FavoritesServiceTest.php index d4ac3300..2d7444eb 100644 --- a/tests/Services/FavoritesServiceTest.php +++ b/tests/Services/FavoritesServiceTest.php @@ -4,6 +4,7 @@ namespace Szurubooru\Tests\Services; final class FavoritesServiceTest extends \Szurubooru\Tests\AbstractTestCase { private $favoritesDaoMock; + private $postScoreDaoMock; private $userDaoMock; private $transactionManagerMock; private $timeServiceMock; @@ -12,23 +13,12 @@ final class FavoritesServiceTest extends \Szurubooru\Tests\AbstractTestCase { parent::setUp(); $this->favoritesDaoMock = $this->mock(\Szurubooru\Dao\FavoritesDao::class); + $this->postScoreDaoMock = $this->mock(\Szurubooru\Dao\PostScoreDao::class); $this->userDaoMock = $this->mock(\Szurubooru\Dao\UserDao::class); $this->transactionManagerMock = $this->mockTransactionManager(); $this->timeServiceMock = $this->mock(\Szurubooru\Services\TimeService::class); } - public function testAddingExisting() - { - $user = new \Szurubooru\Entities\User(); - $post = new \Szurubooru\Entities\Post(); - $fav = new \Szurubooru\Entities\Favorite(3); - $this->favoritesDaoMock->expects($this->once())->method('findByUserAndPost')->with($user, $post)->willReturn($fav); - $this->favoritesDaoMock->expects($this->never())->method('save'); - - $favoritesService = $this->getFavoritesService(); - $favoritesService->addFavorite($user, $post); - } - public function testAdding() { $user = new \Szurubooru\Entities\User(1); @@ -36,13 +26,7 @@ final class FavoritesServiceTest extends \Szurubooru\Tests\AbstractTestCase $fav = new \Szurubooru\Entities\Favorite(); $fav->setUserId($user->getId()); $fav->setPostId($post->getId()); - $this->favoritesDaoMock->expects($this->once())->method('findByUserAndPost')->with($user, $post)->willReturn(null); - $this->favoritesDaoMock->expects($this->once())->method('save')->with($this->callback( - function($subject) use ($fav) - { - $this->assertEntitiesEqual($fav, $subject); - return true; - })); + $this->favoritesDaoMock->expects($this->once())->method('set')->with($user, $post); $favoritesService = $this->getFavoritesService(); $favoritesService->addFavorite($user, $post); @@ -53,8 +37,7 @@ final class FavoritesServiceTest extends \Szurubooru\Tests\AbstractTestCase $user = new \Szurubooru\Entities\User(); $post = new \Szurubooru\Entities\Post(); $fav = new \Szurubooru\Entities\Favorite(3); - $this->favoritesDaoMock->expects($this->once())->method('findByUserAndPost')->with($user, $post)->willReturn($fav); - $this->favoritesDaoMock->expects($this->once())->method('deleteById')->with($fav->getId()); + $this->favoritesDaoMock->expects($this->once())->method('delete')->with($user, $post); $favoritesService = $this->getFavoritesService(); $favoritesService->deleteFavorite($user, $post); @@ -79,6 +62,7 @@ final class FavoritesServiceTest extends \Szurubooru\Tests\AbstractTestCase { return new \Szurubooru\Services\FavoritesService( $this->favoritesDaoMock, + $this->postScoreDaoMock, $this->userDaoMock, $this->transactionManagerMock, $this->timeServiceMock); diff --git a/tests/Services/PostScoreServiceTest.php b/tests/Services/PostScoreServiceTest.php new file mode 100644 index 00000000..0acd0394 --- /dev/null +++ b/tests/Services/PostScoreServiceTest.php @@ -0,0 +1,66 @@ +postScoreDaoMock = $this->mock(\Szurubooru\Dao\PostScoreDao::class); + $this->favoritesDaoMock = $this->mock(\Szurubooru\Dao\FavoritesDao::class); + $this->userDaoMock = $this->mock(\Szurubooru\Dao\UserDao::class); + $this->transactionManagerMock = $this->mockTransactionManager(); + $this->timeServiceMock = $this->mock(\Szurubooru\Services\TimeService::class); + } + + public function testSetting() + { + $user = new \Szurubooru\Entities\User(1); + $post = new \Szurubooru\Entities\Post(2); + $postScore = new \Szurubooru\Entities\PostScore(); + $postScore->setUserId($user->getId()); + $postScore->setPostId($post->getId()); + $postScore->setScore(1); + $this->postScoreDaoMock->expects($this->once())->method('setScore')->with($user, $post)->willReturn(null); + + $postScoreService = $this->getPostScoreService(); + $postScoreService->setScore($user, $post, 1); + } + + public function testSettingInvalid() + { + $user = new \Szurubooru\Entities\User(1); + $post = new \Szurubooru\Entities\Post(2); + $this->setExpectedException(\Exception::class); + $postScoreService = $this->getPostScoreService(); + $postScoreService->setScore($user, $post, 2); + } + + public function testGetting() + { + $user = new \Szurubooru\Entities\User(); + $post = new \Szurubooru\Entities\Post(); + $postScore = new \Szurubooru\Entities\PostScore(3); + $this->postScoreDaoMock->expects($this->once())->method('getScore')->with($user, $post)->willReturn($postScore); + + $postScoreService = $this->getPostScoreService(); + $retrievedScore = $postScoreService->getScore($user, $post); + $this->assertEquals($postScore, $retrievedScore); + } + + private function getPostScoreService() + { + return new \Szurubooru\Services\PostScoreService( + $this->postScoreDaoMock, + $this->favoritesDaoMock, + $this->userDaoMock, + $this->transactionManagerMock, + $this->timeServiceMock); + } +}