Added post featuring

This commit is contained in:
Marcin Kurczewski 2014-09-24 23:24:51 +02:00
parent 0038df26d8
commit 97ca08cf44
24 changed files with 402 additions and 22 deletions

12
TODO
View file

@ -5,9 +5,6 @@ everything related to posts:
- single post view - single post view
- basic information - basic information
- time of last edit - time of last edit
- time of last feature
- how many times the post was featured
- feature
- fav - fav
- score (see notes about scoring) - score (see notes about scoring)
- editing - editing
@ -30,11 +27,9 @@ everything related to posts:
- hiding posts - hiding posts
- link to iqdb and/or tineye - link to iqdb and/or tineye
- featured posts - auto feature
- ability to feature the post - number of posts
- show the post on main page - total size of posts
- tag list
- uploader
- random post - random post
- regard safety settings - regard safety settings
@ -115,7 +110,6 @@ everything related to comments:
- score (see notes about scoring) - score (see notes about scoring)
refactors: refactors:
- centralize markdown prefix decorators
- add enum validation in IValidatables (needs refactors of enums and - add enum validation in IValidatables (needs refactors of enums and
possible disposal of EnumHelper in favor of something more subtle) possible disposal of EnumHelper in favor of something more subtle)
- (idea) keep denormalized data in separate tables, i.e. tag usages in - (idea) keep denormalized data in separate tables, i.e. tag usages in

View file

@ -42,6 +42,7 @@ listUnsafePosts = anonymous, regularUser, powerUser, moderator, administ
uploadPosts = regularUser, powerUser, moderator, administrator uploadPosts = regularUser, powerUser, moderator, administrator
uploadPostsAnonymously = regularUser, powerUser, moderator, administrator uploadPostsAnonymously = regularUser, powerUser, moderator, administrator
deletePosts = moderator, administrator deletePosts = moderator, administrator
featurePosts = moderator, administrator
listTags = anonymous, regularUser, powerUser, moderator, administrator listTags = anonymous, regularUser, powerUser, moderator, administrator

29
public_html/css/home.css Normal file
View file

@ -0,0 +1,29 @@
#home {
text-align: center;
}
#home h1 {
margin-top: 0;
}
#home .post {
text-align: left;
margin: 0 auto;
max-width: 60%;
}
#home .post .left {
display: inline-block;
float: left;
}
#home .post .right {
display: inline-block;
float: right;
}
#home .post-footer,
#home .post-footer img {
vertical-align: middle;
}
#home .post-footer img {
margin-left: 0.5em;
}

View file

@ -31,6 +31,7 @@
<link rel="stylesheet" type="text/css" href="/css/user.css"/> <link rel="stylesheet" type="text/css" href="/css/user.css"/>
<link rel="stylesheet" type="text/css" href="/css/post-list.css"/> <link rel="stylesheet" type="text/css" href="/css/post-list.css"/>
<link rel="stylesheet" type="text/css" href="/css/post.css"/> <link rel="stylesheet" type="text/css" href="/css/post.css"/>
<link rel="stylesheet" type="text/css" href="/css/home.css"/>
<!-- /build --> <!-- /build -->
</head> </head>

View file

@ -24,6 +24,7 @@ App.Auth = function(_, jQuery, util, api, appState, promise) {
uploadPosts: 'uploadPosts', uploadPosts: 'uploadPosts',
uploadPostsAnonymously: 'uploadPostsAnonymously', uploadPostsAnonymously: 'uploadPostsAnonymously',
deletePosts: 'deletePosts', deletePosts: 'deletePosts',
featurePosts: 'featurePosts',
listTags: 'listTags', listTags: 'listTags',
}; };

View file

