summaryrefslogtreecommitdiff
path: root/app/Model
diff options
context:
space:
mode:
Diffstat (limited to 'app/Model')
-rw-r--r--app/Model/Action.php2
-rw-r--r--app/Model/Comment.php9
-rw-r--r--app/Model/Notification.php54
-rw-r--r--app/Model/ProjectGroupRoleFilter.php89
-rw-r--r--app/Model/ProjectPermission.php34
-rw-r--r--app/Model/ProjectUserRoleFilter.php88
-rw-r--r--app/Model/Task.php1
-rw-r--r--app/Model/TaskCreation.php11
-rw-r--r--app/Model/TaskPosition.php180
-rw-r--r--app/Model/UserMention.php61
-rw-r--r--app/Model/UserNotification.php19
11 files changed, 382 insertions, 166 deletions
diff --git a/app/Model/Action.php b/app/Model/Action.php
index 289471f4..d3d18edb 100644
--- a/app/Model/Action.php
+++ b/app/Model/Action.php
@@ -427,7 +427,7 @@ class Action extends Base
return $this->board->getColumnIdByTitle($project_id, $column['title']) ?: false;
case 'user_id':
case 'owner_id':
- return $this->projectPermission->isMember($project_id, $param['value']) ? $param['value'] : false;
+ return $this->projectPermission->isAssignable($project_id, $param['value']) ? $param['value'] : false;
default:
return $param['value'];
}
diff --git a/app/Model/Comment.php b/app/Model/Comment.php
index f60a96e3..71e964dc 100644
--- a/app/Model/Comment.php
+++ b/app/Model/Comment.php
@@ -26,8 +26,9 @@ class Comment extends Base
*
* @var string
*/
- const EVENT_UPDATE = 'comment.update';
- const EVENT_CREATE = 'comment.create';
+ const EVENT_UPDATE = 'comment.update';
+ const EVENT_CREATE = 'comment.create';
+ const EVENT_USER_MENTION = 'comment.user.mention';
/**
* Get all comments for a given task
@@ -110,7 +111,9 @@ class Comment extends Base
$comment_id = $this->persist(self::TABLE, $values);
if ($comment_id) {
- $this->container['dispatcher']->dispatch(self::EVENT_CREATE, new CommentEvent(array('id' => $comment_id) + $values));
+ $event = new CommentEvent(array('id' => $comment_id) + $values);
+ $this->dispatcher->dispatch(self::EVENT_CREATE, $event);
+ $this->userMention->fireEvents($values['comment'], self::EVENT_USER_MENTION, $event);
}
return $comment_id;
diff --git a/app/Model/Notification.php b/app/Model/Notification.php
index f1122993..87c1a796 100644
--- a/app/Model/Notification.php
+++ b/app/Model/Notification.php
@@ -74,6 +74,10 @@ class Notification extends Base
return e('%s commented on the task #%d', $event_author, $event_data['task']['id']);
case File::EVENT_CREATE:
return e('%s attached a file to the task #%d', $event_author, $event_data['task']['id']);
+ case Task::EVENT_USER_MENTION:
+ return e('%s mentioned you in the task #%d', $event_author, $event_data['task']['id']);
+ case Comment::EVENT_USER_MENTION:
+ return e('%s mentioned you in a comment on the task #%d', $event_author, $event_data['task']['id']);
default:
return e('Notification');
}
@@ -91,52 +95,40 @@ class Notification extends Base
{
switch ($event_name) {
case File::EVENT_CREATE:
- $title = e('New attachment on task #%d: %s', $event_data['file']['task_id'], $event_data['file']['name']);
- break;
+ return e('New attachment on task #%d: %s', $event_data['file']['task_id'], $event_data['file']['name']);
case Comment::EVENT_CREATE:
- $title = e('New comment on task #%d', $event_data['comment']['task_id']);
- break;
+ return e('New comment on task #%d', $event_data['comment']['task_id']);
case Comment::EVENT_UPDATE:
- $title = e('Comment updated on task #%d', $event_data['comment']['task_id']);
- break;
+ return e('Comment updated on task #%d', $event_data['comment']['task_id']);
case Subtask::EVENT_CREATE:
- $title = e('New subtask on task #%d', $event_data['subtask']['task_id']);
- break;
+ return e('New subtask on task #%d', $event_data['subtask']['task_id']);
case Subtask::EVENT_UPDATE:
- $title = e('Subtask updated on task #%d', $event_data['subtask']['task_id']);
- break;
+ return e('Subtask updated on task #%d', $event_data['subtask']['task_id']);
case Task::EVENT_CREATE:
- $title = e('New task #%d: %s', $event_data['task']['id'], $event_data['task']['title']);
- break;
+ return e('New task #%d: %s', $event_data['task']['id'], $event_data['task']['title']);
case Task::EVENT_UPDATE:
- $title = e('Task updated #%d', $event_data['task']['id']);
- break;
+ return e('Task updated #%d', $event_data['task']['id']);
case Task::EVENT_CLOSE:
- $title = e('Task #%d closed', $event_data['task']['id']);
- break;
+ return e('Task #%d closed', $event_data['task']['id']);
case Task::EVENT_OPEN:
- $title = e('Task #%d opened', $event_data['task']['id']);
- break;
+ return e('Task #%d opened', $event_data['task']['id']);
case Task::EVENT_MOVE_COLUMN:
- $title = e('Column changed for task #%d', $event_data['task']['id']);
- break;
+ return e('Column changed for task #%d', $event_data['task']['id']);
case Task::EVENT_MOVE_POSITION:
- $title = e('New position for task #%d', $event_data['task']['id']);
- break;
+ return e('New position for task #%d', $event_data['task']['id']);
case Task::EVENT_MOVE_SWIMLANE:
- $title = e('Swimlane changed for task #%d', $event_data['task']['id']);
- break;
+ return e('Swimlane changed for task #%d', $event_data['task']['id']);
case Task::EVENT_ASSIGNEE_CHANGE:
- $title = e('Assignee changed on task #%d', $event_data['task']['id']);
- break;
+ return e('Assignee changed on task #%d', $event_data['task']['id']);
case Task::EVENT_OVERDUE:
$nb = count($event_data['tasks']);
- $title = $nb > 1 ? e('%d overdue tasks', $nb) : e('Task #%d is overdue', $event_data['tasks'][0]['id']);
- break;
+ return $nb > 1 ? e('%d overdue tasks', $nb) : e('Task #%d is overdue', $event_data['tasks'][0]['id']);
+ case Task::EVENT_USER_MENTION:
+ return e('You were mentioned in the task #%d', $event_data['task']['id']);
+ case Comment::EVENT_USER_MENTION:
+ return e('You were mentioned in a comment on the task #%d', $event_data['task']['id']);
default:
- $title = e('Notification');
+ return e('Notification');
}
-
- return $title;
}
}
diff --git a/app/Model/ProjectGroupRoleFilter.php b/app/Model/ProjectGroupRoleFilter.php
new file mode 100644
index 00000000..989d3073
--- /dev/null
+++ b/app/Model/ProjectGroupRoleFilter.php
@@ -0,0 +1,89 @@
+<?php
+
+namespace Kanboard\Model;
+
+/**
+ * Project Group Role Filter
+ *
+ * @package model
+ * @author Frederic Guillot
+ */
+class ProjectGroupRoleFilter extends Base
+{
+ /**
+ * Query
+ *
+ * @access protected
+ * @var \PicoDb\Table
+ */
+ protected $query;
+
+ /**
+ * Initialize filter
+ *
+ * @access public
+ * @return UserFilter
+ */
+ public function create()
+ {
+ $this->query = $this->db->table(ProjectGroupRole::TABLE);
+ return $this;
+ }
+
+ /**
+ * Get all results of the filter
+ *
+ * @access public
+ * @param string $column
+ * @return array
+ */
+ public function findAll($column = '')
+ {
+ if ($column !== '') {
+ return $this->query->asc($column)->findAllByColumn($column);
+ }
+
+ return $this->query->findAll();
+ }
+
+ /**
+ * Get the PicoDb query
+ *
+ * @access public
+ * @return \PicoDb\Table
+ */
+ public function getQuery()
+ {
+ return $this->query;
+ }
+
+ /**
+ * Filter by project id
+ *
+ * @access public
+ * @param integer $project_id
+ * @return ProjectUserRoleFilter
+ */
+ public function filterByProjectId($project_id)
+ {
+ $this->query->eq(ProjectGroupRole::TABLE.'.project_id', $project_id);
+ return $this;
+ }
+
+ /**
+ * Filter by username
+ *
+ * @access public
+ * @param string $input
+ * @return ProjectUserRoleFilter
+ */
+ public function startWithUsername($input)
+ {
+ $this->query
+ ->join(GroupMember::TABLE, 'group_id', 'group_id', ProjectGroupRole::TABLE)
+ ->join(User::TABLE, 'id', 'user_id', GroupMember::TABLE)
+ ->ilike(User::TABLE.'.username', $input.'%');
+
+ return $this;
+ }
+}
diff --git a/app/Model/ProjectPermission.php b/app/Model/ProjectPermission.php
index 4ad9bbf1..cea62e13 100644
--- a/app/Model/ProjectPermission.php
+++ b/app/Model/ProjectPermission.php
@@ -44,6 +44,25 @@ class ProjectPermission extends Base
}
/**
+ * Get all usernames (fetch users from groups)
+ *
+ * @access public
+ * @param integer $project_id
+ * @param string $input
+ * @return array
+ */
+ public function findUsernames($project_id, $input)
+ {
+ $userMembers = $this->projectUserRoleFilter->create()->filterByProjectId($project_id)->startWithUsername($input)->findAll('username');
+ $groupMembers = $this->projectGroupRoleFilter->create()->filterByProjectId($project_id)->startWithUsername($input)->findAll('username');
+ $members = array_unique(array_merge($userMembers, $groupMembers));
+
+ sort($members);
+
+ return $members;
+ }
+
+ /**
* Return true if everybody is allowed for the project
*
* @access public
@@ -86,12 +105,25 @@ class ProjectPermission extends Base
* @param integer $user_id
* @return boolean
*/
- public function isMember($project_id, $user_id)
+ public function isAssignable($project_id, $user_id)
{
return in_array($this->projectUserRole->getUserRole($project_id, $user_id), array(Role::PROJECT_MEMBER, Role::PROJECT_MANAGER));
}
/**
+ * Return true if the user is member
+ *
+ * @access public
+ * @param integer $project_id
+ * @param integer $user_id
+ * @return boolean
+ */
+ public function isMember($project_id, $user_id)
+ {
+ return in_array($this->projectUserRole->getUserRole($project_id, $user_id), array(Role::PROJECT_MEMBER, Role::PROJECT_MANAGER, Role::PROJECT_VIEWER));
+ }
+
+ /**
* Get active project ids by user
*
* @access public
diff --git a/app/Model/ProjectUserRoleFilter.php b/app/Model/ProjectUserRoleFilter.php
new file mode 100644
index 00000000..64403643
--- /dev/null
+++ b/app/Model/ProjectUserRoleFilter.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace Kanboard\Model;
+
+/**
+ * Project User Role Filter
+ *
+ * @package model
+ * @author Frederic Guillot
+ */
+class ProjectUserRoleFilter extends Base
+{
+ /**
+ * Query
+ *
+ * @access protected
+ * @var \PicoDb\Table
+ */
+ protected $query;
+
+ /**
+ * Initialize filter
+ *
+ * @access public
+ * @return UserFilter
+ */
+ public function create()
+ {
+ $this->query = $this->db->table(ProjectUserRole::TABLE);
+ return $this;
+ }
+
+ /**
+ * Get all results of the filter
+ *
+ * @access public
+ * @param string $column
+ * @return array
+ */
+ public function findAll($column = '')
+ {
+ if ($column !== '') {
+ return $this->query->asc($column)->findAllByColumn($column);
+ }
+
+ return $this->query->findAll();
+ }
+
+ /**
+ * Get the PicoDb query
+ *
+ * @access public
+ * @return \PicoDb\Table
+ */
+ public function getQuery()
+ {
+ return $this->query;
+ }
+
+ /**
+ * Filter by project id
+ *
+ * @access public
+ * @param integer $project_id
+ * @return ProjectUserRoleFilter
+ */
+ public function filterByProjectId($project_id)
+ {
+ $this->query->eq(ProjectUserRole::TABLE.'.project_id', $project_id);
+ return $this;
+ }
+
+ /**
+ * Filter by username
+ *
+ * @access public
+ * @param string $input
+ * @return ProjectUserRoleFilter
+ */
+ public function startWithUsername($input)
+ {
+ $this->query
+ ->join(User::TABLE, 'id', 'user_id')
+ ->ilike(User::TABLE.'.username', $input.'%');
+
+ return $this;
+ }
+}
diff --git a/app/Model/Task.php b/app/Model/Task.php
index f1cd094f..7aa9e312 100644
--- a/app/Model/Task.php
+++ b/app/Model/Task.php
@@ -41,6 +41,7 @@ class Task extends Base
const EVENT_CREATE_UPDATE = 'task.create_update';
const EVENT_ASSIGNEE_CHANGE = 'task.assignee_change';
const EVENT_OVERDUE = 'task.overdue';
+ const EVENT_USER_MENTION = 'task.user.mention';
/**
* Recurrence: status
diff --git a/app/Model/TaskCreation.php b/app/Model/TaskCreation.php
index 5ef1a04b..88912d4d 100644
--- a/app/Model/TaskCreation.php
+++ b/app/Model/TaskCreation.php
@@ -86,8 +86,13 @@ class TaskCreation extends Base
*/
private function fireEvents($task_id, array $values)
{
- $values['task_id'] = $task_id;
- $this->container['dispatcher']->dispatch(Task::EVENT_CREATE_UPDATE, new TaskEvent($values));
- $this->container['dispatcher']->dispatch(Task::EVENT_CREATE, new TaskEvent($values));
+ $event = new TaskEvent(array('task_id' => $task_id) + $values);
+
+ $this->dispatcher->dispatch(Task::EVENT_CREATE_UPDATE, $event);
+ $this->dispatcher->dispatch(Task::EVENT_CREATE, $event);
+
+ if (! empty($values['description'])) {
+ $this->userMention->fireEvents($values['description'], Task::EVENT_USER_MENTION, $event);
+ }
}
}
diff --git a/app/Model/TaskPosition.php b/app/Model/TaskPosition.php
index da363cb3..53193c9b 100644
--- a/app/Model/TaskPosition.php
+++ b/app/Model/TaskPosition.php
@@ -26,28 +26,34 @@ class TaskPosition extends Base
*/
public function movePosition($project_id, $task_id, $column_id, $position, $swimlane_id = 0, $fire_events = true)
{
+ $result = false;
+
if ($position < 1) {
- return false;
+ return $result;
}
$task = $this->taskFinder->getById($task_id);
- // Ignore closed tasks
if ($task['is_active'] == Task::STATUS_CLOSED) {
return true;
}
- $result = false;
+ $this->db->startTransaction();
- if ($task['swimlane_id'] != $swimlane_id) {
- $result = $this->saveSwimlaneChange($project_id, $task_id, $position, $task['column_id'], $column_id, $task['swimlane_id'], $swimlane_id);
- } elseif ($task['column_id'] != $column_id) {
- $result = $this->saveColumnChange($project_id, $task_id, $position, $swimlane_id, $task['column_id'], $column_id);
+ if ($task['swimlane_id'] != $swimlane_id || $task['column_id'] != $column_id) {
+ $result = $this->moveTaskToAnotherColumn($task, $swimlane_id, $column_id, $position);
} elseif ($task['position'] != $position) {
- $result = $this->savePositionChange($project_id, $task_id, $position, $column_id, $swimlane_id);
+ $result = $this->moveTaskWithinSameColumn($task, $position);
}
- if ($result && $fire_events) {
+ if (! $result) {
+ $this->db->cancelTransaction();
+ return false;
+ }
+
+ $this->db->closeTransaction();
+
+ if ($fire_events) {
$this->fireEvents($task, $column_id, $position, $swimlane_id);
}
@@ -55,145 +61,87 @@ class TaskPosition extends Base
}
/**
- * Move a task to another swimlane
+ * Move a task to another column/swimlane
*
* @access private
- * @param integer $project_id
- * @param integer $task_id
- * @param integer $position
- * @param integer $original_column_id
- * @param integer $new_column_id
- * @param integer $original_swimlane_id
- * @param integer $new_swimlane_id
+ * @param array $task
+ * @param integer $swimlane_id
+ * @param integer $column_id
+ * @param integer $position
* @return boolean
*/
- private function saveSwimlaneChange($project_id, $task_id, $position, $original_column_id, $new_column_id, $original_swimlane_id, $new_swimlane_id)
+ private function moveTaskToAnotherColumn(array $task, $swimlane_id, $column_id, $position)
{
- $this->db->startTransaction();
- $r1 = $this->saveTaskPositions($project_id, $task_id, 0, $original_column_id, $original_swimlane_id);
- $r2 = $this->saveTaskPositions($project_id, $task_id, $position, $new_column_id, $new_swimlane_id);
- $this->db->closeTransaction();
+ $results = array();
+ $max = $this->getQuery($task['project_id'], $swimlane_id, $column_id)->count();
+ $position = $max > 0 && $position > $max ? $max + 1 : $position;
- return $r1 && $r2;
- }
+ $results[] = $this->getQuery($task['project_id'], $task['swimlane_id'], $task['column_id'])->gt('position', $task['position'])->decrement('position', 1);
+ $results[] = $this->getQuery($task['project_id'], $swimlane_id, $column_id)->gte('position', $position)->increment('position', 1);
+ $results[] = $this->updateTaskPosition($task['id'], $swimlane_id, $column_id, $position);
- /**
- * Move a task to another column
- *
- * @access private
- * @param integer $project_id
- * @param integer $task_id
- * @param integer $position
- * @param integer $swimlane_id
- * @param integer $original_column_id
- * @param integer $new_column_id
- * @return boolean
- */
- private function saveColumnChange($project_id, $task_id, $position, $swimlane_id, $original_column_id, $new_column_id)
- {
- $this->db->startTransaction();
- $r1 = $this->saveTaskPositions($project_id, $task_id, 0, $original_column_id, $swimlane_id);
- $r2 = $this->saveTaskPositions($project_id, $task_id, $position, $new_column_id, $swimlane_id);
- $this->db->closeTransaction();
-
- return $r1 && $r2;
+ return !in_array(false, $results, true);
}
/**
- * Move a task to another position in the same column
+ * Move a task within the same column
*
* @access private
- * @param integer $project_id
- * @param integer $task_id
- * @param integer $position
- * @param integer $column_id
- * @param integer $swimlane_id
+ * @param array $task
+ * @param integer $position
* @return boolean
*/
- private function savePositionChange($project_id, $task_id, $position, $column_id, $swimlane_id)
+ private function moveTaskWithinSameColumn(array $task, $position)
{
- $this->db->startTransaction();
- $result = $this->saveTaskPositions($project_id, $task_id, $position, $column_id, $swimlane_id);
- $this->db->closeTransaction();
+ $results = array();
+ $max = $this->getQuery($task['project_id'], $task['swimlane_id'], $task['column_id'])->count();
+ $position = $max > 0 && $position > $max ? $max : $position;
+
+ if ($position >= $max) {
+ $results[] = $this->getQuery($task['project_id'], $task['swimlane_id'], $task['column_id'])->lte('position', $position)->decrement('position', 1);
+ } else {
+ $results[] = $this->getQuery($task['project_id'], $task['swimlane_id'], $task['column_id'])->gte('position', $position)->increment('position', 1);
+ }
- return $result;
+ $results[] = $this->updateTaskPosition($task['id'], $task['swimlane_id'], $task['column_id'], $position);
+
+ return !in_array(false, $results, true);
}
/**
- * Save all task positions for one column
+ * Update final task position
*
* @access private
- * @param integer $project_id
- * @param integer $task_id
- * @param integer $position
- * @param integer $column_id
- * @param integer $swimlane_id
+ * @param integer $task_id
+ * @param integer $swimlane_id
+ * @param integer $column_id
+ * @param integer $position
* @return boolean
*/
- private function saveTaskPositions($project_id, $task_id, $position, $column_id, $swimlane_id)
+ private function updateTaskPosition($task_id, $swimlane_id, $column_id, $position)
{
- $tasks_ids = $this->db->table(Task::TABLE)
+ return $this->db->table(Task::TABLE)
+ ->eq('id', $task_id)
->eq('is_active', 1)
- ->eq('swimlane_id', $swimlane_id)
- ->eq('project_id', $project_id)
- ->eq('column_id', $column_id)
- ->neq('id', $task_id)
- ->asc('position')
- ->asc('id')
- ->findAllByColumn('id');
-
- $offset = 1;
-
- foreach ($tasks_ids as $current_task_id) {
-
- // Insert the new task
- if ($position == $offset) {
- if (! $this->saveTaskPosition($task_id, $offset, $column_id, $swimlane_id)) {
- return false;
- }
- $offset++;
- }
-
- // Rewrite other tasks position
- if (! $this->saveTaskPosition($current_task_id, $offset, $column_id, $swimlane_id)) {
- return false;
- }
-
- $offset++;
- }
-
- // Insert the new task at the bottom and normalize bad position
- if ($position >= $offset && ! $this->saveTaskPosition($task_id, $offset, $column_id, $swimlane_id)) {
- return false;
- }
-
- return true;
+ ->update(array('position' => $position, 'column_id' => $column_id, 'swimlane_id' => $swimlane_id, 'date_modification' => time()));
}
/**
- * Save new task position
+ * Get common query
*
* @access private
- * @param integer $task_id
- * @param integer $position
- * @param integer $column_id
- * @param integer $swimlane_id
- * @return boolean
+ * @param integer $project_id
+ * @param integer $swimlane_id
+ * @param integer $column_id
+ * @return \PicoDb\Table
*/
- private function saveTaskPosition($task_id, $position, $column_id, $swimlane_id)
+ private function getQuery($project_id, $swimlane_id, $column_id)
{
- $result = $this->db->table(Task::TABLE)->eq('id', $task_id)->update(array(
- 'position' => $position,
- 'column_id' => $column_id,
- 'swimlane_id' => $swimlane_id,
- ));
-
- if (! $result) {
- $this->db->cancelTransaction();
- return false;
- }
-
- return true;
+ return $this->db->table(Task::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('swimlane_id', $swimlane_id)
+ ->eq('column_id', $column_id)
+ ->eq('is_active', 1);
}
/**
diff --git a/app/Model/UserMention.php b/app/Model/UserMention.php
new file mode 100644
index 00000000..97a4e419
--- /dev/null
+++ b/app/Model/UserMention.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace Kanboard\Model;
+
+use Kanboard\Event\GenericEvent;
+
+/**
+ * User Mention
+ *
+ * @package model
+ * @author Frederic Guillot
+ */
+class UserMention extends Base
+{
+ /**
+ * Get list of mentioned users
+ *
+ * @access public
+ * @param string $content
+ * @return array
+ */
+ public function getMentionedUsers($content)
+ {
+ $users = array();
+
+ if (preg_match_all('/@([^\s]+)/', $content, $matches)) {
+ $users = $this->db->table(User::TABLE)
+ ->columns('id', 'username', 'name', 'email', 'language')
+ ->eq('notifications_enabled', 1)
+ ->neq('id', $this->userSession->getId())
+ ->in('username', array_unique($matches[1]))
+ ->findAll();
+ }
+
+ return $users;
+ }
+
+ /**
+ * Fire events for user mentions
+ *
+ * @access public
+ * @param string $content
+ * @param string $eventName
+ * @param GenericEvent $event
+ */
+ public function fireEvents($content, $eventName, GenericEvent $event)
+ {
+ if (empty($event['project_id'])) {
+ $event['project_id'] = $this->taskFinder->getProjectId($event['task_id']);
+ }
+
+ $users = $this->getMentionedUsers($content);
+
+ foreach ($users as $user) {
+ if ($this->projectPermission->isMember($event['project_id'], $user['id'])) {
+ $event['mention'] = $user;
+ $this->dispatcher->dispatch($eventName, $event);
+ }
+ }
+ }
+}
diff --git a/app/Model/UserNotification.php b/app/Model/UserNotification.php
index e00f23c5..8161288c 100644
--- a/app/Model/UserNotification.php
+++ b/app/Model/UserNotification.php
@@ -21,18 +21,12 @@ class UserNotification extends Base
*/
public function sendNotifications($event_name, array $event_data)
{
- $logged_user_id = $this->userSession->isLogged() ? $this->userSession->getId() : 0;
- $users = $this->getUsersWithNotificationEnabled($event_data['task']['project_id'], $logged_user_id);
-
- if (! empty($users)) {
- foreach ($users as $user) {
- if ($this->userNotificationFilter->shouldReceiveNotification($user, $event_data)) {
- $this->sendUserNotification($user, $event_name, $event_data);
- }
- }
+ $users = $this->getUsersWithNotificationEnabled($event_data['task']['project_id'], $this->userSession->getId());
- // Restore locales
- $this->config->setupTranslations();
+ foreach ($users as $user) {
+ if ($this->userNotificationFilter->shouldReceiveNotification($user, $event_data)) {
+ $this->sendUserNotification($user, $event_name, $event_data);
+ }
}
}
@@ -58,6 +52,9 @@ class UserNotification extends Base
foreach ($this->userNotificationType->getSelectedTypes($user['id']) as $type) {
$this->userNotificationType->getType($type)->notifyUser($user, $event_name, $event_data);
}
+
+ // Restore locales
+ $this->config->setupTranslations();
}
/**