summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrédéric Guillot <fguillot@users.noreply.github.com>2014-03-23 22:10:43 -0400
committerFrédéric Guillot <fguillot@users.noreply.github.com>2014-03-23 22:10:43 -0400
commit0d55f5aa35d21b79c5d79f7214c4c9e05b1d2684 (patch)
tree3a70e8fbf58dcbe93df0597f70a1f0bb893e5f40
parentab63ffafc565e75c73c27910abd465bebb09306e (diff)
Comment edit/remove actions
-rw-r--r--assets/css/app.css88
-rw-r--r--controllers/base.php86
-rw-r--r--controllers/comment.php191
-rw-r--r--controllers/task.php73
-rw-r--r--core/helper.php6
-rw-r--r--locales/fr_FR/translations.php10
-rw-r--r--locales/pl_PL/translations.php10
-rw-r--r--models/acl.php3
-rw-r--r--models/comment.php115
-rw-r--r--templates/comment_forbidden.php9
-rw-r--r--templates/comment_remove.php18
-rw-r--r--templates/comment_show.php36
-rw-r--r--templates/task_show.php21
-rw-r--r--tests/CommentTest.php94
14 files changed, 659 insertions, 101 deletions
diff --git a/assets/css/app.css b/assets/css/app.css
index 8bce328d..a2a73be2 100644
--- a/assets/css/app.css
+++ b/assets/css/app.css
@@ -556,7 +556,8 @@ article .task-score {
}
#description {
- border-left: 5px solid #000;
+ border: 1px solid #999;
+ border-radius: 5px;
background: #f0f0f0;
padding: 10px;
}
@@ -594,42 +595,85 @@ article .task-score {
background: #fff;
padding: 10px;
border-radius: 5px;
+ border: 1px dashed #000;
overflow: auto;
color: #000;
}
+.markdown blockquote {
+ font-style: italic;
+ border-left: 5px solid #ddd;
+ padding-left: 8px;
+}
+
/* comments */
.comment {
- margin: 10px 0;
- padding: 10px;
- border-left: 5px solid #000;
+ margin-bottom: 25px;
+ padding: 0;
+ border: 1px solid #ddd;
+ border-radius: 5px;
}
-.comment:nth-child(odd) {
- background-color: #f0f0f0;
+.comment-edit {
+ margin-bottom: 25px;
+ padding: 0;
+ border: 2px solid #000;
+ border-radius: 5px;
}
-.comment:nth-child(even) {
- background-color: #ddd;
+.comment:hover {
+ border: 1px solid #888;
}
-.comment p:first-child {
- font-size: .8em;
- margin-bottom: 10px;
- border-bottom: 1px dotted #000;
+.comment-title {
+ font-size: 0.9em;
+ padding: 5px;
+ margin-bottom: 2px;
+ border-bottom: 1px solid #ddd;
+ border-top-left-radius: 5px;
+ border-top-right-radius: 5px;
+ background: #f0f0f0;
+}
+
+.comment:nth-child(odd) .comment-title {
+ background: #f0f0f0;
}
-.comment p:first-child a {
+.comment:nth-child(even) .comment-title {
+ background: #ddd;
+}
+
+.comment-actions a,
+.comment-title a {
color: #000;
text-decoration: none;
}
-.comment p:first-child a:hover,
-.comment p:first-child a:focus {
+.comment-actions a:hover,
+.comment-actions a:focus,
+.comment-title a:hover,
+.comment-title a:focus {
text-decoration: underline;
}
-.comment .username {
+.comment-actions {
+ font-size: 0.8em;
+ padding: 0;
+ text-align: right;
+}
+
+.comment-actions li {
+ display: inline;
+ padding-left: 5px;
+ padding-right: 5px;
+ border-right: 1px dotted #000;
+}
+
+.comment-actions li:last-child {
+ border: 0;
+}
+
+.comment-username {
font-weight: bold;
}
@@ -638,6 +682,18 @@ article .task-score {
width: 500px;
}
+.comment .markdown {
+ margin: 10px;
+}
+
+.comment .markdown pre {
+ background: #fdfdfd;
+}
+
+.comment-edit form {
+ border: none;
+}
+
/* task colors */
tr td.task-blue,
.task-blue {
diff --git a/controllers/base.php b/controllers/base.php
index 81fb8884..cb76cc05 100644
--- a/controllers/base.php
+++ b/controllers/base.php
@@ -2,8 +2,20 @@
namespace Controller;
+/**
+ * Base controller
+ *
+ * @package controller
+ * @author Frederic Guillot
+ */
abstract class Base
{
+ /**
+ * Constructor
+ *
+ * @access public
+ * @param Core\Registry $registry
+ */
public function __construct(\Core\Registry $registry)
{
$this->acl = $registry->acl;
@@ -17,6 +29,11 @@ abstract class Base
$this->event = $registry->shared('event');
}
+ /**
+ * Method executed before each action
+ *
+ * @access public
+ */
public function beforeAction($controller, $action)
{
// Start the session
@@ -50,7 +67,13 @@ abstract class Base
$this->action->attachEvents();
}
- public function checkProjectPermissions($project_id)
+ /**
+ * Check if the current user have access to the given project
+ *
+ * @access protected
+ * @param integer $project_id Project id
+ */
+ protected function checkProjectPermissions($project_id)
{
if ($this->acl->isRegularUser()) {
@@ -60,14 +83,73 @@ abstract class Base
}
}
- public function redirectNoProject()
+ /**
+ * Redirection when there is no project in the database
+ *
+ * @access protected
+ */
+ protected function redirectNoProject()
{
$this->session->flash(t('There is no active project, the first step is to create a new project.'));
$this->response->redirect('?controller=project&action=create');
}
+ /**
+ * Application not found page (404 error)
+ *
+ * @access public
+ */
public function notfound()
{
$this->response->html($this->template->layout('app_notfound', array('title' => t('Page not found'))));
}
+
+ /**
+ * Display the template show task (common between different actions)
+ *
+ * @access protected
+ * @param array $task Task data
+ * @param array $comment_form Comment form data
+ * @param array $description_form Description form data
+ * @param array $comment_edit_form Comment edit form data
+ */
+ protected function showTask(array $task, array $comment_form = array(), array $description_form = array(), array $comment_edit_form = array())
+ {
+ if (empty($comment_form)) {
+ $comment_form = array(
+ 'values' => array('task_id' => $task['id'], 'user_id' => $this->acl->getUserId()),
+ 'errors' => array()
+ );
+ }
+
+ if (empty($description_form)) {
+ $description_form = array(
+ 'values' => array('id' => $task['id']),
+ 'errors' => array()
+ );
+ }
+
+ if (empty($comment_edit_form)) {
+ $comment_edit_form = array(
+ 'values' => array('id' => 0),
+ 'errors' => array()
+ );
+ }
+ else {
+ $hide_comment_form = true;
+ }
+
+ $this->response->html($this->template->layout('task_show', array(
+ 'hide_comment_form' => isset($hide_comment_form),
+ 'comment_edit_form' => $comment_edit_form,
+ 'comment_form' => $comment_form,
+ 'description_form' => $description_form,
+ 'comments' => $this->comment->getAll($task['id']),
+ 'task' => $task,
+ 'columns_list' => $this->board->getColumnsList($task['project_id']),
+ 'colors_list' => $this->task->getColors(),
+ 'menu' => 'tasks',
+ 'title' => $task['title'],
+ )));
+ }
}
diff --git a/controllers/comment.php b/controllers/comment.php
new file mode 100644
index 00000000..93dbb5ad
--- /dev/null
+++ b/controllers/comment.php
@@ -0,0 +1,191 @@
+<?php
+
+namespace Controller;
+
+require_once __DIR__.'/base.php';
+
+/**
+ * Comment controller
+ *
+ * @package controller
+ * @author Frederic Guillot
+ */
+class Comment extends Base
+{
+ /**
+ * Forbidden page for comments
+ *
+ * @access public
+ */
+ public function forbidden()
+ {
+ $this->response->html($this->template->layout('comment_forbidden', array(
+ 'menu' => 'tasks',
+ 'title' => t('Access Forbidden')
+ )));
+ }
+
+ /**
+ * Add a comment
+ *
+ * @access public
+ */
+ public function save()
+ {
+ $task = $this->task->getById($this->request->getIntegerParam('task_id'), true);
+ $values = $this->request->getValues();
+
+ if (! $task) $this->notfound();
+ $this->checkProjectPermissions($task['project_id']);
+
+ list($valid, $errors) = $this->comment->validateCreation($values);
+
+ if ($valid) {
+
+ if ($this->comment->create($values)) {
+ $this->session->flash(t('Comment added successfully.'));
+ }
+ else {
+ $this->session->flashError(t('Unable to create your comment.'));
+ }
+
+ $this->response->redirect('?controller=task&action=show&task_id='.$task['id']);
+ }
+
+ $this->showTask(
+ $task,
+ array('values' => $values, 'errors' => $errors)
+ );
+ }
+
+ /**
+ * Edit a comment
+ *
+ * @access public
+ */
+ public function edit()
+ {
+ $task_id = $this->request->getIntegerParam('task_id');
+ $comment_id = $this->request->getIntegerParam('comment_id');
+
+ $task = $this->task->getById($task_id, true);
+ $comment = $this->comment->getById($comment_id);
+
+ if (! $task || ! $comment) $this->notfound();
+ $this->checkProjectPermissions($task['project_id']);
+
+ if ($this->acl->isAdminUser() || $comment['user_id'] == $this->acl->getUserId()) {
+
+ $this->showTask(
+ $task,
+ array(),
+ array(),
+ array('values' => array('id' => $comment['id']), 'errors' => array())
+ );
+ }
+
+ $this->forbidden();
+ }
+
+ /**
+ * Update and validate a comment
+ *
+ * @access public
+ */
+ public function update()
+ {
+ $task_id = $this->request->getIntegerParam('task_id');
+ $comment_id = $this->request->getIntegerParam('comment_id');
+
+ $task = $this->task->getById($task_id, true);
+ $comment = $this->comment->getById($comment_id);
+
+ $values = $this->request->getValues();
+
+ if (! $task || ! $comment) $this->notfound();
+ $this->checkProjectPermissions($task['project_id']);
+
+ if ($this->acl->isAdminUser() || $comment['user_id'] == $this->acl->getUserId()) {
+
+ list($valid, $errors) = $this->comment->validateModification($values);
+
+ if ($valid) {
+
+ if ($this->comment->update($values)) {
+ $this->session->flash(t('Comment updated successfully.'));
+ }
+ else {
+ $this->session->flashError(t('Unable to update your comment.'));
+ }
+
+ $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'#comment-'.$comment_id);
+ }
+
+ $this->showTask(
+ $task,
+ array(),
+ array(),
+ array('values' => $values, 'errors' => $errors)
+ );
+ }
+
+ $this->forbidden();
+ }
+
+ /**
+ * Confirmation dialog before removing a comment
+ *
+ * @access public
+ */
+ public function confirm()
+ {
+ $project_id = $this->request->getIntegerParam('project_id');
+ $comment_id = $this->request->getIntegerParam('comment_id');
+
+ $this->checkProjectPermissions($project_id);
+
+ $comment = $this->comment->getById($comment_id);
+ if (! $comment) $this->notfound();
+
+ if ($this->acl->isAdminUser() || $comment['user_id'] == $this->acl->getUserId()) {
+
+ $this->response->html($this->template->layout('comment_remove', array(
+ 'comment' => $comment,
+ 'project_id' => $project_id,
+ 'menu' => 'tasks',
+ 'title' => t('Remove a comment')
+ )));
+ }
+
+ $this->forbidden();
+ }
+
+ /**
+ * Remove a comment
+ *
+ * @access public
+ */
+ public function remove()
+ {
+ $project_id = $this->request->getIntegerParam('project_id');
+ $comment_id = $this->request->getIntegerParam('comment_id');
+
+ $this->checkProjectPermissions($project_id);
+
+ $comment = $this->comment->getById($comment_id);
+ if (! $comment) $this->notfound();
+
+ if ($this->acl->isAdminUser() || $comment['user_id'] == $this->acl->getUserId()) {
+
+ if ($this->comment->remove($comment['id'])) {
+ $this->session->flash(t('Comment removed successfully.'));
+ } else {
+ $this->session->flashError(t('Unable to remove this comment.'));
+ }
+
+ $this->response->redirect('?controller=task&action=show&task_id='.$comment['task_id']);
+ }
+
+ $this->forbidden();
+ }
+}
diff --git a/controllers/task.php b/controllers/task.php
index 0dae014e..7aefb98c 100644
--- a/controllers/task.php
+++ b/controllers/task.php
@@ -52,46 +52,6 @@ class Task extends Base
}
/**
- * Display the template show task, common between different task view
- *
- * @access public
- */
- private function showTask(array $task, array $comment_form = array(), array $description_form = array())
- {
- if (empty($comment_form)) {
-
- $comment_form = array(
- 'values' => array(
- 'task_id' => $task['id'],
- 'user_id' => $this->acl->getUserId()
- ),
- 'errors' => array()
- );
- }
-
- if (empty($description_form)) {
-
- $description_form = array(
- 'values' => array(
- 'id' => $task['id'],
- ),
- 'errors' => array()
- );
- }
-
- $this->response->html($this->template->layout('task_show', array(
- 'comment_form' => $comment_form,
- 'description_form' => $description_form,
- 'comments' => $this->comment->getAll($task['id']),
- 'task' => $task,
- 'columns_list' => $this->board->getColumnsList($task['project_id']),
- 'colors_list' => $this->task->getColors(),
- 'menu' => 'tasks',
- 'title' => $task['title'],
- )));
- }
-
- /**
* Show a task
*
* @access public
@@ -107,39 +67,6 @@ class Task extends Base
}
/**
- * Add a comment
- *
- * @access public
- */
- public function comment()
- {
- $task = $this->task->getById($this->request->getIntegerParam('task_id'), true);
- $values = $this->request->getValues();
-
- if (! $task) $this->notfound();
- $this->checkProjectPermissions($task['project_id']);
-
- list($valid, $errors) = $this->comment->validateCreation($values);
-
- if ($valid) {
-
- if ($this->comment->create($values)) {
- $this->session->flash(t('Comment added successfully.'));
- }
- else {
- $this->session->flashError(t('Unable to create your comment.'));
- }
-
- $this->response->redirect('?controller=task&action=show&task_id='.$task['id']);
- }
-
- $this->showTask(
- $task,
- array('values' => $values, 'errors' => $errors)
- );
- }
-
- /**
* Add a description from the show task page
*
* @access public
diff --git a/core/helper.php b/core/helper.php
index e4ad26f1..0eeec4cd 100644
--- a/core/helper.php
+++ b/core/helper.php
@@ -2,6 +2,12 @@
namespace Helper;
+function template($name, array $args = array())
+{
+ $tpl = new \Core\Template;
+ return $tpl->load($name, $args);
+}
+
function is_current_user($user_id)
{
return $_SESSION['user']['id'] == $user_id;
diff --git a/locales/fr_FR/translations.php b/locales/fr_FR/translations.php
index 4c604e28..9a73228b 100644
--- a/locales/fr_FR/translations.php
+++ b/locales/fr_FR/translations.php
@@ -254,4 +254,14 @@ return array(
'Move Down' => 'Déplacer vers le bas',
'Duplicate to another project' => 'Dupliquer dans un autre projet',
'Duplicate' => 'Dupliquer',
+ 'link' => 'lien',
+ 'Update this comment' => 'Mettre à jour ce commentaire',
+ 'Comment updated successfully.' => 'Commentaire mis à jour avec succès.',
+ 'Unable to update your comment.' => 'Impossible de supprimer votre commentaire.',
+ 'Remove a comment' => 'Supprimer un commentaire',
+ 'Comment removed successfully.' => 'Commentaire supprimé avec succès.',
+ 'Unable to remove this comment.' => 'Impossible de supprimer ce commentaire.',
+ 'Do you really want to remove this comment?' => 'Voulez-vous vraiment supprimer ce commentaire ?',
+ 'Only administrators or the creator of the comment can access to this page.' => 'Uniquement les administrateurs ou le créateur du commentaire peuvent accéder à cette page.',
+ 'Details' => 'Détails',
);
diff --git a/locales/pl_PL/translations.php b/locales/pl_PL/translations.php
index c030bebf..27ffdef7 100644
--- a/locales/pl_PL/translations.php
+++ b/locales/pl_PL/translations.php
@@ -257,4 +257,14 @@ return array(
// 'Move Down' => '',
// 'Duplicate to another project' => '',
// 'Duplicate' => '',
+ // 'link' => '',
+ // 'Update this comment' => '',
+ // 'Comment updated successfully.' => '',
+ // 'Unable to update your comment.' => '',
+ // 'Remove a comment' => '',
+ // 'Comment removed successfully.' => '',
+ // 'Unable to remove this comment.' => '',
+ // 'Do you really want to remove this comment?' => '',
+ // 'Only administrators or the creator of the comment can access to this page.' => '',
+ // 'Details' => '',
);
diff --git a/models/acl.php b/models/acl.php
index fe23bbb4..ea7dd5cb 100644
--- a/models/acl.php
+++ b/models/acl.php
@@ -18,7 +18,8 @@ class Acl extends Base
'app' => array('index'),
'board' => array('index', 'show', 'assign', 'assigntask', 'save'),
'project' => array('tasks', 'index', 'forbidden'),
- 'task' => array('show', 'create', 'save', 'edit', 'update', 'close', 'confirmclose', 'open', 'confirmopen', 'comment', 'description', 'duplicate'),
+ 'task' => array('show', 'create', 'save', 'edit', 'update', 'close', 'confirmclose', 'open', 'confirmopen', 'description', 'duplicate'),
+ 'comment' => array('save', 'confirm', 'remove', 'update', 'edit'),
'user' => array('index', 'edit', 'update', 'forbidden', 'logout', 'index'),
'config' => array('index'),
);
diff --git a/models/comment.php b/models/comment.php
index c476e693..453c2afc 100644
--- a/models/comment.php
+++ b/models/comment.php
@@ -7,10 +7,28 @@ require_once __DIR__.'/base.php';
use \SimpleValidator\Validator;
use \SimpleValidator\Validators;
+/**
+ * Comment model
+ *
+ * @package model
+ * @author Frederic Guillot
+ */
class Comment extends Base
{
+ /**
+ * SQL table name
+ *
+ * @var string
+ */
const TABLE = 'comments';
+ /**
+ * Get all comments for a given task
+ *
+ * @access public
+ * @param integer $task_id Task id
+ * @return array
+ */
public function getAll($task_id)
{
return $this->db
@@ -18,6 +36,8 @@ class Comment extends Base
->columns(
self::TABLE.'.id',
self::TABLE.'.date',
+ self::TABLE.'.task_id',
+ self::TABLE.'.user_id',
self::TABLE.'.comment',
User::TABLE.'.username'
)
@@ -27,6 +47,37 @@ class Comment extends Base
->findAll();
}
+ /**
+ * Get a comment
+ *
+ * @access public
+ * @param integer $comment_id Comment id
+ * @return array
+ */
+ public function getById($comment_id)
+ {
+ return $this->db
+ ->table(self::TABLE)
+ ->columns(
+ self::TABLE.'.id',
+ self::TABLE.'.task_id',
+ self::TABLE.'.user_id',
+ self::TABLE.'.date',
+ self::TABLE.'.comment',
+ User::TABLE.'.username'
+ )
+ ->join(User::TABLE, 'id', 'user_id')
+ ->eq(self::TABLE.'.id', $comment_id)
+ ->findOne();
+ }
+
+ /**
+ * Get the number of comments for a given task
+ *
+ * @access public
+ * @param integer $task_id Task id
+ * @return integer
+ */
public function count($task_id)
{
return $this->db
@@ -35,13 +86,54 @@ class Comment extends Base
->count();
}
+ /**
+ * Save a comment in the database
+ *
+ * @access public
+ * @param array $values Form values
+ * @return boolean
+ */
public function create(array $values)
{
$values['date'] = time();
- return (bool) $this->db->table(self::TABLE)->save($values);
+ return $this->db->table(self::TABLE)->save($values);
+ }
+
+ /**
+ * Update a comment in the database
+ *
+ * @access public
+ * @param array $values Form values
+ * @return boolean
+ */
+ public function update(array $values)
+ {
+ return $this->db
+ ->table(self::TABLE)
+ ->eq('id', $values['id'])
+ ->update(array('comment' => $values['comment']));
+ }
+
+ /**
+ * Remove a comment
+ *
+ * @access public
+ * @param integer $comment_id Comment id
+ * @return boolean
+ */
+ public function remove($comment_id)
+ {
+ return $this->db->table(self::TABLE)->eq('id', $comment_id)->remove();
}
+ /**
+ * Validate comment creation
+ *
+ * @access public
+ * @param array $values Required parameters to save an action
+ * @return array $valid, $errors [0] = Success or not, [1] = List of errors
+ */
public function validateCreation(array $values)
{
$v = new Validator($values, array(
@@ -57,4 +149,25 @@ class Comment extends Base
$v->getErrors()
);
}
+
+ /**
+ * Validate comment modification
+ *
+ * @access public
+ * @param array $values Required parameters to save an action
+ * @return array $valid, $errors [0] = Success or not, [1] = List of errors
+ */
+ public function validateModification(array $values)
+ {
+ $v = new Validator($values, array(
+ new Validators\Required('id', t('This value is required')),
+ new Validators\Integer('id', t('This value must be an integer')),
+ new Validators\Required('comment', t('Comment is required'))
+ ));
+
+ return array(
+ $v->execute(),
+ $v->getErrors()
+ );
+ }
}
diff --git a/templates/comment_forbidden.php b/templates/comment_forbidden.php
new file mode 100644
index 00000000..eeea8404
--- /dev/null
+++ b/templates/comment_forbidden.php
@@ -0,0 +1,9 @@
+<section id="main">
+ <div class="page-header">
+ <h2><?= t('Forbidden') ?></h2>
+ </div>
+
+ <p class="alert alert-error">
+ <?= t('Only administrators or the creator of the comment can access to this page.') ?>
+ </p>
+</section> \ No newline at end of file
diff --git a/templates/comment_remove.php b/templates/comment_remove.php
new file mode 100644
index 00000000..ad1b8e4a
--- /dev/null
+++ b/templates/comment_remove.php
@@ -0,0 +1,18 @@
+<section id="main">
+ <div class="page-header">
+ <h2><?= t('Remove a comment') ?></h2>
+ </div>
+
+ <div class="confirm">
+ <p class="alert alert-info">
+ <?= t('Do you really want to remove this comment?') ?>
+ </p>
+
+ <?= Helper\template('comment_show', array('comment' => $comment)) ?>
+
+ <div class="form-actions">
+ <a href="?controller=comment&amp;action=remove&amp;project_id=<?= $project_id ?>&amp;comment_id=<?= $comment['id'] ?>" class="btn btn-red"><?= t('Yes') ?></a>
+ <?= t('or') ?> <a href="?controller=task&amp;action=show&amp;task_id=<?= $comment['task_id'] ?>#comment-<?= $comment['id'] ?>"><?= t('cancel') ?></a>
+ </div>
+ </div>
+</section> \ No newline at end of file
diff --git a/templates/comment_show.php b/templates/comment_show.php
new file mode 100644
index 00000000..24bf9070
--- /dev/null
+++ b/templates/comment_show.php
@@ -0,0 +1,36 @@
+<div class="<?= isset($display_edit_form) && $display_edit_form === true ? 'comment-edit' : 'comment' ?>" id="comment-<?= $comment['id'] ?>">
+ <p class="comment-title">
+ <span class="comment-username"><?= Helper\escape($comment['username']) ?></span> @ <span class="comment-date"><?= dt('%B %e, %G at %k:%M %p', $comment['date']) ?></span>
+ </p>
+ <?php if (isset($task)): ?>
+ <ul class="comment-actions">
+ <li><a href="#comment-<?= $comment['id'] ?>"><?= t('link') ?></a></li>
+ <?php if (Helper\is_admin() || Helper\is_current_user($comment['user_id'])): ?>
+ <li>
+ <a href="?controller=comment&amp;action=confirm&amp;project_id=<?= $task['project_id'] ?>&amp;comment_id=<?= $comment['id'] ?>"><?= t('remove') ?></a>
+ </li>
+ <li>
+ <a href="?controller=comment&amp;action=edit&amp;task_id=<?= $task['id'] ?>&amp;comment_id=<?= $comment['id'] ?>#comment-<?= $comment['id'] ?>"><?= t('edit') ?></a>
+ </li>
+ <?php endif ?>
+ </ul>
+ <?php endif ?>
+
+ <?php if (isset($display_edit_form) && $display_edit_form === true): ?>
+ <form method="post" action="?controller=comment&amp;action=update&amp;task_id=<?= $task['id'] ?>&amp;comment_id=<?= $comment['id'] ?>" autocomplete="off">
+
+ <?= Helper\form_hidden('id', $values) ?>
+ <?= Helper\form_textarea('comment', $values, $errors, array('required', 'placeholder="'.t('Leave a comment').'"')) ?><br/>
+
+ <div class="form-actions">
+ <input type="submit" value="<?= t('Update this comment') ?>" class="btn btn-blue"/>
+ <?= t('or') ?>
+ <a href="?controller=task&amp;action=show&amp;task_id=<?= $task['id'] ?>"><?= t('cancel') ?></a>
+ </div>
+ </form>
+ <?php else: ?>
+ <div class="markdown">
+ <?= Helper\markdown($comment['comment']) ?>
+ </div>
+ <?php endif ?>
+</div> \ No newline at end of file
diff --git a/templates/task_show.php b/templates/task_show.php
index 986b240d..409e5205 100644
--- a/templates/task_show.php
+++ b/templates/task_show.php
@@ -8,7 +8,7 @@
</ul>
</div>
<section>
- <h3><?= t('Details') ?></h3>
+ <h2><?= t('Details') ?></h2>
<article id="infos" class="task task-<?= $task['color_id'] ?>">
<?php if ($task['score']): ?>
<span class="task-score"><?= Helper\escape($task['score']) ?></span>
@@ -60,7 +60,7 @@
</ul>
</article>
- <h3><?= t('Description') ?></h3>
+ <h2><?= t('Description') ?></h2>
<?php if ($task['description']): ?>
<article id="description" class="markdown">
<?= Helper\markdown($task['description']) ?: t('There is no description.') ?>
@@ -78,19 +78,23 @@
</form>
<?php endif ?>
- <h3><?= t('Comments') ?></h3>
+ <h2><?= t('Comments') ?></h2>
<?php if ($comments): ?>
<ul id="comments">
<?php foreach ($comments as $comment): ?>
- <div class="comment markdown" id="comment-<?= $comment['id'] ?>">
- <p><span class="username"><?= Helper\escape($comment['username']) ?></span> @ <a href="#comment-<?= $comment['id'] ?>"><?= dt('%B %e, %G at %k:%M %p', $comment['date']) ?></a></p>
- <?= Helper\markdown($comment['comment']) ?>
- </div>
+ <?= Helper\template('comment_show', array(
+ 'comment' => $comment,
+ 'task' => $task,
+ 'display_edit_form' => $comment['id'] == $comment_edit_form['values']['id'],
+ 'values' => $comment_edit_form['values'] + array('comment' => $comment['comment']),
+ 'errors' => $comment_edit_form['errors']
+ )) ?>
<?php endforeach ?>
</ul>
<?php endif ?>
- <form method="post" action="?controller=task&amp;action=comment&amp;task_id=<?= $task['id'] ?>" autocomplete="off">
+ <?php if (! isset($hide_comment_form) || $hide_comment_form === false): ?>
+ <form method="post" action="?controller=comment&amp;action=save&amp;task_id=<?= $task['id'] ?>" autocomplete="off">
<?= Helper\form_hidden('task_id', $comment_form['values']) ?>
<?= Helper\form_hidden('user_id', $comment_form['values']) ?>
@@ -101,5 +105,6 @@
<input type="submit" value="<?= t('Post comment') ?>" class="btn btn-blue"/>
</div>
</form>
+ <?php endif ?>
</section>
</section>
diff --git a/tests/CommentTest.php b/tests/CommentTest.php
new file mode 100644
index 00000000..c23c4e51
--- /dev/null
+++ b/tests/CommentTest.php
@@ -0,0 +1,94 @@
+<?php
+
+require_once __DIR__.'/base.php';
+
+use Model\Task;
+use Model\Project;
+use Model\Comment;
+
+class CommentTest extends Base
+{
+ public function testCreate()
+ {
+ $c = new Comment($this->db, $this->event);
+ $t = new Task($this->db, $this->event);
+ $p = new Project($this->db, $this->event);
+
+ $this->assertEquals(1, $p->create(array('name' => 'test1')));
+ $this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
+ $this->assertTrue($c->create(array('task_id' => 1, 'comment' => 'bla bla', 'user_id' => 1)));
+
+ $comment = $c->getById(1);
+
+ $this->assertNotEmpty($comment);
+ $this->assertEquals('bla bla', $comment['comment']);
+ $this->assertEquals(1, $comment['task_id']);
+ $this->assertEquals(1, $comment['user_id']);
+ $this->assertEquals('admin', $comment['username']);
+ $this->assertNotEmpty($comment['date']);
+ }
+
+ public function testGetAll()
+ {
+ $c = new Comment($this->db, $this->event);
+ $t = new Task($this->db, $this->event);
+ $p = new Project($this->db, $this->event);
+
+ $this->assertEquals(1, $p->create(array('name' => 'test1')));
+ $this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
+ $this->assertTrue($c->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1)));
+ $this->assertTrue($c->create(array('task_id' => 1, 'comment' => 'c2', 'user_id' => 1)));
+ $this->assertTrue($c->create(array('task_id' => 1, 'comment' => 'c3', 'user_id' => 1)));
+
+ $comments = $c->getAll(1);
+
+ $this->assertNotEmpty($comments);
+ $this->assertEquals(3, count($comments));
+ $this->assertEquals(1, $comments[0]['id']);
+ $this->assertEquals(2, $comments[1]['id']);
+ $this->assertEquals(3, $comments[2]['id']);
+ }
+
+ public function testUpdate()
+ {
+ $c = new Comment($this->db, $this->event);
+ $t = new Task($this->db, $this->event);
+ $p = new Project($this->db, $this->event);
+
+ $this->assertEquals(1, $p->create(array('name' => 'test1')));
+ $this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
+ $this->assertTrue($c->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1)));
+ $this->assertTrue($c->update(array('id' => 1, 'comment' => 'bla')));
+
+ $comment = $c->getById(1);
+ $this->assertNotEmpty($comment);
+ $this->assertEquals('bla', $comment['comment']);
+
+ $this->assertFalse($c->update(array('id' => 4, 'comment' => 'bla')));
+ }
+
+ public function testValidateCreation()
+ {
+ $c = new Comment($this->db, $this->event);
+
+ $this->assertTrue($c->validateCreation(['user_id' => 1, 'task_id' => 1, 'comment' => 'bla'])[0]);
+ $this->assertFalse($c->validateCreation(['user_id' => 1, 'task_id' => 1, 'comment' => ''])[0]);
+ $this->assertFalse($c->validateCreation(['user_id' => 1, 'task_id' => 'a', 'comment' => 'bla'])[0]);
+ $this->assertFalse($c->validateCreation(['user_id' => 'b', 'task_id' => 1, 'comment' => 'bla'])[0]);
+ $this->assertFalse($c->validateCreation(['user_id' => 1, 'comment' => 'bla'])[0]);
+ $this->assertFalse($c->validateCreation(['task_id' => 1, 'comment' => 'bla'])[0]);
+ $this->assertFalse($c->validateCreation(['comment' => 'bla'])[0]);
+ $this->assertFalse($c->validateCreation([])[0]);
+ }
+
+ public function testValidateModification()
+ {
+ $c = new Comment($this->db, $this->event);
+
+ $this->assertTrue($c->validateModification(['id' => 1, 'comment' => 'bla'])[0]);
+ $this->assertFalse($c->validateModification(['id' => 1, 'comment' => ''])[0]);
+ $this->assertFalse($c->validateModification(['comment' => 'bla'])[0]);
+ $this->assertFalse($c->validateModification(['id' => 'b', 'comment' => 'bla'])[0]);
+ $this->assertFalse($c->validateModification([])[0]);
+ }
+}