@ -2,20 +2,50 @@ var App = App || {};
App.Presenters = App.Presenters || {}; App.Presenters = App.Presenters || {};
App.Presenters.HomePresenter = function( App.Presenters.HomePresenter = function(
_,
jQuery, jQuery,
topNavigationPresenter) { util,
promise,
api,
topNavigationPresenter,
messagePresenter) {
var $el = jQuery('#content'); var $el = jQuery('#content');
var homeTemplate;
var postContentTemplate;
var post;
function init(args, loaded) { function init(args, loaded) {
topNavigationPresenter.select('home'); topNavigationPresenter.select('home');
topNavigationPresenter.changeTitle('Home'); topNavigationPresenter.changeTitle('Home');
promise.waitAll(
util.promiseTemplate('home'),
util.promiseTemplate('post-content'),
api.get('/posts/featured'))
.then(function(
homeTemplateHtml,
postContentTemplateHtml,
response) {
homeTemplate = _.template(homeTemplateHtml);
postContentTemplate = _.template(postContentTemplateHtml);
post = response.json;
render(); render();
loaded(); loaded();
}).fail(function(response) {
messagePresenter.showError($el, response.json && response.json.error || response);
});
} }
function render() { function render() {
$el.html('Home placeholder'); $el.html(homeTemplate({
post: post,
postContentTemplate: postContentTemplate,
title: topNavigationPresenter.getBaseTitle(),
formatRelativeTime: util.formatRelativeTime,
}));
} }
return { return {
@ -25,4 +55,4 @@ App.Presenters.HomePresenter = function(
}; };
App.DI.register('homePresenter', ['jQuery', 'topNavigationPresenter'], App.Presenters.HomePresenter); App.DI.register('homePresenter', ['_', 'jQuery', 'util', 'promise', 'api', 'topNavigationPresenter', 'messagePresenter'], App.Presenters.HomePresenter);

View file

@ -25,6 +25,7 @@ App.Presenters.PostPresenter = function(
topNavigationPresenter.select('posts'); topNavigationPresenter.select('posts');
privileges.canDeletePosts = auth.hasPrivilege(auth.privileges.deletePosts); privileges.canDeletePosts = auth.hasPrivilege(auth.privileges.deletePosts);
privileges.canFeaturePosts = auth.hasPrivilege(auth.privileges.featurePosts);
promise.waitAll( promise.waitAll(
util.promiseTemplate('post'), util.promiseTemplate('post'),
@ -34,7 +35,6 @@ App.Presenters.PostPresenter = function(
postTemplateHtml, postTemplateHtml,
postContentTemplateHtml, postContentTemplateHtml,
response) { response) {
$messages = $el.find('.messages');
postTemplate = _.template(postTemplateHtml); postTemplate = _.template(postTemplateHtml);
postContentTemplate = _.template(postContentTemplateHtml); postContentTemplate = _.template(postContentTemplateHtml);
@ -45,7 +45,7 @@ App.Presenters.PostPresenter = function(
}).fail(function(response) { }).fail(function(response) {
$el.empty(); $el.empty();
messagePresenter.showError($messages, response.json && response.json.error || response); showGenericError(response);
}); });
} }
@ -57,23 +57,45 @@ App.Presenters.PostPresenter = function(
postContentTemplate: postContentTemplate, postContentTemplate: postContentTemplate,
privileges: privileges, privileges: privileges,
})); }));
$messages = $el.find('.messages');
$el.find('.delete').click(deleteButtonClicked); $el.find('.delete').click(deleteButtonClicked);
$el.find('.feature').click(featureButtonClicked);
} }
function deleteButtonClicked(e) { function deleteButtonClicked(e) {
e.preventDefault(); e.preventDefault();
messagePresenter.hideMessages($messages);
if (window.confirm('Do you really want to delete this post?')) { if (window.confirm('Do you really want to delete this post?')) {
deletePost(); deletePost();
} }
} }
function deletePost() { function deletePost() {
api.delete('/posts/' + post.id).then(function(response) { api.delete('/posts/' + post.id)
.then(function(response) {
router.navigate('#/posts'); router.navigate('#/posts');
}).fail(function(response) { }).fail(showGenericError);
}
function featureButtonClicked(e) {
e.preventDefault();
messagePresenter.hideMessages($messages);
if (window.confirm('Do you want to feature this post on fron page?')) {
featurePost();
}
}
function featurePost() {
api.post('/posts/' + post.id + '/feature')
.then(function(response) {
router.navigate('#/home');
})
.fail(showGenericError);
}
function showGenericError(response) {
messagePresenter.showError($messages, response.json && response.json.error || response); messagePresenter.showError($messages, response.json && response.json.error || response);
});
} }
return { return {

View file

@ -47,6 +47,10 @@ App.Presenters.TopNavigationPresenter = function(
$el.find('li.' + selectedElement).find('a').addClass('active'); $el.find('li.' + selectedElement).find('a').addClass('active');
} }
function getBaseTitle() {
return baseTitle;
}
function changeTitle(subTitle) { function changeTitle(subTitle) {
var newTitle = baseTitle; var newTitle = baseTitle;
if (subTitle) { if (subTitle) {
@ -59,6 +63,7 @@ App.Presenters.TopNavigationPresenter = function(
init: init, init: init,
render: render, render: render,
select: select, select: select,
getBaseTitle: getBaseTitle,
changeTitle: changeTitle, changeTitle: changeTitle,
}; };

View file

@ -0,0 +1,30 @@
<div id="home">
<h1><%= title %></h1>
<% if (post) { %>
<div class="post">
<%= postContentTemplate({post: post}) %>
<div class="post-footer">
<span class="left">
<a href="#/post/<%= post.id %>">
<%= post.idMarkdown %>
</a>
uploaded
<%= formatRelativeTime(post.uploadTime) %>
</span>
<span class="right">
featured by
<img class="author-avatar"
src="/data/thumbnails/25x25/avatars/<%= post.user.name || '!' %>"
alt="<%= post.user.name || 'Anonymous user' %>"/>
<%= post.user.name || 'Anonymous user' %>
</span>
</div>
</div>
<% } %>
</div>

View file

@ -3,6 +3,6 @@
title="<%= _.map(post.tags, function(tag) { return '#' + tag.name; }).join(', ') %>" title="<%= _.map(post.tags, function(tag) { return '#' + tag.name; }).join(', ') %>"
href="#/post/<%= post.id %>"> href="#/post/<%= post.id %>">
<img class="thumb" src="/data/thumbnails/160x160/posts/<%= post.name %>" alt="@<%= post.id %>"/> <img class="thumb" src="/data/thumbnails/160x160/posts/<%= post.name %>" alt="<%= post.idMarkdown %>"/>
</a> </a>
</li> </li>

View file

@ -69,6 +69,13 @@
</li> </li>
<% } %> <% } %>
<% if (post.featureCount > 0) { %>
<li>
Featured: <%= post.featureCount %> <%= post.featureCount < 2 ? 'time' : 'times' %>
<small>(<%= formatRelativeTime(post.lastFeatureTime) %>)</small>
</li>
<% } %>
<% if (post.source) { %> <% if (post.source) { %>
<li> <li>
Source:&nbsp;<!-- Source:&nbsp;<!--
@ -91,12 +98,22 @@
</a> </a>
</li> </li>
<% } %> <% } %>
<% if (privileges.canFeaturePosts) { %>
<li>
<a href="#" class="feature">
Feature
</a>
</li>
<% } %>
</ul> </ul>
<% } %> <% } %>
</div> </div>
<div id="post-view"> <div id="post-view">
<div class="messages"></div>
<%= postContentTemplate({post: post}) %> <%= postContentTemplate({post: post}) %>
</div> </div>
</div> </div>

