Refactored comment model, fixed anonymous previews

This commit is contained in:
Marcin Kurczewski 2014-05-06 00:54:15 +02:00
parent fb7119b235
commit 8009c16f0c
12 changed files with 197 additions and 59 deletions

View file

@ -5,13 +5,13 @@ class AddCommentJob extends AbstractJob
{ {
$user = Auth::getCurrentUser(); $user = Auth::getCurrentUser();
$post = PostModel::findById($this->getArgument(self::POST_ID)); $post = PostModel::findById($this->getArgument(self::POST_ID));
$text = CommentModel::validateText($this->getArgument(self::TEXT)); $text = $this->getArgument(self::TEXT);
$comment = CommentModel::spawn(); $comment = CommentModel::spawn();
$comment->setCommenter($user); $comment->setCommenter($user);
$comment->setPost($post); $comment->setPost($post);
$comment->commentDate = time(); $comment->setDateTime(time());
$comment->text = $text; $comment->setText($text);
CommentModel::save($comment); CommentModel::save($comment);
Logger::log('{user} commented on {post}', [ Logger::log('{user} commented on {post}', [

View file

@ -12,8 +12,8 @@ class EditCommentJob extends AbstractJob
{ {
$comment = $this->comment; $comment = $this->comment;
$comment->commentDate = time(); $comment->setDateTime(time());
$comment->text = CommentModel::validateText($this->getArgument(self::TEXT)); $comment->setText($this->getArgument(self::TEXT));
CommentModel::save($comment); CommentModel::save($comment);
Logger::log('{user} edited comment in {post}', [ Logger::log('{user} edited comment in {post}', [

View file

@ -4,12 +4,17 @@ class PreviewCommentJob extends AbstractJob
public function execute() public function execute()
{ {
$user = Auth::getCurrentUser(); $user = Auth::getCurrentUser();
$text = CommentModel::validateText($this->getArgument(self::TEXT)); $text = $this->getArgument(self::TEXT);
$post = PostModel::findById($this->getArgument(self::POST_ID));
$comment = CommentModel::spawn(); $comment = CommentModel::spawn();
$comment->setCommenter($user); $comment->setCommenter($user);
$comment->commentDate = time(); $comment->setDateTime(time());
$comment->text = $text; $comment->setText($text);
$comment->setPost($post);
$comment->validate();
return $comment; return $comment;
} }
@ -20,7 +25,7 @@ class PreviewCommentJob extends AbstractJob
public function requiresAuthentication() public function requiresAuthentication()
{ {
return true; return false;
} }
public function requiresConfirmedEmail() public function requiresConfirmedEmail()

View file

@ -19,10 +19,11 @@ class CommentController
$comment = Api::run( $comment = Api::run(
new PreviewCommentJob(), new PreviewCommentJob(),
[ [
PreviewCommentJob::POST_ID => InputHelper::get('post-id'),
PreviewCommentJob::TEXT => InputHelper::get('text') PreviewCommentJob::TEXT => InputHelper::get('text')
]); ]);
getContext()->transport->textPreview = $comment->getText(); getContext()->transport->textPreview = $comment->getTextMarkdown();
} }
public function addAction() public function addAction()

View file

@ -2,7 +2,7 @@
use \Chibi\Sql as Sql; use \Chibi\Sql as Sql;
use \Chibi\Database as Database; use \Chibi\Database as Database;
class CommentModel extends AbstractCrudModel final class CommentModel extends AbstractCrudModel
{ {
public static function getTableName() public static function getTableName()
{ {
@ -12,7 +12,7 @@ class CommentModel extends AbstractCrudModel
public static function spawn() public static function spawn()
{ {
$comment = new CommentEntity; $comment = new CommentEntity;
$comment->commentDate = time(); $comment->setDateTime(time());
return $comment; return $comment;
} }
@ -25,10 +25,10 @@ class CommentModel extends AbstractCrudModel
self::forgeId($comment); self::forgeId($comment);
$bindings = [ $bindings = [
'text' => $comment->text, 'text' => $comment->getText(),
'post_id' => $comment->postId, 'post_id' => $comment->getPostId(),
'comment_date' => $comment->commentDate, 'comment_date' => $comment->getDateTime(),
'commenter_id' => $comment->commenterId]; 'commenter_id' => $comment->getCommenterId()];
$stmt = new Sql\UpdateStatement(); $stmt = new Sql\UpdateStatement();
$stmt->setTable('comment'); $stmt->setTable('comment');
@ -74,7 +74,7 @@ class CommentModel extends AbstractCrudModel
public static function preloadCommenters($comments) public static function preloadCommenters($comments)
{ {
self::preloadOneToMany($comments, self::preloadOneToMany($comments,
function($comment) { return $comment->commenterId; }, function($comment) { return $comment->getCommenterId(); },
function($user) { return $user->getId(); }, function($user) { return $user->getId(); },
function($userIds) { return UserModel::findByIds($userIds); }, function($userIds) { return UserModel::findByIds($userIds); },
function($comment, $user) { return $comment->setCache('commenter', $user); }); function($comment, $user) { return $comment->setCache('commenter', $user); });
@ -83,25 +83,9 @@ class CommentModel extends AbstractCrudModel
public static function preloadPosts($comments) public static function preloadPosts($comments)
{ {
self::preloadOneToMany($comments, self::preloadOneToMany($comments,
function($comment) { return $comment->postId; }, function($comment) { return $comment->getPostId(); },
function($post) { return $post->getId(); }, function($post) { return $post->getId(); },
function($postIds) { return PostModel::findByIds($postIds); }, function($postIds) { return PostModel::findByIds($postIds); },
function($comment, $post) { $comment->setCache('post', $post); }); function($comment, $post) { $comment->setCache('post', $post); });
} }
public static function validateText($text)
{
$text = trim($text);
$config = getConfig();
if (strlen($text) < $config->comments->minLength)
throw new SimpleException('Comment must have at least %d characters', $config->comments->minLength);
if (strlen($text) > $config->comments->maxLength)
throw new SimpleException('Comment must have at most %d characters', $config->comments->maxLength);
return $text;
}
} }

View file

@ -1,48 +1,93 @@
<?php <?php
class CommentEntity extends AbstractEntity implements IValidatable final class CommentEntity extends AbstractEntity implements IValidatable
{ {
public $text; protected $text;
public $postId; protected $postId;
public $commentDate; protected $commentDate;
public $commenterId; protected $commenterId;
public function validate() public function validate()
{ {
//todo $text = trim($this->getText());
$config = getConfig();
if (strlen($text) < $config->comments->minLength)
throw new SimpleException('Comment must have at least %d characters', $config->comments->minLength);
if (strlen($text) > $config->comments->maxLength)
throw new SimpleException('Comment must have at most %d characters', $config->comments->maxLength);
if (!$this->getPostId())
throw new SimpleException('Trying to save comment that doesn\'t refer to any post');
if (!$this->getDateTime())
throw new SimpleException('Trying to save comment that has no creation date specified');
$this->setText($text);
} }
public function getText() public function getText()
{ {
return TextHelper::parseMarkdown($this->text); return $this->text;
} }
public function setPost($post) public function getTextMarkdown()
{ {
$this->setCache('post', $post); return TextHelper::parseMarkdown($this->getText());
$this->postId = $post->id;
} }
public function setCommenter($user) public function setText($text)
{ {
$this->setCache('commenter', $user); $this->text = $text;
$this->commenterId = $user ? $user->id : null;
} }
public function getPost() public function getPost()
{ {
if ($this->hasCache('post')) if ($this->hasCache('post'))
return $this->getCache('post'); return $this->getCache('post');
$post = PostModel::findById($this->postId); $post = PostModel::findById($this->getPostId());
$this->setCache('post', $post); $this->setCache('post', $post);
return $post; return $post;
} }
public function getPostId()
{
return $this->postId;
}
public function setPost($post)
{
$this->setCache('post', $post);
$this->postId = $post->getId();
}
public function getDateTime()
{
return $this->commentDate;
}
public function setDateTime($dateTime)
{
$this->commentDate = $dateTime;
}
public function getCommenter() public function getCommenter()
{ {
if ($this->hasCache('commenter')) if ($this->hasCache('commenter'))
return $this->getCache('commenter'); return $this->getCache('commenter');
$user = UserModel::findById($this->commenterId, false); $user = UserModel::findById($this->getCommenterId(), false);
$this->setCache('commenter', $user); $this->setCache('commenter', $user);
return $user; return $user;
} }
public function getCommenterId()
{
return $this->commenterId;
}
public function setCommenter($user)
{
$this->setCache('commenter', $user);
$this->commenterId = $user ? $user->getId() : null;
}
} }

View file

@ -16,7 +16,7 @@ Assets::addScript('comment-edit.js');
<div class="form-row text"> <div class="form-row text">
<div class="input-wrapper"> <div class="input-wrapper">
<textarea name="text" cols="50" rows="3"><?= $this->context->transport->comment->text ?></textarea> <textarea name="text" cols="50" rows="3"><?= $this->context->transport->comment->getText() ?></textarea>
</div> </div>
</div> </div>

View file

@ -32,8 +32,8 @@ Assets::addScript('comment-edit.js');
<?php endif ?> <?php endif ?>
</span> </span>
<span class="date" title="<?= TextHelper::formatDate($this->context->comment->commentDate, true) ?>"> <span class="date" title="<?= TextHelper::formatDate($this->context->comment->getDateTime(), true) ?>">
<?= TextHelper::formatDate($this->context->comment->commentDate, false) ?> <?= TextHelper::formatDate($this->context->comment->getDateTime(), false) ?>
</span> </span>
<?php if (Access::check(new Privilege( <?php if (Access::check(new Privilege(
@ -64,7 +64,7 @@ Assets::addScript('comment-edit.js');
</div> </div>
<div class="content"> <div class="content">
<?= $this->context->comment->getText() ?> <?= $this->context->comment->getTextMarkdown() ?>
</div> </div>
</div> </div>

View file

@ -35,7 +35,7 @@ class AbstractTest
$comment = CommentModel::spawn(); $comment = CommentModel::spawn();
$comment->setPost($post); $comment->setPost($post);
$comment->setCommenter($owner); $comment->setCommenter($owner);
$comment->text = 'test test'; $comment->setText('test test');
return CommentModel::save($comment); return CommentModel::save($comment);
} }
} }

View file

@ -14,10 +14,10 @@ class CommentAddTest extends AbstractTest
}); });
$this->assert->areEqual(1, CommentModel::getCount()); $this->assert->areEqual(1, CommentModel::getCount());
$this->assert->areEqual($text, $comment->text); $this->assert->areEqual($text, $comment->getText());
$this->assert->areEqual(Auth::getCurrentUser()->getId(), $comment->getCommenter()->getId()); $this->assert->areEqual(Auth::getCurrentUser()->getId(), $comment->getCommenter()->getId());
$this->assert->areEqual(1, $comment->getPost()->getId()); $this->assert->areEqual(1, $comment->getPost()->getId());
$this->assert->isNotNull($comment->commentDate); $this->assert->isNotNull($comment->getDateTime());
$this->assert->doesNotThrow(function() use ($comment) $this->assert->doesNotThrow(function() use ($comment)
{ {
CommentModel::findById($comment->getId()); CommentModel::findById($comment->getId());
@ -101,7 +101,7 @@ class CommentAddTest extends AbstractTest
return $this->runApi($text); return $this->runApi($text);
}); });
$this->assert->areEqual($text, $comment->text); $this->assert->areEqual($text, $comment->getText());
$this->assert->areEqual(Auth::getCurrentUser()->getId(), $comment->getCommenter()->getId()); $this->assert->areEqual(Auth::getCurrentUser()->getId(), $comment->getCommenter()->getId());
$this->assert->areEqual(UserModel::getAnonymousName(), $comment->getCommenter()->getName()); $this->assert->areEqual(UserModel::getAnonymousName(), $comment->getCommenter()->getName());
} }

View file

@ -11,10 +11,10 @@ class CommentEditTest extends AbstractTest
return $this->runApi($text); return $this->runApi($text);
}); });
$this->assert->areEqual($text, $comment->text); $this->assert->areEqual($text, $comment->getText());
$this->assert->areEqual(Auth::getCurrentUser()->getId(), $comment->getCommenter()->getId()); $this->assert->areEqual(Auth::getCurrentUser()->getId(), $comment->getCommenter()->getId());
$this->assert->areEqual(1, $comment->getPost()->getId()); $this->assert->areEqual(1, $comment->getPost()->getId());
$this->assert->isNotNull($comment->commentDate); $this->assert->isNotNull($comment->getDateTime());
$this->assert->doesNotThrow(function() use ($comment) $this->assert->doesNotThrow(function() use ($comment)
{ {
CommentModel::findById($comment->getId()); CommentModel::findById($comment->getId());

View file

@ -0,0 +1,103 @@
<?php
class CommentPreviewTest extends AbstractTest
{
public function testPreview()
{
$this->prepare();
$text = 'alohaaaaaaa';
$comment = $this->assert->doesNotThrow(function() use ($text)
{
return $this->runApi($text);
});
$this->assert->areEqual(0, CommentModel::getCount());
$this->assert->areEqual($text, $comment->getText());
$this->assert->areEqual(Auth::getCurrentUser()->getId(), $comment->getCommenter()->getId());
$this->assert->isNotNull($comment->getDateTime());
$this->assert->throws(function() use ($comment)
{
CommentModel::findById($comment->getId());
}, 'Invalid comment ID');
}
public function testAlmostTooShortText()
{
$this->prepare();
$this->assert->doesNotThrow(function()
{
return $this->runApi(str_repeat('b', getConfig()->comments->minLength));
});
}
public function testAlmostTooLongText()
{
$this->prepare();
$this->assert->doesNotThrow(function()
{
return $this->runApi(str_repeat('b', getConfig()->comments->maxLength));
});
}
public function testTooShortText()
{
$this->prepare();
$this->assert->throws(function()
{
return $this->runApi(str_repeat('b', getConfig()->comments->minLength - 1));
}, 'Comment must have at least');
}
public function testTooLongText()
{
$this->prepare();
$this->assert->throws(function()
{
return $this->runApi(str_repeat('b', getConfig()->comments->maxLength + 1));
}, 'Comment must have at most');
}
public function testNoAuth()
{
$this->prepare();
Auth::setCurrentUser(null);
$this->assert->throws(function()
{
$this->assert->isFalse(Auth::isLoggedIn());
return $this->runApi('alohaaaaaaa');
}, 'Insufficient privileges');
}
public function testAccessDenial()
{
$this->prepare();
getConfig()->privileges->addComment = 'nobody';
Access::init();
$this->assert->isFalse(Access::check(new Privilege(Privilege::AddComment)));
$this->assert->throws(function()
{
return $this->runApi('alohaaaaaaa');
}, 'Insufficient privileges');
}
protected function runApi($text)
{
$post = $this->mockPost();
return Api::run(
new PreviewCommentJob(),
[
PreviewCommentJob::POST_ID => $post->getId(),
PreviewCommentJob::TEXT => $text,
]);
}
protected function prepare()
{
$this->login($this->mockUser());
}
}