summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrédéric Guillot <fred@kanboard.net>2014-10-12 21:38:56 -0400
committerFrédéric Guillot <fred@kanboard.net>2014-10-12 21:38:56 -0400
commit074056352de98fc567b4d13184c72887c75625d0 (patch)
tree7d262c3a5d5f779648f51aa0eb7d9f279c05d89d
parent4061927d215c846ff8eb196301bf61532018042b (diff)
Project activity refactoring and listeners improvements
-rw-r--r--app/Action/Base.php1
-rw-r--r--app/Controller/Base.php4
-rw-r--r--app/Controller/Project.php4
-rw-r--r--app/Core/Event.php5
-rw-r--r--app/Event/Base.php79
-rw-r--r--app/Event/BaseNotificationListener.php87
-rw-r--r--app/Event/CommentHistoryListener.php73
-rw-r--r--app/Event/CommentNotificationListener.php30
-rw-r--r--app/Event/FileNotificationListener.php30
-rw-r--r--app/Event/NotificationListener.php83
-rw-r--r--app/Event/ProjectActivityListener.php61
-rw-r--r--app/Event/ProjectModificationDate.php63
-rw-r--r--app/Event/ProjectModificationDateListener.php30
-rw-r--r--app/Event/SubTaskNotificationListener.php30
-rw-r--r--app/Event/SubtaskHistoryListener.php73
-rw-r--r--app/Event/TaskHistoryListener.php63
-rw-r--r--app/Event/TaskNotificationListener.php29
-rw-r--r--app/Event/WebhookListener.php32
-rw-r--r--app/Locales/de_DE/translations.php4
-rw-r--r--app/Locales/es_ES/translations.php4
-rw-r--r--app/Locales/fi_FI/translations.php4
-rw-r--r--app/Locales/fr_FR/translations.php4
-rw-r--r--app/Locales/it_IT/translations.php4
-rw-r--r--app/Locales/pl_PL/translations.php4
-rw-r--r--app/Locales/pt_BR/translations.php4
-rw-r--r--app/Locales/ru_RU/translations.php4
-rw-r--r--app/Locales/sv_SE/translations.php4
-rw-r--r--app/Locales/zh_CN/translations.php4
-rw-r--r--app/Model/BaseHistory.php70
-rw-r--r--app/Model/CommentHistory.php152
-rw-r--r--app/Model/Notification.php60
-rw-r--r--app/Model/Project.php35
-rw-r--r--app/Model/ProjectActivity.php189
-rw-r--r--app/Model/SubtaskHistory.php161
-rw-r--r--app/Model/TaskHistory.php160
-rw-r--r--app/Model/Webhook.php11
-rw-r--r--app/Schema/Mysql.php27
-rw-r--r--app/Schema/Postgres.php24
-rw-r--r--app/Schema/Sqlite.php24
-rw-r--r--app/Templates/event_comment_create.php8
-rw-r--r--app/Templates/event_comment_update.php8
-rw-r--r--app/Templates/event_subtask_create.php25
-rw-r--r--app/Templates/event_subtask_update.php25
-rw-r--r--app/Templates/event_task_assignee_change.php10
-rw-r--r--app/Templates/event_task_close.php2
-rw-r--r--app/Templates/event_task_create.php2
-rw-r--r--app/Templates/event_task_move_column.php4
-rw-r--r--app/Templates/event_task_move_position.php4
-rw-r--r--app/Templates/event_task_open.php2
-rw-r--r--app/Templates/event_task_update.php2
-rw-r--r--app/Templates/project_activity.php16
-rw-r--r--app/Templates/project_feed.php4
-rw-r--r--app/Templates/task_public.php2
-rw-r--r--assets/css/app.css19
-rw-r--r--tests/units/ProjectActivityTest.php (renamed from tests/units/TaskHistoryTest.php)38
-rw-r--r--tests/units/ProjectTest.php2
56 files changed, 695 insertions, 1208 deletions
diff --git a/app/Action/Base.php b/app/Action/Base.php
index 339aeecc..80930a4c 100644
--- a/app/Action/Base.php
+++ b/app/Action/Base.php
@@ -14,6 +14,7 @@ use Core\Tool;
*
* @property \Model\Acl $acl
* @property \Model\Task $task
+ * @property \Model\TaskFinder $taskFinder
*/
abstract class Base implements Listener
{
diff --git a/app/Controller/Base.php b/app/Controller/Base.php
index ac88df04..a8e22fd8 100644
--- a/app/Controller/Base.php
+++ b/app/Controller/Base.php
@@ -153,13 +153,11 @@ abstract class Base
private function attachEvents()
{
$models = array(
+ 'projectActivity', // Order is important
'action',
'project',
'webhook',
'notification',
- 'taskHistory',
- 'commentHistory',
- 'subtaskHistory',
);
foreach ($models as $model) {
diff --git a/app/Controller/Project.php b/app/Controller/Project.php
index 39d8d1b0..1fac3ffb 100644
--- a/app/Controller/Project.php
+++ b/app/Controller/Project.php
@@ -364,7 +364,7 @@ class Project extends Base
}
$this->response->xml($this->template->load('project_feed', array(
- 'events' => $this->project->getActivity($project['id']),
+ 'events' => $this->projectActivity->getAll($project['id']),
'project' => $project,
)));
}
@@ -379,7 +379,7 @@ class Project extends Base
$project = $this->getProject();
$this->response->html($this->template->layout('project_activity', array(
- 'events' => $this->project->getActivity($project['id']),
+ 'events' => $this->projectActivity->getAll($project['id']),
'menu' => 'projects',
'project' => $project,
'title' => t('%s\'s activity', $project['name'])
diff --git a/app/Core/Event.php b/app/Core/Event.php
index 0e6df5e8..a32499d8 100644
--- a/app/Core/Event.php
+++ b/app/Core/Event.php
@@ -69,11 +69,14 @@ class Event
{
if (! $this->isEventTriggered($eventName)) {
- $this->lastEvent = $eventName;
$this->events[] = $eventName;
if (isset($this->listeners[$eventName])) {
+
foreach ($this->listeners[$eventName] as $listener) {
+
+ $this->lastEvent = $eventName;
+
if ($listener->execute($data)) {
$this->lastListener = get_class($listener);
}
diff --git a/app/Event/Base.php b/app/Event/Base.php
new file mode 100644
index 00000000..745871a5
--- /dev/null
+++ b/app/Event/Base.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Event;
+
+use Core\Listener;
+use Core\Registry;
+use Core\Tool;
+
+/**
+ * Base Listener
+ *
+ * @package event
+ * @author Frederic Guillot
+ *
+ * @property \Model\Comment $comment
+ * @property \Model\Project $project
+ * @property \Model\ProjectActivity $projectActivity
+ * @property \Model\SubTask $subTask
+ * @property \Model\Task $task
+ * @property \Model\TaskFinder $taskFinder
+ */
+abstract class Base implements Listener
+{
+ /**
+ * Registry instance
+ *
+ * @access protected
+ * @var \Core\Registry
+ */
+ protected $registry;
+
+ /**
+ * Constructor
+ *
+ * @access public
+ * @param \Core\Registry $registry Regsitry instance
+ */
+ public function __construct(Registry $registry)
+ {
+ $this->registry = $registry;
+ }
+
+ /**
+ * Return class information
+ *
+ * @access public
+ * @return string
+ */
+ public function __toString()
+ {
+ return get_called_class();
+ }
+
+ /**
+ * Load automatically models
+ *
+ * @access public
+ * @param string $name Model name
+ * @return mixed
+ */
+ public function __get($name)
+ {
+ return Tool::loadModel($this->registry, $name);
+ }
+
+ /**
+ * Get event namespace
+ *
+ * Event = task.close | Namespace = task
+ *
+ * @access public
+ * @return string
+ */
+ public function getEventNamespace()
+ {
+ $event_name = $this->registry->event->getLastTriggeredEvent();
+ return substr($event_name, 0, strpos($event_name, '.'));
+ }
+}
diff --git a/app/Event/BaseNotificationListener.php b/app/Event/BaseNotificationListener.php
deleted file mode 100644
index fdabaf57..00000000
--- a/app/Event/BaseNotificationListener.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-
-namespace Event;
-
-use Core\Listener;
-use Model\Notification;
-
-/**
- * Base notification listener
- *
- * @package event
- * @author Frederic Guillot
- */
-abstract class BaseNotificationListener implements Listener
-{
- /**
- * Notification model
- *
- * @accesss protected
- * @var Model\Notification
- */
- protected $notification;
-
- /**
- * Template name
- *
- * @accesss private
- * @var string
- */
- private $template = '';
-
- /**
- * Fetch data for the mail template
- *
- * @access public
- * @param array $data Event data
- * @return array
- */
- abstract public function getTemplateData(array $data);
-
- /**
- * Constructor
- *
- * @access public
- * @param \Model\Notification $notification Notification model instance
- * @param string $template Template name
- */
- public function __construct(Notification $notification, $template)
- {
- $this->template = $template;
- $this->notification = $notification;
- }
-
- /**
- * Return class information
- *
- * @access public
- * @return string
- */
- public function __toString()
- {
- return get_called_class();
- }
-
- /**
- * Execute the action
- *
- * @access public
- * @param array $data Event data dictionary
- * @return bool True if the action was executed or false when not executed
- */
- public function execute(array $data)
- {
- $values = $this->getTemplateData($data);
-
- // Get the list of users to be notified
- $users = $this->notification->getUsersList($values['task']['project_id']);
-
- // Send notifications
- if ($users) {
- $this->notification->sendEmails($this->template, $users, $values);
- return true;
- }
-
- return false;
- }
-}
diff --git a/app/Event/CommentHistoryListener.php b/app/Event/CommentHistoryListener.php
deleted file mode 100644
index ec826615..00000000
--- a/app/Event/CommentHistoryListener.php
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-
-namespace Event;
-
-use Core\Listener;
-use Model\CommentHistory;
-
-/**
- * Comment history listener
- *
- * @package event
- * @author Frederic Guillot
- */
-class CommentHistoryListener implements Listener
-{
- /**
- * Comment History model
- *
- * @accesss private
- * @var \Model\CommentHistory
- */
- private $model;
-
- /**
- * Constructor
- *
- * @access public
- * @param \Model\CommentHistory $model Comment History model instance
- */
- public function __construct(CommentHistory $model)
- {
- $this->model = $model;
- }
-
- /**
- * Return class information
- *
- * @access public
- * @return string
- */
- public function __toString()
- {
- return get_called_class();
- }
-
- /**
- * Execute the action
- *
- * @access public
- * @param array $data Event data dictionary
- * @return bool True if the action was executed or false when not executed
- */
- public function execute(array $data)
- {
- $creator_id = $this->model->acl->getUserId();
-
- if ($creator_id && isset($data['task_id']) && isset($data['id'])) {
-
- $task = $this->model->taskFinder->getById($data['task_id']);
-
- $this->model->create(
- $task['project_id'],
- $data['task_id'],
- $data['id'],
- $creator_id,
- $this->model->event->getLastTriggeredEvent(),
- $data['comment']
- );
- }
-
- return false;
- }
-}
diff --git a/app/Event/CommentNotificationListener.php b/app/Event/CommentNotificationListener.php
deleted file mode 100644
index 13803874..00000000
--- a/app/Event/CommentNotificationListener.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-namespace Event;
-
-use Event\BaseNotificationListener;
-
-/**
- * Comment notification listener
- *
- * @package event
- * @author Frederic Guillot
- */
-class CommentNotificationListener extends BaseNotificationListener
-{
- /**
- * Fetch data for the mail template
- *
- * @access public
- * @param array $data Event data
- * @return array
- */
- public function getTemplateData(array $data)
- {
- $values = array();
- $values['comment'] = $this->notification->comment->getById($data['id']);
- $values['task'] = $this->notification->taskFinder->getDetails($values['comment']['task_id']);
-
- return $values;
- }
-}
diff --git a/app/Event/FileNotificationListener.php b/app/Event/FileNotificationListener.php
deleted file mode 100644
index 2366ce5d..00000000
--- a/app/Event/FileNotificationListener.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-namespace Event;
-
-use Event\BaseNotificationListener;
-
-/**
- * File notification listener
- *
- * @package event
- * @author Frederic Guillot
- */
-class FileNotificationListener extends BaseNotificationListener
-{
- /**
- * Fetch data for the mail template
- *
- * @access public
- * @param array $data Event data
- * @return array
- */
- public function getTemplateData(array $data)
- {
- $values = array();
- $values['file'] = $data;
- $values['task'] = $this->notification->taskFinder->getDetails($data['task_id']);
-
- return $values;
- }
-}
diff --git a/app/Event/NotificationListener.php b/app/Event/NotificationListener.php
new file mode 100644
index 00000000..3c049327
--- /dev/null
+++ b/app/Event/NotificationListener.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace Event;
+
+/**
+ * Notification listener
+ *
+ * @package event
+ * @author Frederic Guillot
+ */
+class NotificationListener extends Base
+{
+ /**
+ * Template name
+ *
+ * @accesss private
+ * @var string
+ */
+ private $template = '';
+
+ /**
+ * Set template name
+ *
+ * @access public
+ * @param string $template Template name
+ */
+ public function setTemplate($template)
+ {
+ $this->template = $template;
+ }
+
+ /**
+ * Execute the action
+ *
+ * @access public
+ * @param array $data Event data dictionary
+ * @return bool True if the action was executed or false when not executed
+ */
+ public function execute(array $data)
+ {
+ $values = $this->getTemplateData($data);
+ $users = $this->notification->getUsersList($values['task']['project_id']);
+
+ if ($users) {
+ $this->notification->sendEmails($this->template, $users, $values);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Fetch data for the mail template
+ *
+ * @access public
+ * @param array $data Event data
+ * @return array
+ */
+ public function getTemplateData(array $data)
+ {
+ $values = array();
+
+ switch ($this->getEventNamespace()) {
+ case 'task':
+ $values['task'] = $this->taskFinder->getDetails($data['task_id']);
+ break;
+ case 'subtask':
+ $values['subtask'] = $this->subtask->getById($data['id'], true);
+ $values['task'] = $this->taskFinder->getDetails($data['task_id']);
+ break;
+ case 'file':
+ $values['file'] = $data;
+ $values['task'] = $this->taskFinder->getDetails($data['task_id']);
+ break;
+ case 'comment':
+ $values['comment'] = $this->comment->getById($data['id']);
+ $values['task'] = $this->taskFinder->getDetails($values['comment']['task_id']);
+ break;
+ }
+
+ return $values;
+ }
+}
diff --git a/app/Event/ProjectActivityListener.php b/app/Event/ProjectActivityListener.php
new file mode 100644
index 00000000..8958bd2b
--- /dev/null
+++ b/app/Event/ProjectActivityListener.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace Event;
+
+/**
+ * Project activity listener
+ *
+ * @package event
+ * @author Frederic Guillot
+ */
+class ProjectActivityListener extends Base
+{
+ /**
+ * Execute the action
+ *
+ * @access public
+ * @param array $data Event data dictionary
+ * @return bool True if the action was executed or false when not executed
+ */
+ public function execute(array $data)
+ {
+ if (isset($data['task_id'])) {
+
+ $values = $this->getValues($data);
+
+ return $this->projectActivity->createEvent(
+ $values['task']['project_id'],
+ $values['task']['id'],
+ $this->acl->getUserId(),
+ $this->registry->event->getLastTriggeredEvent(),
+ $values
+ );
+ }
+
+ return false;
+ }
+
+ /**
+ * Get event activity data
+ *
+ * @access private
+ * @param array $data Event data dictionary
+ * @return array
+ */
+ private function getValues(array $data)
+ {
+ $values = array();
+ $values['task'] = $this->taskFinder->getDetails($data['task_id']);
+
+ switch ($this->getEventNamespace()) {
+ case 'subtask':
+ $values['subtask'] = $this->subTask->getById($data['id'], true);
+ break;
+ case 'comment':
+ $values['comment'] = $this->comment->getById($data['id']);
+ break;
+ }
+
+ return $values;
+ }
+}
diff --git a/app/Event/ProjectModificationDate.php b/app/Event/ProjectModificationDate.php
deleted file mode 100644
index 1b0b3736..00000000
--- a/app/Event/ProjectModificationDate.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-namespace Event;
-
-use Core\Listener;
-use Model\Project;
-
-/**
- * Project modification date listener
- *
- * Update the last modified field for a project
- *
- * @package event
- * @author Frederic Guillot
- */
-class ProjectModificationDate implements Listener
-{
- /**
- * Project model
- *
- * @accesss private
- * @var \Model\Project
- */
- private $project;
-
- /**
- * Constructor
- *
- * @access public
- * @param \Model\Project $project Project model instance
- */
- public function __construct(Project $project)
- {
- $this->project = $project;
- }
-
- /**
- * Return class information
- *
- * @access public
- * @return string
- */
- public function __toString()
- {
- return get_called_class();
- }
-
- /**
- * Execute the action
- *
- * @access public
- * @param array $data Event data dictionary
- * @return bool True if the action was executed or false when not executed
- */
- public function execute(array $data)
- {
- if (isset($data['project_id'])) {
- return $this->project->updateModificationDate($data['project_id']);
- }
-
- return false;
- }
-}
diff --git a/app/Event/ProjectModificationDateListener.php b/app/Event/ProjectModificationDateListener.php
new file mode 100644
index 00000000..abc176b0
--- /dev/null
+++ b/app/Event/ProjectModificationDateListener.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Event;
+
+/**
+ * Project modification date listener
+ *
+ * Update the "last_modified" field for a project
+ *
+ * @package event
+ * @author Frederic Guillot
+ */
+class ProjectModificationDateListener extends Base
+{
+ /**
+ * Execute the action
+ *
+ * @access public
+ * @param array $data Event data dictionary
+ * @return bool True if the action was executed or false when not executed
+ */
+ public function execute(array $data)
+ {
+ if (isset($data['project_id'])) {
+ return $this->project->updateModificationDate($data['project_id']);
+ }
+
+ return false;
+ }
+}
diff --git a/app/Event/SubTaskNotificationListener.php b/app/Event/SubTaskNotificationListener.php
deleted file mode 100644
index 2b35d757..00000000
--- a/app/Event/SubTaskNotificationListener.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-namespace Event;
-
-use Event\BaseNotificationListener;
-
-/**
- * SubTask notification listener
- *
- * @package event
- * @author Frederic Guillot
- */
-class SubTaskNotificationListener extends BaseNotificationListener
-{
- /**
- * Fetch data for the mail template
- *
- * @access public
- * @param array $data Event data
- * @return array
- */
- public function getTemplateData(array $data)
- {
- $values = array();
- $values['subtask'] = $this->notification->subtask->getById($data['id'], true);
- $values['task'] = $this->notification->taskFinder->getDetails($data['task_id']);
-
- return $values;
- }
-}
diff --git a/app/Event/SubtaskHistoryListener.php b/app/Event/SubtaskHistoryListener.php
deleted file mode 100644
index 6b4f1c2d..00000000
--- a/app/Event/SubtaskHistoryListener.php
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-
-namespace Event;
-
-use Core\Listener;
-use Model\SubtaskHistory;
-
-/**
- * Subtask history listener
- *
- * @package event
- * @author Frederic Guillot
- */
-class SubtaskHistoryListener implements Listener
-{
- /**
- * Comment History model
- *
- * @accesss private
- * @var \Model\SubtaskHistory
- */
- private $model;
-
- /**
- * Constructor
- *
- * @access public
- * @param \Model\SubtaskHistory $model Subtask History model instance
- */
- public function __construct(SubtaskHistory $model)
- {
- $this->model = $model;
- }
-
- /**
- * Return class information
- *
- * @access public
- * @return string
- */
- public function __toString()
- {
- return get_called_class();
- }
-
- /**
- * Execute the action
- *
- * @access public
- * @param array $data Event data dictionary
- * @return bool True if the action was executed or false when not executed
- */
- public function execute(array $data)
- {
- $creator_id = $this->model->acl->getUserId();
-
- if ($creator_id && isset($data['task_id']) && isset($data['id'])) {
-
- $task = $this->model->taskFinder->getById($data['task_id']);
-
- $this->model->create(
- $task['project_id'],
- $data['task_id'],
- $data['id'],
- $creator_id,
- $this->model->event->getLastTriggeredEvent(),
- ''
- );
- }
-
- return false;
- }
-}
diff --git a/app/Event/TaskHistoryListener.php b/app/Event/TaskHistoryListener.php
deleted file mode 100644
index d963fa71..00000000
--- a/app/Event/TaskHistoryListener.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-namespace Event;
-
-use Core\Listener;
-use Model\TaskHistory;
-
-/**
- * Task history listener
- *
- * @package event
- * @author Frederic Guillot
- */
-class TaskHistoryListener implements Listener
-{
- /**
- * Task History model
- *
- * @accesss private
- * @var \Model\TaskHistory
- */
- private $model;
-
- /**
- * Constructor
- *
- * @access public
- * @param \Model\TaskHistory $model Task History model instance
- */
- public function __construct(TaskHistory $model)
- {
- $this->model = $model;
- }
-
- /**
- * Return class information
- *
- * @access public
- * @return string
- */
- public function __toString()
- {
- return get_called_class();
- }
-
- /**
- * Execute the action
- *
- * @access public
- * @param array $data Event data dictionary
- * @return bool True if the action was executed or false when not executed
- */
- public function execute(array $data)
- {
- $creator_id = $this->model->acl->getUserId();
-
- if ($creator_id && isset($data['task_id']) && isset($data['project_id'])) {
- $this->model->create($data['project_id'], $data['task_id'], $creator_id, $this->model->event->getLastTriggeredEvent());
- }
-
- return false;
- }
-}
diff --git a/app/Event/TaskNotificationListener.php b/app/Event/TaskNotificationListener.php
deleted file mode 100644
index 119e61e5..00000000
--- a/app/Event/TaskNotificationListener.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-namespace Event;
-
-use Event\BaseNotificationListener;
-
-/**
- * Task notification listener
- *
- * @package event
- * @author Frederic Guillot
- */
-class TaskNotificationListener extends BaseNotificationListener
-{
- /**
- * Fetch data for the mail template
- *
- * @access public
- * @param array $data Event data
- * @return array
- */
- public function getTemplateData(array $data)
- {
- $values = array();
- $values['task'] = $this->notification->taskFinder->getDetails($data['task_id']);
-
- return $values;
- }
-}
diff --git a/app/Event/WebhookListener.php b/app/Event/WebhookListener.php
index c2f6d56a..f7e23e07 100644
--- a/app/Event/WebhookListener.php
+++ b/app/Event/WebhookListener.php
@@ -2,26 +2,15 @@
namespace Event;
-use Core\Listener;
-use Model\Webhook;
-
/**
* Webhook task events
*
* @package event
* @author Frederic Guillot
*/
-class WebhookListener implements Listener
+class WebhookListener extends Base
{
/**
- * Webhook model
- *
- * @accesss private
- * @var \Model\Webhook
- */
- private $webhook;
-
- /**
* Url to call
*
* @access private
@@ -30,27 +19,14 @@ class WebhookListener implements Listener
private $url = '';
/**
- * Constructor
+ * Set webhook url
*
* @access public
- * @param string $url URL to call
- * @param \Model\Webhook $webhook Webhook model instance
+ * @param string $url URL to call
*/
- public function __construct($url, Webhook $webhook)
+ public function setUrl($url)
{
$this->url = $url;
- $this->webhook = $webhook;
- }
-
- /**
- * Return class information
- *
- * @access public
- * @return string
- */
- public function __toString()
- {
- return get_called_class();
}
/**
diff --git a/app/Locales/de_DE/translations.php b/app/Locales/de_DE/translations.php
index fdf96638..4b901148 100644
--- a/app/Locales/de_DE/translations.php
+++ b/app/Locales/de_DE/translations.php
@@ -495,8 +495,8 @@ return array(
// 'Default values are "%s"' => '',
// 'Default columns for new projects (Comma-separated)' => '',
// 'Task assignee change' => '',
- // '%s change the assignee of the task #%d' => '',
- // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>' => '',
+ // '%s change the assignee of the task #%d to %s' => '',
+ // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to %s' => '',
// '[%s][Column Change] %s (#%d)' => '',
// '[%s][Position Change] %s (#%d)' => '',
// '[%s][Assignee Change] %s (#%d)' => '',
diff --git a/app/Locales/es_ES/translations.php b/app/Locales/es_ES/translations.php
index 368a11ee..0cdd5f32 100644
--- a/app/Locales/es_ES/translations.php
+++ b/app/Locales/es_ES/translations.php
@@ -495,8 +495,8 @@ return array(
'Default values are "%s"' => 'Los valores por defecto son "%s"',
'Default columns for new projects (Comma-separated)' => 'Columnas por defecto de los nuevos proyectos (Separadas mediante comas)',
'Task assignee change' => 'Cambiar persona asignada a la tarea',
- '%s change the assignee of the task #%d' => '%s cambia la persona asignada a la tarea #%d',
- '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>' => '%s cambia la persona asignada a la tarea <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>',
+ // '%s change the assignee of the task #%d to %s' => '',
+ // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to %s' => '',
'[%s][Column Change] %s (#%d)' => '[%s][Cambia Columna] %s (#%d)',
'[%s][Position Change] %s (#%d)' => '[%s][Cambia Posición] %s (#%d)',
'[%s][Assignee Change] %s (#%d)' => '[%s][Cambia Persona Asignada] %s (#%d)',
diff --git a/app/Locales/fi_FI/translations.php b/app/Locales/fi_FI/translations.php
index 2a2f3e96..5d05e92d 100644
--- a/app/Locales/fi_FI/translations.php
+++ b/app/Locales/fi_FI/translations.php
@@ -495,8 +495,8 @@ return array(
// 'Default values are "%s"' => '',
// 'Default columns for new projects (Comma-separated)' => '',
// 'Task assignee change' => '',
- // '%s change the assignee of the task #%d' => '',
- // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>' => '',
+ // '%s change the assignee of the task #%d to %s' => '',
+ // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to %s' => '',
// '[%s][Column Change] %s (#%d)' => '',
// '[%s][Position Change] %s (#%d)' => '',
// '[%s][Assignee Change] %s (#%d)' => '',
diff --git a/app/Locales/fr_FR/translations.php b/app/Locales/fr_FR/translations.php
index 49e6bc2f..f4bffc3b 100644
--- a/app/Locales/fr_FR/translations.php
+++ b/app/Locales/fr_FR/translations.php
@@ -495,8 +495,8 @@ return array(
'Default values are "%s"' => 'Les valeurs par défaut sont « %s »',
'Default columns for new projects (Comma-separated)' => 'Colonnes par défaut pour les nouveaux projets (séparé par des virgules)',
'Task assignee change' => 'Modification de la personne assignée sur une tâche',
- '%s change the assignee of the task #%d' => '%s a changé la personne assignée sur la tâche #%d',
- '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>' => '%s a changé la personne assignée sur la tâche <a href="?controller=task&amp;action=show&amp;task_id=%d">n°%d</a>',
+ '%s change the assignee of the task #%d to %s' => '%s a changé la personne assignée sur la tâche #%d pour %s',
+ '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to %s' => '%s a changé la personne assignée sur la tâche <a href="?controller=task&amp;action=show&amp;task_id=%d">n°%d</a> pour %s',
'[%s][Column Change] %s (#%d)' => '[%s][Changement de colonne] %s (#%d)',
'[%s][Position Change] %s (#%d)' => '[%s][Changement de position] %s (#%d)',
'[%s][Assignee Change] %s (#%d)' => '[%s][Changement d\'assigné] %s (#%d)',
diff --git a/app/Locales/it_IT/translations.php b/app/Locales/it_IT/translations.php
index 9f532438..5854d033 100644
--- a/app/Locales/it_IT/translations.php
+++ b/app/Locales/it_IT/translations.php
@@ -495,8 +495,8 @@ return array(
// 'Default values are "%s"' => '',
// 'Default columns for new projects (Comma-separated)' => '',
// 'Task assignee change' => '',
- // '%s change the assignee of the task #%d' => '',
- // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>' => '',
+ // '%s change the assignee of the task #%d to %s' => '',
+ // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to %s' => '',
// '[%s][Column Change] %s (#%d)' => '',
// '[%s][Position Change] %s (#%d)' => '',
// '[%s][Assignee Change] %s (#%d)' => '',
diff --git a/app/Locales/pl_PL/translations.php b/app/Locales/pl_PL/translations.php
index f2e96bb6..fe76b34c 100644
--- a/app/Locales/pl_PL/translations.php
+++ b/app/Locales/pl_PL/translations.php
@@ -495,8 +495,8 @@ return array(
// 'Default values are "%s"' => '',
// 'Default columns for new projects (Comma-separated)' => '',
// 'Task assignee change' => '',
- // '%s change the assignee of the task #%d' => '',
- // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>' => '',
+ // '%s change the assignee of the task #%d to %s' => '',
+ // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to %s' => '',
// '[%s][Column Change] %s (#%d)' => '',
// '[%s][Position Change] %s (#%d)' => '',
// '[%s][Assignee Change] %s (#%d)' => '',
diff --git a/app/Locales/pt_BR/translations.php b/app/Locales/pt_BR/translations.php
index 3f208361..59fcc983 100644
--- a/app/Locales/pt_BR/translations.php
+++ b/app/Locales/pt_BR/translations.php
@@ -495,8 +495,8 @@ return array(
// 'Default values are "%s"' => '',
// 'Default columns for new projects (Comma-separated)' => '',
// 'Task assignee change' => '',
- // '%s change the assignee of the task #%d' => '',
- // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>' => '',
+ // '%s change the assignee of the task #%d to %s' => '',
+ // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to %s' => '',
// '[%s][Column Change] %s (#%d)' => '',
// '[%s][Position Change] %s (#%d)' => '',
// '[%s][Assignee Change] %s (#%d)' => '',
diff --git a/app/Locales/ru_RU/translations.php b/app/Locales/ru_RU/translations.php
index 5c634184..1f5bfea2 100644
--- a/app/Locales/ru_RU/translations.php
+++ b/app/Locales/ru_RU/translations.php
@@ -495,8 +495,8 @@ return array(
'Default values are "%s"' => 'Колонки по умолчанию: "%s"',
'Default columns for new projects (Comma-separated)' => 'Колонки по умолчанию для новых проектов (разделять запятой)',
// 'Task assignee change' => '',
- // '%s change the assignee of the task #%d' => '',
- // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>' => '',
+ // '%s change the assignee of the task #%d to %s' => '',
+ // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to %s' => '',
// '[%s][Column Change] %s (#%d)' => '',
// '[%s][Position Change] %s (#%d)' => '',
// '[%s][Assignee Change] %s (#%d)' => '',
diff --git a/app/Locales/sv_SE/translations.php b/app/Locales/sv_SE/translations.php
index a96b6c9a..20b685ef 100644
--- a/app/Locales/sv_SE/translations.php
+++ b/app/Locales/sv_SE/translations.php
@@ -495,8 +495,8 @@ return array(
// 'Default values are "%s"' => '',
// 'Default columns for new projects (Comma-separated)' => '',
// 'Task assignee change' => '',
- // '%s change the assignee of the task #%d' => '',
- // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>' => '',
+ // '%s change the assignee of the task #%d to %s' => '',
+ // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to %s' => '',
// '[%s][Column Change] %s (#%d)' => '',
// '[%s][Position Change] %s (#%d)' => '',
// '[%s][Assignee Change] %s (#%d)' => '',
diff --git a/app/Locales/zh_CN/translations.php b/app/Locales/zh_CN/translations.php
index ea7183c7..92f46ef9 100644
--- a/app/Locales/zh_CN/translations.php
+++ b/app/Locales/zh_CN/translations.php
@@ -495,8 +495,8 @@ return array(
// 'Default values are "%s"' => '',
// 'Default columns for new projects (Comma-separated)' => '',
// 'Task assignee change' => '',
- // '%s change the assignee of the task #%d' => '',
- // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>' => '',
+ // '%s change the assignee of the task #%d to %s' => '',
+ // '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to %s' => '',
// '[%s][Column Change] %s (#%d)' => '',
// '[%s][Position Change] %s (#%d)' => '',
// '[%s][Assignee Change] %s (#%d)' => '',
diff --git a/app/Model/BaseHistory.php b/app/Model/BaseHistory.php
deleted file mode 100644
index 31578a3b..00000000
--- a/app/Model/BaseHistory.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-
-namespace Model;
-
-use PDO;
-use Core\Template;
-
-/**
- * Task history model
- *
- * @package model
- * @author Frederic Guillot
- */
-abstract class BaseHistory extends Base
-{
- /**
- * SQL table name
- *
- * @access protected
- * @var string
- */
- protected $table = '';
-
- /**
- * Remove old event entries to avoid a large table
- *
- * @access public
- * @param integer $max Maximum number of items to keep in the table
- */
- public function cleanup($max)
- {
- if ($this->db->table($this->table)->count() > $max) {
-
- $this->db->execute('
- DELETE FROM '.$this->table.'
- WHERE id <= (
- SELECT id FROM (
- SELECT id FROM '.$this->table.' ORDER BY id DESC LIMIT 1 OFFSET '.$max.'
- ) foo
- )');
- }
- }
-
- /**
- * Get all events for a given project
- *
- * @access public
- * @return array
- */
- public function getAllByProjectId($project_id)
- {
- return $this->db->table($this->table)
- ->eq('project_id', $project_id)
- ->desc('id')
- ->findAll();
- }
-
- /**
- * Get the event html content
- *
- * @access public
- * @param array $params Event properties
- * @return string
- */
- public function getContent(array $params)
- {
- $tpl = new Template;
- return $tpl->load('event_'.str_replace('.', '_', $params['event_name']), $params);
- }
-}
diff --git a/app/Model/CommentHistory.php b/app/Model/CommentHistory.php
deleted file mode 100644
index 5988c026..00000000
--- a/app/Model/CommentHistory.php
+++ /dev/null
@@ -1,152 +0,0 @@
-<?php
-
-namespace Model;
-
-use PDO;
-use Core\Registry;
-use Event\CommentHistoryListener;
-
-/**
- * Comment history model
- *
- * @package model
- * @author Frederic Guillot
- */
-class CommentHistory extends BaseHistory
-{
- /**
- * SQL table name
- *
- * @var string
- */
- const TABLE = 'comment_has_events';
-
- /**
- * Maximum number of events
- *
- * @var integer
- */
- const MAX_EVENTS = 5000;
-
- /**
- * Constructor
- *
- * @access public
- * @param \Core\Registry $registry Registry instance
- */
- public function __construct(Registry $registry)
- {
- parent::__construct($registry);
- $this->table = self::TABLE;
- }
-
- /**
- * Create a new event
- *
- * @access public
- * @param integer $project_id Project id
- * @param integer $task_id Task id
- * @param integer $comment_id Comment id
- * @param integer $creator_id Author of the event (user id)
- * @param string $event_name Task event name
- * @param string $data Current comment
- * @return boolean
- */
- public function create($project_id, $task_id, $comment_id, $creator_id, $event_name, $data)
- {
- $values = array(
- 'project_id' => $project_id,
- 'task_id' => $task_id,
- 'comment_id' => $comment_id,
- 'creator_id' => $creator_id,
- 'event_name' => $event_name,
- 'date_creation' => time(),
- 'data' => $data,
- );
-
- $this->db->startTransaction();
-
- $this->cleanup(self::MAX_EVENTS - 1);
- $result = $this->db->table(self::TABLE)->insert($values);
-
- $this->db->closeTransaction();
-
- return $result;
- }
-
- /**
- * Get all necessary content to display activity feed
- *
- * $author_name
- * $author_username
- * $task['id', 'title', 'position', 'column_name']
- */
- public function getAllContentByProjectId($project_id, $limit = 50)
- {
- $sql = '
- SELECT
- comment_has_events.id,
- comment_has_events.date_creation,
- comment_has_events.event_name,
- comment_has_events.data as comment,
- comment_has_events.task_id,
- tasks.title as task_title,
- users.username as author_username,
- users.name as author_name
- FROM comment_has_events
- LEFT JOIN users ON users.id=comment_has_events.creator_id
- LEFT JOIN tasks ON tasks.id=comment_has_events.task_id
- WHERE comment_has_events.project_id = ?
- ORDER BY comment_has_events.id DESC
- LIMIT '.$limit.' OFFSET 0
- ';
-
- $rq = $this->db->execute($sql, array($project_id));
- $events = $rq->fetchAll(PDO::FETCH_ASSOC);
-
- foreach ($events as &$event) {
- $event['author'] = $event['author_name'] ?: $event['author_username'];
- $event['event_title'] = $this->getTitle($event);
- $event['event_content'] = $this->getContent($event);
- $event['event_type'] = 'comment';
- }
-
- return $events;
- }
-
- /**
- * Get the event title (translated)
- *
- * @access public
- * @param array $event Event properties
- * @return string
- */
- public function getTitle(array $event)
- {
- $titles = array(
- Comment::EVENT_UPDATE => t('%s updated a comment on the task #%d', $event['author'], $event['task_id']),
- Comment::EVENT_CREATE => t('%s commented on the task #%d', $event['author'], $event['task_id']),
- );
-
- return isset($titles[$event['event_name']]) ? $titles[$event['event_name']] : '';
- }
-
- /**
- * Attach events to be able to record the history
- *
- * @access public
- */
- public function attachEvents()
- {
- $events = array(
- Comment::EVENT_UPDATE,
- Comment::EVENT_CREATE,
- );
-
- $listener = new CommentHistoryListener($this);
-
- foreach ($events as $event_name) {
- $this->event->attach($event_name, $listener);
- }
- }
-}
diff --git a/app/Model/Notification.php b/app/Model/Notification.php
index 4b7ae50f..0a80e335 100644
--- a/app/Model/Notification.php
+++ b/app/Model/Notification.php
@@ -5,12 +5,10 @@ namespace Model;
use Core\Session;
use Core\Translator;
use Core\Template;
-use Event\TaskNotificationListener;
-use Event\CommentNotificationListener;
-use Event\FileNotificationListener;
-use Event\SubTaskNotificationListener;
+use Event\NotificationListener;
use Swift_Message;
use Swift_Mailer;
+use Swift_TransportException;
/**
* Notification model
@@ -91,21 +89,28 @@ class Notification extends Base
*/
public function attachEvents()
{
- $this->event->attach(File::EVENT_CREATE, new FileNotificationListener($this, 'notification_file_creation'));
+ $events = array(
+ Task::EVENT_CREATE => 'notification_task_creation',
+ Task::EVENT_UPDATE => 'notification_task_update',
+ Task::EVENT_CLOSE => 'notification_task_close',
+ Task::EVENT_OPEN => 'notification_task_open',
+ Task::EVENT_MOVE_COLUMN => 'notification_task_move_column',
+ Task::EVENT_MOVE_POSITION => 'notification_task_move_position',
+ Task::EVENT_ASSIGNEE_CHANGE => 'notification_task_assignee_change',
+ SubTask::EVENT_CREATE => 'notification_subtask_creation',
+ SubTask::EVENT_UPDATE => 'notification_subtask_update',
+ Comment::EVENT_CREATE => 'notification_comment_creation',
+ Comment::EVENT_UPDATE => 'notification_comment_update',
+ File::EVENT_CREATE => 'notification_file_creation',
+ );
- $this->event->attach(Comment::EVENT_CREATE, new CommentNotificationListener($this, 'notification_comment_creation'));
- $this->event->attach(Comment::EVENT_UPDATE, new CommentNotificationListener($this, 'notification_comment_update'));
+ foreach ($events as $event_name => $template_name) {
- $this->event->attach(SubTask::EVENT_CREATE, new SubTaskNotificationListener($this, 'notification_subtask_creation'));
- $this->event->attach(SubTask::EVENT_UPDATE, new SubTaskNotificationListener($this, 'notification_subtask_update'));
+ $listener = new NotificationListener($this->registry);
+ $listener->setTemplate($template_name);
- $this->event->attach(Task::EVENT_CREATE, new TaskNotificationListener($this, 'notification_task_creation'));
- $this->event->attach(Task::EVENT_UPDATE, new TaskNotificationListener($this, 'notification_task_update'));
- $this->event->attach(Task::EVENT_CLOSE, new TaskNotificationListener($this, 'notification_task_close'));
- $this->event->attach(Task::EVENT_OPEN, new TaskNotificationListener($this, 'notification_task_open'));
- $this->event->attach(Task::EVENT_MOVE_COLUMN, new TaskNotificationListener($this, 'notification_task_move_column'));
- $this->event->attach(Task::EVENT_MOVE_POSITION, new TaskNotificationListener($this, 'notification_task_move_position'));
- $this->event->attach(Task::EVENT_ASSIGNEE_CHANGE, new TaskNotificationListener($this, 'notification_task_assignee_change'));
+ $this->event->attach($event_name, $listener);
+ }
}
/**
@@ -118,17 +123,22 @@ class Notification extends Base
*/
public function sendEmails($template, array $users, array $data)
{
- $transport = $this->registry->shared('mailer');
- $mailer = Swift_Mailer::newInstance($transport);
+ try {
+ $transport = $this->registry->shared('mailer');
+ $mailer = Swift_Mailer::newInstance($transport);
- $message = Swift_Message::newInstance()
- ->setSubject($this->getMailSubject($template, $data))
- ->setFrom(array(MAIL_FROM => 'Kanboard'))
- ->setBody($this->getMailContent($template, $data), 'text/html');
+ $message = Swift_Message::newInstance()
+ ->setSubject($this->getMailSubject($template, $data))
+ ->setFrom(array(MAIL_FROM => 'Kanboard'))
+ ->setBody($this->getMailContent($template, $data), 'text/html');
- foreach ($users as $user) {
- $message->setTo(array($user['email'] => $user['name'] ?: $user['username']));
- $mailer->send($message);
+ foreach ($users as $user) {
+ $message->setTo(array($user['email'] => $user['name'] ?: $user['username']));
+ $mailer->send($message);
+ }
+ }
+ catch (Swift_TransportException $e) {
+ debug($e->getMessage());
}
}
diff --git a/app/Model/Project.php b/app/Model/Project.php
index ad0afa82..32b7fcbe 100644
--- a/app/Model/Project.php
+++ b/app/Model/Project.php
@@ -4,7 +4,7 @@ namespace Model;
use SimpleValidator\Validator;
use SimpleValidator\Validators;
-use Event\ProjectModificationDate;
+use Event\ProjectModificationDateListener;
use Core\Security;
/**
@@ -512,41 +512,10 @@ class Project extends Base
GithubWebhook::EVENT_COMMIT,
);
- $listener = new ProjectModificationDate($this);
+ $listener = new ProjectModificationDateListener($this->registry);
foreach ($events as $event_name) {
$this->event->attach($event_name, $listener);
}
}
-
- /**
- * Get project activity
- *
- * @access public
- * @param integer $project_id Project id
- * @return array
- */
- public function getActivity($project_id)
- {
- $activity = array();
- $tasks = $this->taskHistory->getAllContentByProjectId($project_id, 25);
- $comments = $this->commentHistory->getAllContentByProjectId($project_id, 25);
- $subtasks = $this->subtaskHistory->getAllContentByProjectId($project_id, 25);
-
- foreach ($tasks as &$task) {
- $activity[$task['date_creation'].'-'.$task['id']] = $task;
- }
-
- foreach ($subtasks as &$subtask) {
- $activity[$subtask['date_creation'].'-'.$subtask['id']] = $subtask;
- }
-
- foreach ($comments as &$comment) {
- $activity[$comment['date_creation'].'-'.$comment['id']] = $comment;
- }
-
- krsort($activity);
-
- return $activity;
- }
}
diff --git a/app/Model/ProjectActivity.php b/app/Model/ProjectActivity.php
new file mode 100644
index 00000000..d2457609
--- /dev/null
+++ b/app/Model/ProjectActivity.php
@@ -0,0 +1,189 @@
+<?php
+
+namespace Model;
+
+use Core\Template;
+use Event\ProjectActivityListener;
+
+/**
+ * Project activity model
+ *
+ * @package model
+ * @author Frederic Guillot
+ */
+class ProjectActivity extends Base
+{
+ /**
+ * SQL table name
+ *
+ * @var string
+ */
+ const TABLE = 'project_activities';
+
+ /**
+ * Maximum number of events
+ *
+ * @var integer
+ */
+ const MAX_EVENTS = 5000;
+
+ /**
+ * Add a new event for the project
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param integer $task_id Task id
+ * @param integer $creator_id User id
+ * @param string $event_name Event name
+ * @param array $data Event data (will be serialized)
+ * @return boolean
+ */
+ public function createEvent($project_id, $task_id, $creator_id, $event_name, array $data)
+ {
+ $values = array(
+ 'project_id' => $project_id,
+ 'task_id' => $task_id,
+ 'creator_id' => $creator_id,
+ 'event_name' => $event_name,
+ 'date_creation' => time(),
+ 'data' => serialize($data),
+ );
+
+ $this->cleanup(self::MAX_EVENTS - 1);
+ return $this->db->table(self::TABLE)->insert($values);
+ }
+
+ /**
+ * Get all events for the given project
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param integer $limit Maximum events number
+ * @return array
+ */
+ public function getAll($project_id, $limit = 50)
+ {
+ $events = $this->db->table(self::TABLE)
+ ->columns(
+ self::TABLE.'.*',
+ User::TABLE.'.username AS author_username',
+ User::TABLE.'.name AS author_name'
+ )
+ ->eq('project_id', $project_id)
+ ->join(User::TABLE, 'id', 'creator_id')
+ ->desc('id')
+ ->limit($limit)
+ ->findAll();
+
+ foreach ($events as &$event) {
+
+ $event += unserialize($event['data']);
+ unset($event['data']);
+
+ $event['author'] = $event['author_name'] ?: $event['author_username'];
+ $event['event_title'] = $this->getTitle($event);
+ $event['event_content'] = $this->getContent($event);
+ }
+
+ return $events;
+ }
+
+ /**
+ * Remove old event entries to avoid large table
+ *
+ * @access public
+ * @param integer $max Maximum number of items to keep in the table
+ */
+ public function cleanup($max)
+ {
+ if ($this->db->table(self::TABLE)->count() > $max) {
+
+ $this->db->execute('
+ DELETE FROM '.self::TABLE.'
+ WHERE id <= (
+ SELECT id FROM (
+ SELECT id FROM '.self::TABLE.' ORDER BY id DESC LIMIT 1 OFFSET '.$max.'
+ ) foo
+ )'
+ );
+ }
+ }
+
+ /**
+ * Attach events to be able to record the history
+ *
+ * @access public
+ */
+ public function attachEvents()
+ {
+ $events = array(
+ Task::EVENT_ASSIGNEE_CHANGE,
+ Task::EVENT_UPDATE,
+ Task::EVENT_CREATE,
+ Task::EVENT_CLOSE,
+ Task::EVENT_OPEN,
+ Task::EVENT_MOVE_COLUMN,
+ Task::EVENT_MOVE_POSITION,
+ Comment::EVENT_UPDATE,
+ Comment::EVENT_CREATE,
+ SubTask::EVENT_UPDATE,
+ SubTask::EVENT_CREATE,
+ );
+
+ $listener = new ProjectActivityListener($this->registry);
+
+ foreach ($events as $event_name) {
+ $this->event->attach($event_name, $listener);
+ }
+ }
+
+ /**
+ * Get the event html content
+ *
+ * @access public
+ * @param array $params Event properties
+ * @return string
+ */
+ public function getContent(array $params)
+ {
+ $tpl = new Template;
+ return $tpl->load('event_'.str_replace('.', '_', $params['event_name']), $params);
+ }
+
+ /**
+ * Get the event title (translated)
+ *
+ * @access public
+ * @param array $event Event properties
+ * @return string
+ */
+ public function getTitle(array $event)
+ {
+ switch ($event['event_name']) {
+ case Task::EVENT_ASSIGNEE_CHANGE:
+ return t('%s change the assignee of the task #%d to %s', $event['author'], $event['task']['id'], $event['task']['assignee_name'] ?: $event['task']['assignee_username']);
+ case Task::EVENT_UPDATE:
+ return t('%s updated the task #%d', $event['author'], $event['task']['id']);
+ case Task::EVENT_CREATE:
+ return t('%s created the task #%d', $event['author'], $event['task']['id']);
+ case Task::EVENT_CLOSE:
+ return t('%s closed the task #%d', $event['author'], $event['task']['id']);
+ case Task::EVENT_OPEN:
+ return t('%s open the task #%d', $event['author'], $event['task']['id']);
+ case Task::EVENT_MOVE_COLUMN:
+ return t('%s moved the task #%d to the column "%s"', $event['author'], $event['task']['id'], $event['task']['column_title']);
+ case Task::EVENT_MOVE_POSITION:
+ return t('%s moved the task #%d to the position %d in the column "%s"', $event['author'], $event['task']['id'], $event['task']['position'], $event['task']['column_title']);
+ case SubTask::EVENT_UPDATE:
+ return t('%s updated a subtask for the task #%d', $event['author'], $event['task']['id']);
+ case SubTask::EVENT_CREATE:
+ return t('%s created a subtask for the task #%d', $event['author'], $event['task']['id']);
+ case Comment::EVENT_UPDATE:
+ return t('%s updated a comment on the task #%d', $event['author'], $event['task']['id']);
+ case Comment::EVENT_CREATE:
+ return t('%s commented on the task #%d', $event['author'], $event['task']['id']);
+ default:
+ return '';
+ }
+ }
+}
diff --git a/app/Model/SubtaskHistory.php b/app/Model/SubtaskHistory.php
deleted file mode 100644
index 89076261..00000000
--- a/app/Model/SubtaskHistory.php
+++ /dev/null
@@ -1,161 +0,0 @@
-<?php
-
-namespace Model;
-
-use PDO;
-use Core\Registry;
-use Event\SubtaskHistoryListener;
-
-/**
- * Comment history model
- *
- * @package model
- * @author Frederic Guillot
- */
-class SubtaskHistory extends BaseHistory
-{
- /**
- * SQL table name
- *
- * @var string
- */
- const TABLE = 'subtask_has_events';
-
- /**
- * Maximum number of events
- *
- * @var integer
- */
- const MAX_EVENTS = 5000;
-
- /**
- * Constructor
- *
- * @access public
- * @param \Core\Registry $registry Registry instance
- */
- public function __construct(Registry $registry)
- {
- parent::__construct($registry);
- $this->table = self::TABLE;
- }
-
- /**
- * Create a new event
- *
- * @access public
- * @param integer $project_id Project id
- * @param integer $task_id Task id
- * @param integer $subtask_id Subtask id
- * @param integer $creator_id Author of the event (user id)
- * @param string $event_name Task event name
- * @param string $data Current comment
- * @return boolean
- */
- public function create($project_id, $task_id, $subtask_id, $creator_id, $event_name, $data)
- {
- $values = array(
- 'project_id' => $project_id,
- 'task_id' => $task_id,
- 'subtask_id' => $subtask_id,
- 'creator_id' => $creator_id,
- 'event_name' => $event_name,
- 'date_creation' => time(),
- 'data' => $data,
- );
-
- $this->db->startTransaction();
-
- $this->cleanup(self::MAX_EVENTS - 1);
- $result = $this->db->table(self::TABLE)->insert($values);
-
- $this->db->closeTransaction();
-
- return $result;
- }
-
- /**
- * Get all necessary content to display activity feed
- *
- * $author_name
- * $author_username
- * $task['id', 'title', 'position', 'column_name']
- */
- public function getAllContentByProjectId($project_id, $limit = 50)
- {
- $sql = '
- SELECT
- subtask_has_events.id,
- subtask_has_events.date_creation,
- subtask_has_events.event_name,
- subtask_has_events.task_id,
- tasks.title as task_title,
- users.username as author_username,
- users.name as author_name,
- assignees.name as subtask_assignee_name,
- assignees.username as subtask_assignee_username,
- task_has_subtasks.title as subtask_title,
- task_has_subtasks.status as subtask_status,
- task_has_subtasks.time_spent as subtask_time_spent,
- task_has_subtasks.time_estimated as subtask_time_estimated
- FROM subtask_has_events
- LEFT JOIN users ON users.id=subtask_has_events.creator_id
- LEFT JOIN tasks ON tasks.id=subtask_has_events.task_id
- LEFT JOIN task_has_subtasks ON task_has_subtasks.id=subtask_has_events.subtask_id
- LEFT JOIN users AS assignees ON assignees.id=task_has_subtasks.user_id
- WHERE subtask_has_events.project_id = ?
- ORDER BY subtask_has_events.id DESC
- LIMIT '.$limit.' OFFSET 0
- ';
-
- $rq = $this->db->execute($sql, array($project_id));
- $events = $rq->fetchAll(PDO::FETCH_ASSOC);
-
- foreach ($events as &$event) {
- $event['author'] = $event['author_name'] ?: $event['author_username'];
- $event['subtask_assignee'] = $event['subtask_assignee_name'] ?: $event['subtask_assignee_username'];
- $event['subtask_status_list'] = $this->subTask->getStatusList();
- $event['event_title'] = $this->getTitle($event);
- $event['event_content'] = $this->getContent($event);
- $event['event_type'] = 'subtask';
- }
-
- return $events;
- }
-
- /**
- * Get the event title (translated)
- *
- * @access public
- * @param array $event Event properties
- * @return string
- */
- public function getTitle(array $event)
- {
- $titles = array(
- SubTask::EVENT_UPDATE => t('%s updated a subtask for the task #%d', $event['author'], $event['task_id']),
- SubTask::EVENT_CREATE => t('%s created a subtask for the task #%d', $event['author'], $event['task_id']),
- );
-
- return isset($titles[$event['event_name']]) ? $titles[$event['event_name']] : '';
- }
-
- /**
- * Attach events to be able to record the history
- *
- * @access public
- */
- public function attachEvents()
- {
- $events = array(
- SubTask::EVENT_UPDATE,
- SubTask::EVENT_CREATE,
- );
-
- $listener = new SubtaskHistoryListener($this);
-
- foreach ($events as $event_name) {
- $this->event->attach($event_name, $listener);
- }
- }
-}
diff --git a/app/Model/TaskHistory.php b/app/Model/TaskHistory.php
deleted file mode 100644
index 0615cba0..00000000
--- a/app/Model/TaskHistory.php
+++ /dev/null
@@ -1,160 +0,0 @@
-<?php
-
-namespace Model;
-
-use PDO;
-use Core\Registry;
-use Event\TaskHistoryListener;
-
-/**
- * Task history model
- *
- * @package model
- * @author Frederic Guillot
- */
-class TaskHistory extends BaseHistory
-{
- /**
- * SQL table name
- *
- * @var string
- */
- const TABLE = 'task_has_events';
-
- /**
- * Maximum number of events
- *
- * @var integer
- */
- const MAX_EVENTS = 5000;
-
- /**
- * Constructor
- *
- * @access public
- * @param \Core\Registry $registry Registry instance
- */
- public function __construct(Registry $registry)
- {
- parent::__construct($registry);
- $this->table = self::TABLE;
- }
-
- /**
- * Create a new event
- *
- * @access public
- * @param integer $project_id Project id
- * @param integer $task_id Task id
- * @param integer $creator_id Author of the event (user id)
- * @param string $event_name Task event name
- * @return boolean
- */
- public function create($project_id, $task_id, $creator_id, $event_name)
- {
- $values = array(
- 'project_id' => $project_id,
- 'task_id' => $task_id,
- 'creator_id' => $creator_id,
- 'event_name' => $event_name,
- 'date_creation' => time(),
- );
-
- $this->db->startTransaction();
-
- $this->cleanup(self::MAX_EVENTS - 1);
- $result = $this->db->table(self::TABLE)->insert($values);
-
- $this->db->closeTransaction();
-
- return $result;
- }
-
- /**
- * Get all necessary content to display activity feed
- *
- * $author_name
- * $author_username
- * $task['id', 'title', 'position', 'column_name']
- */
- public function getAllContentByProjectId($project_id, $limit = 50)
- {
- $sql = '
- SELECT
- task_has_events.id,
- task_has_events.date_creation,
- task_has_events.event_name,
- task_has_events.task_id,
- tasks.title as task_title,
- tasks.position as task_position,
- columns.title as task_column_name,
- users.username as author_username,
- users.name as author_name
- FROM task_has_events
- LEFT JOIN users ON users.id=task_has_events.creator_id
- LEFT JOIN tasks ON tasks.id=task_has_events.task_id
- LEFT JOIN columns ON columns.id=tasks.column_id
- WHERE task_has_events.project_id = ?
- ORDER BY task_has_events.id DESC
- LIMIT '.$limit.' OFFSET 0
- ';
-
- $rq = $this->db->execute($sql, array($project_id));
- $events = $rq->fetchAll(PDO::FETCH_ASSOC);
-
- foreach ($events as &$event) {
- $event['author'] = $event['author_name'] ?: $event['author_username'];
- $event['event_title'] = $this->getTitle($event);
- $event['event_content'] = $this->getContent($event);
- $event['event_type'] = 'task';
- }
-
- return $events;
- }
-
- /**
- * Get the event title (translated)
- *
- * @access public
- * @param array $event Event properties
- * @return string
- */
- public function getTitle(array $event)
- {
- $titles = array(
- Task::EVENT_ASSIGNEE_CHANGE => t('%s change the assignee of the task #%d', $event['author'], $event['task_id']),
- Task::EVENT_UPDATE => t('%s updated the task #%d', $event['author'], $event['task_id']),
- Task::EVENT_CREATE => t('%s created the task #%d', $event['author'], $event['task_id']),
- Task::EVENT_CLOSE => t('%s closed the task #%d', $event['author'], $event['task_id']),
- Task::EVENT_OPEN => t('%s open the task #%d', $event['author'], $event['task_id']),
- Task::EVENT_MOVE_COLUMN => t('%s moved the task #%d to the column "%s"', $event['author'], $event['task_id'], $event['task_column_name']),
- Task::EVENT_MOVE_POSITION => t('%s moved the task #%d to the position %d in the column "%s"', $event['author'], $event['task_id'], $event['task_position'], $event['task_column_name']),
- );
-
- return isset($titles[$event['event_name']]) ? $titles[$event['event_name']] : '';
- }
-
- /**
- * Attach events to be able to record the history
- *
- * @access public
- */
- public function attachEvents()
- {
- $events = array(
- Task::EVENT_ASSIGNEE_CHANGE,
- Task::EVENT_UPDATE,
- Task::EVENT_CREATE,
- Task::EVENT_CLOSE,
- Task::EVENT_OPEN,
- Task::EVENT_MOVE_COLUMN,
- Task::EVENT_MOVE_POSITION,
- );
-
- $listener = new TaskHistoryListener($this);
-
- foreach ($events as $event_name) {
- $this->event->attach($event_name, $listener);
- }
- }
-}
diff --git a/app/Model/Webhook.php b/app/Model/Webhook.php
index 241806ba..b84728cf 100644
--- a/app/Model/Webhook.php
+++ b/app/Model/Webhook.php
@@ -88,9 +88,13 @@ class Webhook extends Base
Task::EVENT_UPDATE,
Task::EVENT_CLOSE,
Task::EVENT_OPEN,
+ Task::EVENT_MOVE_COLUMN,
+ Task::EVENT_MOVE_POSITION,
+ Task::EVENT_ASSIGNEE_CHANGE,
);
- $listener = new WebhookListener($this->url_task_modification, $this);
+ $listener = new WebhookListener($this->registry);
+ $listener->setUrl($this->url_task_modification);
foreach ($events as $event_name) {
$this->event->attach($event_name, $listener);
@@ -104,7 +108,10 @@ class Webhook extends Base
*/
public function attachCreateEvents()
{
- $this->event->attach(Task::EVENT_CREATE, new WebhookListener($this->url_task_creation, $this));
+ $listener = new WebhookListener($this->registry);
+ $listener->setUrl($this->url_task_creation);
+
+ $this->event->attach(Task::EVENT_CREATE, $listener);
}
/**
diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php
index 7a0b2cd1..05bef8cd 100644
--- a/app/Schema/Mysql.php
+++ b/app/Schema/Mysql.php
@@ -5,7 +5,30 @@ namespace Schema;
use PDO;
use Core\Security;
-const VERSION = 32;
+const VERSION = 33;
+
+function version_33($pdo)
+{
+ $pdo->exec("
+ CREATE TABLE project_activities (
+ id INT NOT NULL AUTO_INCREMENT,
+ date_creation INT NOT NULL,
+ event_name VARCHAR(50) NOT NULL,
+ creator_id INT,
+ project_id INT,
+ task_id INT,
+ data TEXT,
+ PRIMARY KEY(id),
+ FOREIGN KEY(creator_id) REFERENCES users(id) ON DELETE CASCADE,
+ FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
+ FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE
+ ) ENGINE=InnoDB CHARSET=utf8
+ ");
+
+ $pdo->exec('DROP TABLE task_has_events');
+ $pdo->exec('DROP TABLE comment_has_events');
+ $pdo->exec('DROP TABLE subtask_has_events');
+}
function version_32($pdo)
{
@@ -355,7 +378,7 @@ function version_1($pdo)
id INT NOT NULL AUTO_INCREMENT,
task_id INT,
user_id INT,
- date INT,
+ `date` INT,
comment TEXT,
PRIMARY KEY (id),
FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE,
diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php
index e42e8e72..8aaff259 100644
--- a/app/Schema/Postgres.php
+++ b/app/Schema/Postgres.php
@@ -5,7 +5,29 @@ namespace Schema;
use PDO;
use Core\Security;
-const VERSION = 13;
+const VERSION = 14;
+
+function version_14($pdo)
+{
+ $pdo->exec("
+ CREATE TABLE project_activities (
+ id SERIAL PRIMARY KEY,
+ date_creation INTEGER NOT NULL,
+ event_name VARCHAR(50) NOT NULL,
+ creator_id INTEGER,
+ project_id INTEGER,
+ task_id INTEGER,
+ data TEXT,
+ FOREIGN KEY(creator_id) REFERENCES users(id) ON DELETE CASCADE,
+ FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
+ FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE
+ )
+ ");
+
+ $pdo->exec('DROP TABLE task_has_events');
+ $pdo->exec('DROP TABLE comment_has_events');
+ $pdo->exec('DROP TABLE subtask_has_events');
+}
function version_13($pdo)
{
diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php
index f290c824..3c220f8c 100644
--- a/app/Schema/Sqlite.php
+++ b/app/Schema/Sqlite.php
@@ -5,7 +5,29 @@ namespace Schema;
use Core\Security;
use PDO;
-const VERSION = 32;
+const VERSION = 33;
+
+function version_33($pdo)
+{
+ $pdo->exec("
+ CREATE TABLE project_activities (
+ id INTEGER PRIMARY KEY,
+ date_creation INTEGER NOT NULL,
+ event_name TEXT NOT NULL,
+ creator_id INTEGER,
+ project_id INTEGER,
+ task_id INTEGER,
+ data TEXT,
+ FOREIGN KEY(creator_id) REFERENCES users(id) ON DELETE CASCADE,
+ FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
+ FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE
+ )
+ ");
+
+ $pdo->exec('DROP TABLE task_has_events');
+ $pdo->exec('DROP TABLE comment_has_events');
+ $pdo->exec('DROP TABLE subtask_has_events');
+}
function version_32($pdo)
{
diff --git a/app/Templates/event_comment_create.php b/app/Templates/event_comment_create.php
index 4af59614..d2f6f97b 100644
--- a/app/Templates/event_comment_create.php
+++ b/app/Templates/event_comment_create.php
@@ -1,7 +1,7 @@
<p class="activity-title">
<?= e('%s commented the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>', Helper\escape($author), $task_id, $task_id) ?>
</p>
-<p class="activity-description">
- <em><?= Helper\escape($task_title) ?></em><br/>
- <div class="markdown"><?= Helper\markdown($comment) ?></div>
-</p> \ No newline at end of file
+<div class="activity-description">
+ <em><?= Helper\escape($task['title']) ?></em><br/>
+ <div class="markdown"><?= Helper\markdown($comment['comment']) ?></div>
+</div> \ No newline at end of file
diff --git a/app/Templates/event_comment_update.php b/app/Templates/event_comment_update.php
index fe93b691..27cc0be6 100644
--- a/app/Templates/event_comment_update.php
+++ b/app/Templates/event_comment_update.php
@@ -1,7 +1,7 @@
<p class="activity-title">
<?= e('%s updated a comment on the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>', Helper\escape($author), $task_id, $task_id) ?>
</p>
-<p class="activity-description">
- <em><?= Helper\escape($task_title) ?></em><br/>
- <div class="markdown"><?= Helper\markdown($comment) ?></div>
-</p> \ No newline at end of file
+<div class="activity-description">
+ <em><?= Helper\escape($task['title']) ?></em><br/>
+ <div class="markdown"><?= Helper\markdown($comment['comment']) ?></div>
+</div> \ No newline at end of file
diff --git a/app/Templates/event_subtask_create.php b/app/Templates/event_subtask_create.php
index 9772d807..664e9da2 100644
--- a/app/Templates/event_subtask_create.php
+++ b/app/Templates/event_subtask_create.php
@@ -1,12 +1,19 @@
<p class="activity-title">
<?= e('%s created a subtask for the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>', Helper\escape($author), $task_id, $task_id) ?>
</p>
-<p class="activity-description">
- <em><?= Helper\escape($task_title) ?></em><br/>
- <p><?= Helper\escape($subtask_title) ?> <strong>(<?= Helper\in_list($subtask_status, $subtask_status_list) ?>)</strong></p>
- <?php if ($subtask_assignee): ?>
- <p><?= t('Assigned to %s with an estimate of %s/%sh', $subtask_assignee, $subtask_time_spent, $subtask_time_estimated) ?></p>
- <?php else: ?>
- <p><?= t('Not assigned, estimate of %sh', $subtask_time_estimated) ?></p>
- <?php endif ?>
-</p> \ No newline at end of file
+<div class="activity-description">
+ <p><em><?= Helper\escape($task['title']) ?></em></p>
+
+ <ul>
+ <li>
+ <?= Helper\escape($subtask['title']) ?> (<strong><?= Helper\escape($subtask['status_name']) ?></strong>)
+ </li>
+ <li>
+ <?php if ($subtask['username']): ?>
+ <?= t('Assigned to %s with an estimate of %s/%sh', $subtask['name'] ?: $subtask['username'], $subtask['time_spent'], $subtask['time_estimated']) ?>
+ <?php else: ?>
+ <?= t('Not assigned, estimate of %sh', $subtask['time_estimated']) ?>
+ <?php endif ?>
+ </li>
+ </ul>
+</div> \ No newline at end of file
diff --git a/app/Templates/event_subtask_update.php b/app/Templates/event_subtask_update.php
index 70f9d76d..96a589dd 100644
--- a/app/Templates/event_subtask_update.php
+++ b/app/Templates/event_subtask_update.php
@@ -1,12 +1,19 @@
<p class="activity-title">
<?= e('%s updated a subtask for the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>', Helper\escape($author), $task_id, $task_id) ?>
</p>
-<p class="activity-description">
- <em><?= Helper\escape($task_title) ?></em><br/>
- <p><?= Helper\escape($subtask_title) ?> <strong>(<?= Helper\in_list($subtask_status, $subtask_status_list) ?>)</strong></p>
- <?php if ($subtask_assignee): ?>
- <p><?= t('Assigned to %s with an estimate of %s/%sh', $subtask_assignee, $subtask_time_spent, $subtask_time_estimated) ?></p>
- <?php else: ?>
- <p><?= t('Not assigned, estimate of %sh', $subtask_time_estimated) ?></p>
- <?php endif ?>
-</p> \ No newline at end of file
+<div class="activity-description">
+ <p><em><?= Helper\escape($task['title']) ?></em></p>
+
+ <ul>
+ <li>
+ <?= Helper\escape($subtask['title']) ?> (<strong><?= Helper\escape($subtask['status_name']) ?></strong>)
+ </li>
+ <li>
+ <?php if ($subtask['username']): ?>
+ <?= t('Assigned to %s with an estimate of %s/%sh', $subtask['name'] ?: $subtask['username'], $subtask['time_spent'], $subtask['time_estimated']) ?>
+ <?php else: ?>
+ <?= t('Not assigned, estimate of %sh', $subtask['time_estimated']) ?>
+ <?php endif ?>
+ </li>
+ </ul>
+</div>
diff --git a/app/Templates/event_task_assignee_change.php b/app/Templates/event_task_assignee_change.php
index ac18af2f..b346325e 100644
--- a/app/Templates/event_task_assignee_change.php
+++ b/app/Templates/event_task_assignee_change.php
@@ -1,6 +1,12 @@
<p class="activity-title">
- <?= e('%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>', Helper\escape($author), $task_id, $task_id) ?>
+ <?= e(
+ '%s change the assignee of the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to %s',
+ Helper\escape($author),
+ $task_id,
+ $task_id,
+ Helper\escape($task['assignee_name'] ?: $task['assignee_username'])
+ ) ?>
</p>
<p class="activity-description">
- <em><?= Helper\escape($task_title) ?></em>
+ <em><?= Helper\escape($task['title']) ?></em>
</p> \ No newline at end of file
diff --git a/app/Templates/event_task_close.php b/app/Templates/event_task_close.php
index 9d92ea55..48d25678 100644
--- a/app/Templates/event_task_close.php
+++ b/app/Templates/event_task_close.php
@@ -2,5 +2,5 @@
<?= e('%s closed the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>', Helper\escape($author), $task_id, $task_id) ?>
</p>
<p class="activity-description">
- <em><?= Helper\escape($task_title) ?></em>
+ <em><?= Helper\escape($task['title']) ?></em>
</p> \ No newline at end of file
diff --git a/app/Templates/event_task_create.php b/app/Templates/event_task_create.php
index 7ceab4bb..2515af05 100644
--- a/app/Templates/event_task_create.php
+++ b/app/Templates/event_task_create.php
@@ -2,5 +2,5 @@
<?= e('%s created the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>', Helper\escape($author), $task_id, $task_id) ?>
</p>
<p class="activity-description">
- <em><?= Helper\escape($task_title) ?></em>
+ <em><?= Helper\escape($task['title']) ?></em>
</p> \ No newline at end of file
diff --git a/app/Templates/event_task_move_column.php b/app/Templates/event_task_move_column.php
index a674f80a..f2aac8f7 100644
--- a/app/Templates/event_task_move_column.php
+++ b/app/Templates/event_task_move_column.php
@@ -1,6 +1,6 @@
<p class="activity-title">
- <?= e('%s moved the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to the column "%s"', Helper\escape($author), $task_id, $task_id, Helper\escape($task_column_name)) ?>
+ <?= e('%s moved the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to the column "%s"', Helper\escape($author), $task_id, $task_id, Helper\escape($task['column_title'])) ?>
</p>
<p class="activity-description">
- <em><?= Helper\escape($task_title) ?></em>
+ <em><?= Helper\escape($task['title']) ?></em>
</p> \ No newline at end of file
diff --git a/app/Templates/event_task_move_position.php b/app/Templates/event_task_move_position.php
index 0b7e9615..26cdeb13 100644
--- a/app/Templates/event_task_move_position.php
+++ b/app/Templates/event_task_move_position.php
@@ -1,6 +1,6 @@
<p class="activity-title">
- <?= e('%s moved the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to the position #%d in the column "%s"', Helper\escape($author), $task_id, $task_id, $task_position, Helper\escape($task_column_name)) ?>
+ <?= e('%s moved the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a> to the position #%d in the column "%s"', Helper\escape($author), $task_id, $task_id, $task['position'], Helper\escape($task['column_title'])) ?>
</p>
<p class="activity-description">
- <em><?= Helper\escape($task_title) ?></em>
+ <em><?= Helper\escape($task['title']) ?></em>
</p> \ No newline at end of file
diff --git a/app/Templates/event_task_open.php b/app/Templates/event_task_open.php
index 763b0dfc..9623be74 100644
--- a/app/Templates/event_task_open.php
+++ b/app/Templates/event_task_open.php
@@ -2,5 +2,5 @@
<?= e('%s open the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>', Helper\escape($author), $task_id, $task_id) ?>
</p>
<p class="activity-description">
- <em><?= Helper\escape($task_title) ?></em>
+ <em><?= Helper\escape($task['title']) ?></em>
</p> \ No newline at end of file
diff --git a/app/Templates/event_task_update.php b/app/Templates/event_task_update.php
index 313e79cb..a270b936 100644
--- a/app/Templates/event_task_update.php
+++ b/app/Templates/event_task_update.php
@@ -2,5 +2,5 @@
<?= e('%s updated the task <a href="?controller=task&amp;action=show&amp;task_id=%d">#%d</a>', Helper\escape($author), $task_id, $task_id) ?>
</p>
<p class="activity-description">
- <em><?= Helper\escape($task_title) ?></em>
+ <em><?= Helper\escape($task['title']) ?></em>
</p> \ No newline at end of file
diff --git a/app/Templates/project_activity.php b/app/Templates/project_activity.php
index ad91f8b8..50743d68 100644
--- a/app/Templates/project_activity.php
+++ b/app/Templates/project_activity.php
@@ -2,10 +2,10 @@
<div class="page-header">
<h2><?= t('%s\'s activity', $project['name']) ?></h2>
<ul>
- <li><a href="?controller=board&amp;action=show&amp;project_id=<?= $project['id'] ?>"><?= t('Back to the board') ?></a></li>
- <li><a href="?controller=project&amp;action=search&amp;project_id=<?= $project['id'] ?>"><?= t('Search') ?></a></li>
- <li><a href="?controller=project&amp;action=tasks&amp;project_id=<?= $project['id'] ?>"><?= t('Completed tasks') ?></a></li>
- <li><a href="?controller=project&amp;action=index"><?= t('List of projects') ?></a></li>
+ <li><?= Helper\a(t('Back to the board'), 'board', 'show', array('project_id' => $project['id'])) ?></li>
+ <li><?= Helper\a(t('Search'), 'project', 'search', array('project_id' => $project['id'])) ?></li>
+ <li><?= Helper\a(t('Completed tasks'), 'project', 'tasks', array('project_id' => $project['id'])) ?></li>
+ <li><?= Helper\a(t('List of projects'), 'project', 'index') ?></li>
</ul>
</div>
<section>
@@ -14,17 +14,17 @@
<?php else: ?>
<?php if ($project['is_public']): ?>
- <p class="pull-right"><i class="fa fa-rss-square"></i> <a href="?controller=project&amp;action=feed&amp;token=<?= $project['token'] ?>" target="_blank"><?= t('RSS feed') ?></a></p>
+ <p class="pull-right"><i class="fa fa-rss-square"></i> <?= Helper\a(t('RSS feed'), 'project', 'feed', array('token' => $project['token'])) ?></p>
<?php endif ?>
<?php foreach ($events as $event): ?>
<div class="activity-event">
<p class="activity-datetime">
- <?php if ($event['event_type'] === 'task'): ?>
+ <?php if (Helper\contains($event['event_name'], 'task')): ?>
<i class="fa fa-newspaper-o"></i>
- <?php elseif ($event['event_type'] === 'subtask'): ?>
+ <?php elseif (Helper\contains($event['event_name'], 'subtask')): ?>
<i class="fa fa-tasks"></i>
- <?php elseif ($event['event_type'] === 'comment'): ?>
+ <?php elseif (Helper\contains($event['event_name'], 'comment')): ?>
<i class="fa fa-comments-o"></i>
<?php endif ?>
&nbsp;<?= dt('%B %e, %Y at %k:%M %p', $event['date_creation']) ?>
diff --git a/app/Templates/project_feed.php b/app/Templates/project_feed.php
index b47c87ad..9d10ecb1 100644
--- a/app/Templates/project_feed.php
+++ b/app/Templates/project_feed.php
@@ -2,7 +2,7 @@
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
<title><?= t('%s\'s activity', $project['name']) ?></title>
<link rel="alternate" type="text/html" href="<?= Helper\get_current_base_url() ?>"/>
- <link rel="self" type="application/atom+xml" href="<?= Helper\get_current_base_url() ?>?controller=project&amp;action=feed&amp;token=<?= $project['token'] ?>"/>
+ <link rel="self" type="application/atom+xml" href="<?= Helper\get_current_base_url().Helper\u('project', 'feed', array('token' => $project['token'])) ?>"/>
<updated><?= date(DATE_ATOM) ?></updated>
<id><?= Helper\get_current_base_url() ?></id>
<icon><?= Helper\get_current_base_url() ?>assets/img/favicon.png</icon>
@@ -10,7 +10,7 @@
<?php foreach ($events as $e): ?>
<entry>
<title type="text"><?= $e['event_title'] ?></title>
- <link rel="alternate" href="<?= Helper\get_current_base_url().'?controller=task&amp;action=show&amp;task_id='.$e['task_id'] ?>"/>
+ <link rel="alternate" href="<?= Helper\get_current_base_url().Helper\u('task', 'show', array('task_id' => $e['task_id'])) ?>"/>
<id><?= $e['id'].'-'.$e['event_name'].'-'.$e['task_id'].'-'.$e['date_creation'] ?></id>
<published><?= date(DATE_ATOM, $e['date_creation']) ?></published>
<updated><?= date(DATE_ATOM, $e['date_creation']) ?></updated>
diff --git a/app/Templates/task_public.php b/app/Templates/task_public.php
index bc4608d1..3f44ceec 100644
--- a/app/Templates/task_public.php
+++ b/app/Templates/task_public.php
@@ -2,7 +2,7 @@
<?= Helper\template('task_details', array('task' => $task, 'project' => $project)) ?>
- <p class="align-right"><?= Helper\a(t('Back to the board'), 'board', 'readonly', array('token' => $project['token'])) ?></p>
+ <p class="pull-right"><?= Helper\a(t('Back to the board'), 'board', 'readonly', array('token' => $project['token'])) ?></p>
<?= Helper\template('task_show_description', array('task' => $task)) ?>
diff --git a/assets/css/app.css b/assets/css/app.css
index 185c98ec..0bb25740 100644
--- a/assets/css/app.css
+++ b/assets/css/app.css
@@ -26,10 +26,6 @@ body {
text-rendering: optimizeLegibility;
}
-.align-right {
- text-align: right;
-}
-
/* links */
a {
color: #3366CC;
@@ -1108,6 +1104,21 @@ tr td.task-orange,
padding-top: 5px;
}
+.activity-description ul {
+ margin-top: 10px;
+}
+
+.activity-description li {
+ margin-left: 40px;
+ list-style-type: circle;
+ color: #555;
+}
+
+.activity-description .markdown {
+ margin-top: 10px;
+ color: #555;
+}
+
/* confirmation box */
.confirm {
max-width: 700px;
diff --git a/tests/units/TaskHistoryTest.php b/tests/units/ProjectActivityTest.php
index 085162ea..2565b6e7 100644
--- a/tests/units/TaskHistoryTest.php
+++ b/tests/units/ProjectActivityTest.php
@@ -3,26 +3,28 @@
require_once __DIR__.'/Base.php';
use Model\Task;
-use Model\TaskHistory;
+use Model\TaskFinder;
+use Model\ProjectActivity;
use Model\Project;
-class TaskHistoryTest extends Base
+class ProjectActivityTest extends Base
{
public function testCreation()
{
- $e = new TaskHistory($this->registry);
+ $e = new ProjectActivity($this->registry);
$t = new Task($this->registry);
+ $tf = new TaskFinder($this->registry);
$p = new Project($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'Project #1')));
$this->assertEquals(1, $t->create(array('title' => 'Task #1', 'project_id' => 1)));
$this->assertEquals(2, $t->create(array('title' => 'Task #2', 'project_id' => 1)));
- $this->assertTrue($e->create(1, 1, 1, Task::EVENT_CLOSE));
- $this->assertTrue($e->create(1, 2, 1, Task::EVENT_UPDATE));
- $this->assertFalse($e->create(1, 1, 0, Task::EVENT_OPEN));
+ $this->assertTrue($e->createEvent(1, 1, 1, Task::EVENT_CLOSE, array('task' => $tf->getbyId(1))));
+ $this->assertTrue($e->createEvent(1, 2, 1, Task::EVENT_UPDATE, array('task' => $tf->getById(2))));
+ $this->assertFalse($e->createEvent(1, 1, 0, Task::EVENT_OPEN, array('task' => $tf->getbyId(1))));
- $events = $e->getAllByProjectId(1);
+ $events = $e->getAll(1);
$this->assertNotEmpty($events);
$this->assertTrue(is_array($events));
@@ -34,8 +36,9 @@ class TaskHistoryTest extends Base
public function testFetchAllContent()
{
- $e = new TaskHistory($this->registry);
+ $e = new ProjectActivity($this->registry);
$t = new Task($this->registry);
+ $tf = new TaskFinder($this->registry);
$p = new Project($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'Project #1')));
@@ -44,10 +47,10 @@ class TaskHistoryTest extends Base
$nb_events = 80;
for ($i = 0; $i < $nb_events; $i++) {
- $this->assertTrue($e->create(1, 1, 1, Task::EVENT_UPDATE));
+ $this->assertTrue($e->createEvent(1, 1, 1, Task::EVENT_UPDATE, array('task' => $tf->getbyId(1))));
}
- $events = $e->getAllContentByProjectId(1);
+ $events = $e->getAll(1);
$this->assertNotEmpty($events);
$this->assertTrue(is_array($events));
@@ -59,8 +62,9 @@ class TaskHistoryTest extends Base
public function testCleanup()
{
- $e = new TaskHistory($this->registry);
+ $e = new ProjectActivity($this->registry);
$t = new Task($this->registry);
+ $tf = new TaskFinder($this->registry);
$p = new Project($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'Project #1')));
@@ -70,13 +74,13 @@ class TaskHistoryTest extends Base
$nb_events = 100;
for ($i = 0; $i < $nb_events; $i++) {
- $this->assertTrue($e->create(1, 1, 1, Task::EVENT_CLOSE));
+ $this->assertTrue($e->createEvent(1, 1, 1, Task::EVENT_CLOSE, array('task' => $tf->getbyId(1))));
}
- $this->assertEquals($nb_events, $this->registry->shared('db')->table('task_has_events')->count());
+ $this->assertEquals($nb_events, $this->registry->shared('db')->table('project_activities')->count());
$e->cleanup($max);
- $events = $e->getAllByProjectId(1);
+ $events = $e->getAll(1);
$this->assertNotEmpty($events);
$this->assertTrue(is_array($events));
@@ -87,12 +91,12 @@ class TaskHistoryTest extends Base
// Cleanup during task creation
- $nb_events = TaskHistory::MAX_EVENTS + 10;
+ $nb_events = ProjectActivity::MAX_EVENTS + 10;
for ($i = 0; $i < $nb_events; $i++) {
- $this->assertTrue($e->create(1, 1, 1, Task::EVENT_CLOSE));
+ $this->assertTrue($e->createEvent(1, 1, 1, Task::EVENT_CLOSE, array('task' => $tf->getbyId(1))));
}
- $this->assertEquals(TaskHistory::MAX_EVENTS, $this->registry->shared('db')->table('task_has_events')->count());
+ $this->assertEquals(ProjectActivity::MAX_EVENTS, $this->registry->shared('db')->table('project_activities')->count());
}
}
diff --git a/tests/units/ProjectTest.php b/tests/units/ProjectTest.php
index 0085711a..cec8d93d 100644
--- a/tests/units/ProjectTest.php
+++ b/tests/units/ProjectTest.php
@@ -63,7 +63,7 @@ class ProjectTest extends Base
$this->assertEquals(1, $t->create(array('title' => 'Task #1', 'project_id' => 1)));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_CREATE));
- $this->assertEquals('Event\ProjectModificationDate', $this->registry->shared('event')->getLastListenerExecuted());
+ $this->assertEquals('Event\ProjectModificationDateListener', $this->registry->shared('event')->getLastListenerExecuted());
$project = $p->getById(1);
$this->assertNotEmpty($project);