View file

@ -24,8 +24,17 @@ final class PostController extends AbstractController
{ {
$router->post('/api/posts', [$this, 'createPost']); $router->post('/api/posts', [$this, 'createPost']);
$router->get('/api/posts', [$this, 'getFiltered']); $router->get('/api/posts', [$this, 'getFiltered']);
$router->get('/api/posts/featured', [$this, 'getFeatured']);
$router->get('/api/posts/:postNameOrId', [$this, 'getByNameOrId']); $router->get('/api/posts/:postNameOrId', [$this, 'getByNameOrId']);
$router->delete('/api/posts/:postNameOrId', [$this, 'deletePost']); $router->delete('/api/posts/:postNameOrId', [$this, 'deletePost']);
$router->post('/api/posts/:postNameOrId/feature', [$this, 'featurePost']);
$router->put('/api/posts/:postNameOrId/feature', [$this, 'featurePost']);
}
public function getFeatured()
{
$post = $this->postService->getFeatured();
return $this->postViewProxy->fromEntity($post);
} }
public function getByNameOrId($postNameOrId) public function getByNameOrId($postNameOrId)
@ -64,4 +73,10 @@ final class PostController extends AbstractController
$post = $this->postService->getByNameOrId($postNameOrId); $post = $this->postService->getByNameOrId($postNameOrId);
$this->postService->deletePost($post); $this->postService->deletePost($post);
} }
public function featurePost($postNameOrId)
{
$post = $this->postService->getByNameOrId($postNameOrId);
$this->postService->featurePost($post);
}
} }

View file

@ -20,6 +20,7 @@ class PostViewProxy extends AbstractViewProxy
if ($post) if ($post)
{ {
$result->id = $post->getId(); $result->id = $post->getId();
$result->idMarkdown = $post->getIdMarkdown();
$result->name = $post->getName(); $result->name = $post->getName();
$result->uploadTime = $post->getUploadTime(); $result->uploadTime = $post->getUploadTime();
$result->lastEditTime = $post->getLastEditTime(); $result->lastEditTime = $post->getLastEditTime();
@ -31,6 +32,8 @@ class PostViewProxy extends AbstractViewProxy
$result->source = $post->getSource(); $result->source = $post->getSource();
$result->imageWidth = $post->getImageWidth(); $result->imageWidth = $post->getImageWidth();
$result->imageHeight = $post->getImageHeight(); $result->imageHeight = $post->getImageHeight();
$result->featureCount = $post->getFeatureCount();
$result->lastFeatureTime = $post->getLastFeatureTime();
$result->tags = $this->tagViewProxy->fromArray($post->getTags()); $result->tags = $this->tagViewProxy->fromArray($post->getTags());
$result->originalFileSize = $post->getOriginalFileSize(); $result->originalFileSize = $post->getOriginalFileSize();
$result->user = $this->userViewProxy->fromEntity($post->getUser()); $result->user = $this->userViewProxy->fromEntity($post->getUser());

View file

@ -0,0 +1,23 @@
<?php
namespace Szurubooru\Dao\EntityConverters;
class GlobalParamEntityConverter extends AbstractEntityConverter implements IEntityConverter
{
public function toArray(\Szurubooru\Entities\Entity $entity)
{
return
[
'id' => $entity->getId(),
'key' => $entity->getKey(),
'value' => $entity->getValue(),
];
}
public function toBasicEntity(array $array)
{
$entity = new \Szurubooru\Entities\GlobalParam($array['id']);
$entity->setKey($array['key']);
$entity->setValue($array['value']);
return $entity;
}
}

View file

@ -21,6 +21,8 @@ class PostEntityConverter extends AbstractEntityConverter implements IEntityConv
'imageHeight' => $entity->getImageHeight(), 'imageHeight' => $entity->getImageHeight(),
'originalFileSize' => $entity->getOriginalFileSize(), 'originalFileSize' => $entity->getOriginalFileSize(),
'originalFileName' => $entity->getOriginalFileName(), 'originalFileName' => $entity->getOriginalFileName(),
'featureCount' => $entity->getFeatureCount(),
'lastFeatureTime' => $entity->getLastFeatureTime(),
]; ];
} }
@ -40,6 +42,8 @@ class PostEntityConverter extends AbstractEntityConverter implements IEntityConv
$entity->setImageHeight($array['imageHeight']); $entity->setImageHeight($array['imageHeight']);
$entity->setOriginalFileSize($array['originalFileSize']); $entity->setOriginalFileSize($array['originalFileSize']);
$entity->setOriginalFileName($array['originalFileName']); $entity->setOriginalFileName($array['originalFileName']);
$entity->setFeatureCount(intval($array['featureCount']));
$entity->setLastFeatureTime($array['lastFeatureTime']);
$entity->setMeta(\Szurubooru\Entities\Post::META_TAG_COUNT, intval($array['tagCount'])); $entity->setMeta(\Szurubooru\Entities\Post::META_TAG_COUNT, intval($array['tagCount']));
return $entity; return $entity;
} }

View file

@ -0,0 +1,34 @@
<?php
namespace Szurubooru\Dao;
class GlobalParamDao extends AbstractDao implements ICrudDao
{
public function __construct(\Szurubooru\DatabaseConnection $databaseConnection)
{
parent::__construct(
$databaseConnection,
'globals',
new \Szurubooru\Dao\EntityConverters\GlobalParamEntityConverter());
}
public function save(&$entity)
{
if (!$entity->getId())
{
$otherEntityWithThisKey = $this->findByKey($entity->getKey());
if ($otherEntityWithThisKey)
$entity->setId($otherEntityWithThisKey->getId());
}
parent::save($entity);
}
public function findByKey($key)
{
return $this->findOneBy('key', $key);
}
public function deleteByKey($key)
{
return $this->deleteBy('key', $key);
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace Szurubooru\Entities;
class GlobalParam extends Entity
{
const KEY_FEATURED_POST = 'featuredPost';
private $key;
private $value;
public function getKey()
{
return $this->key;
}
public function setKey($key)
{
$this->key = $key;
}
public function getValue()
{
return $this->value;
}
public function setValue($value)
{
$this->value = $value;
}
}

View file

@ -32,6 +32,8 @@ final class Post extends Entity
protected $imageHeight; protected $imageHeight;
protected $originalFileSize; protected $originalFileSize;
protected $originalFileName; protected $originalFileName;
protected $featureCount = 0;
protected $lastFeatureTime;
public function getIdMarkdown() public function getIdMarkdown()
{ {
@ -168,6 +170,26 @@ final class Post extends Entity
$this->originalFileName = $originalFileName; $this->originalFileName = $originalFileName;
} }
public function getFeatureCount()
{
return $this->featureCount;
}
public function setFeatureCount($featureCount)
{
$this->featureCount = $featureCount;
}
public function getLastFeatureTime()
{
return $this->lastFeatureTime;
}
public function setLastFeatureTime($lastFeatureTime)
{
$this->lastFeatureTime = $lastFeatureTime;
}
public function getTags() public function getTags()
{ {
return $this->lazyLoad(self::LAZY_LOADER_TAGS, []); return $this->lazyLoad(self::LAZY_LOADER_TAGS, []);

View file

@ -24,6 +24,7 @@ class Privilege
const UPLOAD_POSTS = 'uploadPosts'; const UPLOAD_POSTS = 'uploadPosts';
const UPLOAD_POSTS_ANONYMOUSLY = 'uploadPostsAnonymously'; const UPLOAD_POSTS_ANONYMOUSLY = 'uploadPostsAnonymously';
const DELETE_POSTS = 'deletePosts'; const DELETE_POSTS = 'deletePosts';
const FEATURE_POSTS = 'featurePosts';
const LIST_TAGS = 'listTags'; const LIST_TAGS = 'listTags';
} }

View file

@ -7,6 +7,7 @@ class PostService
private $validator; private $validator;
private $transactionManager; private $transactionManager;
private $postDao; private $postDao;
private $globalParamDao;
private $postSearchParser; private $postSearchParser;
private $timeService; private $timeService;
private $authService; private $authService;
@ -18,6 +19,7 @@ class PostService
\Szurubooru\Validator $validator, \Szurubooru\Validator $validator,
\Szurubooru\Dao\TransactionManager $transactionManager, \Szurubooru\Dao\TransactionManager $transactionManager,
\Szurubooru\Dao\PostDao $postDao, \Szurubooru\Dao\PostDao $postDao,
\Szurubooru\Dao\GlobalParamDao $globalParamDao,
\Szurubooru\SearchServices\Parsers\PostSearchParser $postSearchParser, \Szurubooru\SearchServices\Parsers\PostSearchParser $postSearchParser,
\Szurubooru\Services\AuthService $authService, \Szurubooru\Services\AuthService $authService,
\Szurubooru\Services\TimeService $timeService, \Szurubooru\Services\TimeService $timeService,
@ -28,6 +30,7 @@ class PostService
$this->validator = $validator; $this->validator = $validator;
$this->transactionManager = $transactionManager; $this->transactionManager = $transactionManager;
$this->postDao = $postDao; $this->postDao = $postDao;
$this->globalParamDao = $globalParamDao;
$this->postSearchParser = $postSearchParser; $this->postSearchParser = $postSearchParser;
$this->timeService = $timeService; $this->timeService = $timeService;
$this->authService = $authService; $this->authService = $authService;
@ -72,6 +75,18 @@ class PostService
return $this->transactionManager->rollback($transactionFunc); return $this->transactionManager->rollback($transactionFunc);
} }
public function getFeatured()
{
$transactionFunc = function()
{
$globalParam = $this->globalParamDao->findByKey(\Szurubooru\Entities\GlobalParam::KEY_FEATURED_POST);
if (!$globalParam)
return null;
return $this->getByNameOrId($globalParam->getValue());
};
return $this->transactionManager->rollback($transactionFunc);
}
public function createPost(\Szurubooru\FormData\UploadFormData $formData) public function createPost(\Szurubooru\FormData\UploadFormData $formData)
{ {
$transactionFunc = function() use ($formData) $transactionFunc = function() use ($formData)
@ -199,6 +214,21 @@ class PostService
$this->transactionManager->commit($transactionFunc); $this->transactionManager->commit($transactionFunc);
} }
public function featurePost(\Szurubooru\Entities\Post $post)
{
$transactionFunc = function() use ($post)
{
$post->setLastFeatureTime($this->timeService->getCurrentTime());
$post->setFeatureCount($post->getFeatureCount() + 1);
$this->postDao->save($post);
$globalParam = new \Szurubooru\Entities\GlobalParam();
$globalParam->setKey(\Szurubooru\Entities\GlobalParam::KEY_FEATURED_POST);
$globalParam->setValue($post->getId());
$this->globalParamDao->save($globalParam);
};
$this->transactionManager->commit($transactionFunc);
}
private function assertNoPostWithThisContentChecksum(\Szurubooru\Entities\Post $parent) private function assertNoPostWithThisContentChecksum(\Szurubooru\Entities\Post $parent)
{ {
$checksumToCheck = $parent->getContentChecksum(); $checksumToCheck = $parent->getContentChecksum();

View file

@ -0,0 +1,20 @@
<?php
namespace Szurubooru\Upgrades;
class Upgrade07 implements IUpgrade
{
public function run(\Szurubooru\DatabaseConnection $databaseConnection)
{
$pdo = $databaseConnection->getPDO();
$pdo->exec('ALTER TABLE posts ADD COLUMN featureCount INTEGER NOT NULL DEFAULT 0');
$pdo->exec('ALTER TABLE posts ADD COLUMN lastFeatureTime TIMESTAMP');
$pdo->exec('CREATE TABLE globals
(
id INTEGER PRIMARY KEY NOT NULL,
key TEXT UNIQUE NOT NULL,
value TEXT
)');
}
}

View file

@ -22,6 +22,7 @@ return [
$container->get(\Szurubooru\Upgrades\Upgrade04::class), $container->get(\Szurubooru\Upgrades\Upgrade04::class),
$container->get(\Szurubooru\Upgrades\Upgrade05::class), $container->get(\Szurubooru\Upgrades\Upgrade05::class),
$container->get(\Szurubooru\Upgrades\Upgrade06::class), $container->get(\Szurubooru\Upgrades\Upgrade06::class),
$container->get(\Szurubooru\Upgrades\Upgrade07::class),
]; ];
}), }),

View file

@ -0,0 +1,64 @@
<?php
namespace Szurubooru\Tests\Dao;
class GlobalParamDaoTest extends \Szurubooru\Tests\AbstractDatabaseTestCase
{
public function testSettingValues()
{
$expected = new \Szurubooru\Entities\GlobalParam();
$expected->setKey('key');
$expected->setValue('test');
$globalParamDao = $this->getGlobalParamDao();
$globalParamDao->save($expected);
$actual = $globalParamDao->findByKey($expected->getKey());
$this->assertEntitiesEqual($actual, $expected);
}
public function testInsertingSameKeyTwice()
{
$param1 = new \Szurubooru\Entities\GlobalParam();
$param1->setKey('key');
$param1->setValue('value1');
$param2 = new \Szurubooru\Entities\GlobalParam();
$param2->setKey('key');
$param2->setValue('value2');
$globalParamDao = $this->getGlobalParamDao();
$globalParamDao->save($param1);
$globalParamDao->save($param2);
$this->assertEquals([$param2], array_values($globalParamDao->findAll()));
}
public function testUpdatingValues()
{
$expected = new \Szurubooru\Entities\GlobalParam();
$expected->setKey('key');
$expected->setValue('test');
$globalParamDao = $this->getGlobalParamDao();
$globalParamDao->save($expected);
$expected->setKey('key2');
$expected->setValue('test2');
$globalParamDao->save($expected);
$actual = $globalParamDao->findByKey($expected->getKey());
$this->assertEntitiesEqual($actual, $expected);
}
public function testRetrievingUnknownKeys()
{
$globalParamDao = $this->getGlobalParamDao();
$actual = $globalParamDao->findByKey('hey i dont exist');
$this->assertNull($actual);
}
private function getGlobalParamDao()
{
return new \Szurubooru\Dao\GlobalParamDao($this->databaseConnection);
}
}

View file

@ -7,6 +7,7 @@ class PostServiceTest extends \Szurubooru\Tests\AbstractTestCase
private $validatorMock; private $validatorMock;
private $transactionManagerMock; private $transactionManagerMock;
private $postDaoMock; private $postDaoMock;
private $globalParamDaoMock;
private $postSearchParserMock; private $postSearchParserMock;
private $authServiceMock; private $authServiceMock;
private $timeServiceMock; private $timeServiceMock;
@ -19,6 +20,7 @@ class PostServiceTest extends \Szurubooru\Tests\AbstractTestCase
$this->validatorMock = $this->mock(\Szurubooru\Validator::class); $this->validatorMock = $this->mock(\Szurubooru\Validator::class);
$this->transactionManagerMock = $this->mockTransactionManager(); $this->transactionManagerMock = $this->mockTransactionManager();
$this->postDaoMock = $this->mock(\Szurubooru\Dao\PostDao::class); $this->postDaoMock = $this->mock(\Szurubooru\Dao\PostDao::class);
$this->globalParamDaoMock = $this->mock(\Szurubooru\Dao\GlobalParamDao::class);
$this->postSearchParserMock = $this->mock(\Szurubooru\SearchServices\Parsers\PostSearchParser::class); $this->postSearchParserMock = $this->mock(\Szurubooru\SearchServices\Parsers\PostSearchParser::class);
$this->authServiceMock = $this->mock(\Szurubooru\Services\AuthService::class); $this->authServiceMock = $this->mock(\Szurubooru\Services\AuthService::class);
$this->timeServiceMock = $this->mock(\Szurubooru\Services\TimeService::class); $this->timeServiceMock = $this->mock(\Szurubooru\Services\TimeService::class);
@ -178,6 +180,7 @@ class PostServiceTest extends \Szurubooru\Tests\AbstractTestCase
$this->validatorMock, $this->validatorMock,
$this->transactionManagerMock, $this->transactionManagerMock,
$this->postDaoMock, $this->postDaoMock,
$this->globalParamDaoMock,
$this->postSearchParserMock, $this->postSearchParserMock,
$this->authServiceMock, $this->authServiceMock,
$this->timeServiceMock, $this->timeServiceMock,