From 73a5b9bc75d40a30e7c9674b292957657ac01f63 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 17 Oct 2015 09:51:15 -0400 Subject: Make user notifications pluggable --- app/Controller/App.php | 2 +- app/Controller/User.php | 10 +- app/Controller/WebNotification.php | 50 ++++++ app/Controller/Webnotification.php | 39 ----- app/Core/Base.php | 8 +- app/Core/NotificationInterface.php | 22 --- app/Helper/User.php | 2 +- app/Model/EmailNotification.php | 123 -------------- app/Model/Notification.php | 187 --------------------- app/Model/NotificationFilter.php | 199 ----------------------- app/Model/NotificationType.php | 76 +++++---- app/Model/OverdueNotification.php | 6 +- app/Model/UserNotification.php | 185 +++++++++++++++++++++ app/Model/UserNotificationFilter.php | 199 +++++++++++++++++++++++ app/Model/UserNotificationType.php | 51 ++++++ app/Model/UserUnreadNotification.php | 154 ++++++++++++++++++ app/Model/WebNotification.php | 156 ------------------ app/Notification/Mail.php | 140 ++++++++++++++++ app/Notification/NotificationInterface.php | 32 ++++ app/Notification/Web.php | 39 +++++ app/ServiceProvider/ClassProvider.php | 20 ++- app/Subscriber/NotificationSubscriber.php | 2 +- app/Template/app/notifications.php | 4 +- tests/units/Base.php | 6 + tests/units/Model/EmailNotificationTest.php | 118 -------------- tests/units/Model/NotificationFilterTest.php | 193 ---------------------- tests/units/Model/NotificationTest.php | 197 ---------------------- tests/units/Model/NotificationTypeTest.php | 26 --- tests/units/Model/UserNotificationFilterTest.php | 193 ++++++++++++++++++++++ tests/units/Model/UserNotificationTest.php | 198 ++++++++++++++++++++++ tests/units/Model/UserNotificationTypeTest.php | 30 ++++ tests/units/Model/UserUnreadNotificationTest.php | 141 ++++++++++++++++ tests/units/Model/WebNotificationTest.php | 141 ---------------- tests/units/Notification/MailTest.php | 118 ++++++++++++++ 34 files changed, 1608 insertions(+), 1459 deletions(-) create mode 100644 app/Controller/WebNotification.php delete mode 100644 app/Controller/Webnotification.php delete mode 100644 app/Core/NotificationInterface.php delete mode 100644 app/Model/EmailNotification.php delete mode 100644 app/Model/Notification.php delete mode 100644 app/Model/NotificationFilter.php create mode 100644 app/Model/UserNotification.php create mode 100644 app/Model/UserNotificationFilter.php create mode 100644 app/Model/UserNotificationType.php create mode 100644 app/Model/UserUnreadNotification.php delete mode 100644 app/Model/WebNotification.php create mode 100644 app/Notification/Mail.php create mode 100644 app/Notification/NotificationInterface.php create mode 100644 app/Notification/Web.php delete mode 100644 tests/units/Model/EmailNotificationTest.php delete mode 100644 tests/units/Model/NotificationFilterTest.php delete mode 100644 tests/units/Model/NotificationTest.php delete mode 100644 tests/units/Model/NotificationTypeTest.php create mode 100644 tests/units/Model/UserNotificationFilterTest.php create mode 100644 tests/units/Model/UserNotificationTest.php create mode 100644 tests/units/Model/UserNotificationTypeTest.php create mode 100644 tests/units/Model/UserUnreadNotificationTest.php delete mode 100644 tests/units/Model/WebNotificationTest.php create mode 100644 tests/units/Notification/MailTest.php diff --git a/app/Controller/App.php b/app/Controller/App.php index 50ac1d32..3f3f0176 100644 --- a/app/Controller/App.php +++ b/app/Controller/App.php @@ -198,7 +198,7 @@ class App extends Base $this->response->html($this->layout('app/notifications', array( 'title' => t('My notifications'), - 'notifications' => $this->webNotification->getAll($user['id']), + 'notifications' => $this->userUnreadNotification->getAll($user['id']), 'user' => $user, ))); } diff --git a/app/Controller/User.php b/app/Controller/User.php index 15e9a0ee..7444ed82 100644 --- a/app/Controller/User.php +++ b/app/Controller/User.php @@ -96,7 +96,7 @@ class User extends Base $this->projectPermission->addMember($project_id, $user_id); if (! empty($values['notifications_enabled'])) { - $this->notificationType->saveUserSelectedTypes($user_id, array(NotificationType::TYPE_EMAIL)); + $this->userNotificationType->saveSelectedTypes($user_id, array(NotificationType::TYPE_EMAIL)); } $this->session->flash(t('User created successfully.')); @@ -201,16 +201,16 @@ class User extends Base if ($this->request->isPost()) { $values = $this->request->getValues(); - $this->notification->saveSettings($user['id'], $values); + $this->userNotification->saveSettings($user['id'], $values); $this->session->flash(t('User updated successfully.')); $this->response->redirect($this->helper->url->to('user', 'notifications', array('user_id' => $user['id']))); } $this->response->html($this->layout('user/notifications', array( 'projects' => $this->projectPermission->getMemberProjects($user['id']), - 'notifications' => $this->notification->readSettings($user['id']), - 'types' => $this->notificationType->getTypes(), - 'filters' => $this->notificationFilter->getFilters(), + 'notifications' => $this->userNotification->readSettings($user['id']), + 'types' => $this->userNotificationType->getTypes(), + 'filters' => $this->userNotificationFilter->getFilters(), 'user' => $user, ))); } diff --git a/app/Controller/WebNotification.php b/app/Controller/WebNotification.php new file mode 100644 index 00000000..dca5cb46 --- /dev/null +++ b/app/Controller/WebNotification.php @@ -0,0 +1,50 @@ +getUserId(); + + $this->userUnreadNotification->markAllAsRead($user_id); + $this->response->redirect($this->helper->url->to('app', 'notifications', array('user_id' => $user_id))); + } + + /** + * Mark a notification as read + * + * @access public + */ + public function remove() + { + $user_id = $this->getUserId(); + $notification_id = $this->request->getIntegerParam('notification_id'); + + $this->userUnreadNotification->markAsRead($user_id, $notification_id); + $this->response->redirect($this->helper->url->to('app', 'notifications', array('user_id' => $user_id))); + } + + private function getUserId() + { + $user_id = $this->request->getIntegerParam('user_id'); + + if (! $this->userSession->isAdmin() && $user_id != $this->userSession->getId()) { + $user_id = $this->userSession->getId(); + } + + return $user_id; + } +} diff --git a/app/Controller/Webnotification.php b/app/Controller/Webnotification.php deleted file mode 100644 index 52e3f266..00000000 --- a/app/Controller/Webnotification.php +++ /dev/null @@ -1,39 +0,0 @@ -userSession->getId(); - - $this->webNotification->markAllAsRead($user_id); - $this->response->redirect($this->helper->url->to('app', 'notifications', array('user_id' => $user_id))); - } - - /** - * Mark a notification as read - * - * @access public - */ - public function remove() - { - $user_id = $this->userSession->getId(); - $notification_id = $this->request->getIntegerParam('notification_id'); - - $this->webNotification->markAsRead($user_id, $notification_id); - $this->response->redirect($this->helper->url->to('app', 'notifications', array('user_id' => $user_id))); - } -} diff --git a/app/Core/Base.php b/app/Core/Base.php index 76723e8f..c542cd47 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -49,11 +49,11 @@ use Pimple\Container; * @property \Kanboard\Model\File $file * @property \Kanboard\Model\LastLogin $lastLogin * @property \Kanboard\Model\Link $link - * @property \Kanboard\Model\Notification $notification - * @property \Kanboard\Model\NotificationType $notificationType - * @property \Kanboard\Model\NotificationFilter $notificationFilter + * @property \Kanboard\Model\UserNotification $userNotification + * @property \Kanboard\Model\UserNotificationType $userNotificationType + * @property \Kanboard\Model\UserNotificationFilter $userNotificationFilter + * @property \Kanboard\Model\UserUnreadNotification $userUnreadNotification * @property \Kanboard\Model\OverdueNotification $overdueNotification - * @property \Kanboard\Model\WebNotification $webNotification * @property \Kanboard\Model\Project $project * @property \Kanboard\Model\ProjectActivity $projectActivity * @property \Kanboard\Model\ProjectAnalytic $projectAnalytic diff --git a/app/Core/NotificationInterface.php b/app/Core/NotificationInterface.php deleted file mode 100644 index b6cd1781..00000000 --- a/app/Core/NotificationInterface.php +++ /dev/null @@ -1,22 +0,0 @@ -webNotification->hasNotifications($this->userSession->getId()); + return $this->userUnreadNotification->hasNotifications($this->userSession->getId()); } /** diff --git a/app/Model/EmailNotification.php b/app/Model/EmailNotification.php deleted file mode 100644 index 312828e4..00000000 --- a/app/Model/EmailNotification.php +++ /dev/null @@ -1,123 +0,0 @@ -emailClient->send( - $user['email'], - $user['name'] ?: $user['username'], - $this->getMailSubject($event_name, $event_data), - $this->getMailContent($event_name, $event_data) - ); - } - } - - /** - * Get the mail content for a given template name - * - * @access public - * @param string $event_name Event name - * @param array $event_data Event data - * @return string - */ - public function getMailContent($event_name, array $event_data) - { - return $this->template->render( - 'notification/'.str_replace('.', '_', $event_name), - $event_data + array('application_url' => $this->config->get('application_url')) - ); - } - - /** - * Get the mail subject for a given template name - * - * @access public - * @param string $event_name Event name - * @param array $event_data Event data - * @return string - */ - public function getMailSubject($event_name, array $event_data) - { - switch ($event_name) { - case File::EVENT_CREATE: - $subject = $this->getStandardMailSubject(e('New attachment'), $event_data); - break; - case Comment::EVENT_CREATE: - $subject = $this->getStandardMailSubject(e('New comment'), $event_data); - break; - case Comment::EVENT_UPDATE: - $subject = $this->getStandardMailSubject(e('Comment updated'), $event_data); - break; - case Subtask::EVENT_CREATE: - $subject = $this->getStandardMailSubject(e('New subtask'), $event_data); - break; - case Subtask::EVENT_UPDATE: - $subject = $this->getStandardMailSubject(e('Subtask updated'), $event_data); - break; - case Task::EVENT_CREATE: - $subject = $this->getStandardMailSubject(e('New task'), $event_data); - break; - case Task::EVENT_UPDATE: - $subject = $this->getStandardMailSubject(e('Task updated'), $event_data); - break; - case Task::EVENT_CLOSE: - $subject = $this->getStandardMailSubject(e('Task closed'), $event_data); - break; - case Task::EVENT_OPEN: - $subject = $this->getStandardMailSubject(e('Task opened'), $event_data); - break; - case Task::EVENT_MOVE_COLUMN: - $subject = $this->getStandardMailSubject(e('Column change'), $event_data); - break; - case Task::EVENT_MOVE_POSITION: - $subject = $this->getStandardMailSubject(e('Position change'), $event_data); - break; - case Task::EVENT_MOVE_SWIMLANE: - $subject = $this->getStandardMailSubject(e('Swimlane change'), $event_data); - break; - case Task::EVENT_ASSIGNEE_CHANGE: - $subject = $this->getStandardMailSubject(e('Assignee change'), $event_data); - break; - case Task::EVENT_OVERDUE: - $subject = e('[%s] Overdue tasks', $event_data['project_name']); - break; - default: - $subject = e('Notification'); - } - - return $subject; - } - - /** - * Get the mail subject for a given label - * - * @access private - * @param string $label Label - * @param array $data Template data - * @return string - */ - private function getStandardMailSubject($label, array $data) - { - return sprintf('[%s][%s] %s (#%d)', $data['task']['project_name'], $label, $data['task']['title'], $data['task']['id']); - } -} diff --git a/app/Model/Notification.php b/app/Model/Notification.php deleted file mode 100644 index 692f37a7..00000000 --- a/app/Model/Notification.php +++ /dev/null @@ -1,187 +0,0 @@ -userSession->isLogged() ? $this->userSession->getId() : 0; - $users = $this->notification->getUsersWithNotificationEnabled($event_data['task']['project_id'], $logged_user_id); - - if (! empty($users)) { - - foreach ($users as $user) { - if ($this->notificationFilter->shouldReceiveNotification($user, $event_data)) { - $this->sendUserNotification($user, $event_name, $event_data); - } - } - - // Restore locales - $this->config->setupTranslations(); - } - } - - /** - * Send notification to someone - * - * @access public - * @param array $user User - * @param string $event_name - * @param array $event_data - */ - public function sendUserNotification(array $user, $event_name, array $event_data) - { - Translator::unload(); - - // Use the user language otherwise use the application language (do not use the session language) - if (! empty($user['language'])) { - Translator::load($user['language']); - } - else { - Translator::load($this->config->get('application_language', 'en_US')); - } - - foreach ($this->notificationType->getUserSelectedTypes($user['id']) as $type) { - $className = strtolower($type).'Notification'; - $this->$className->send($user, $event_name, $event_data); - } - } - - /** - * Get a list of people with notifications enabled - * - * @access public - * @param integer $project_id Project id - * @param integer $exclude_user_id User id to exclude - * @return array - */ - public function getUsersWithNotificationEnabled($project_id, $exclude_user_id = 0) - { - if ($this->projectPermission->isEverybodyAllowed($project_id)) { - return $this->getEverybodyWithNotificationEnabled($exclude_user_id); - } - - return $this->getProjectMembersWithNotificationEnabled($project_id, $exclude_user_id); - } - - /** - * Enable notification for someone - * - * @access public - * @param integer $user_id - * @return boolean - */ - public function enableNotification($user_id) - { - return $this->db->table(User::TABLE)->eq('id', $user_id)->update(array('notifications_enabled' => 1)); - } - - /** - * Disable notification for someone - * - * @access public - * @param integer $user_id - * @return boolean - */ - public function disableNotification($user_id) - { - return $this->db->table(User::TABLE)->eq('id', $user_id)->update(array('notifications_enabled' => 0)); - } - - /** - * Save settings for the given user - * - * @access public - * @param integer $user_id User id - * @param array $values Form values - */ - public function saveSettings($user_id, array $values) - { - $this->db->startTransaction(); - - if (isset($values['notifications_enabled']) && $values['notifications_enabled'] == 1) { - $this->enableNotification($user_id); - - $filter = empty($values['notifications_filter']) ? NotificationFilter::FILTER_BOTH : $values['notifications_filter']; - $projects = empty($values['notification_projects']) ? array() : array_keys($values['notification_projects']); - $types = empty($values['notification_types']) ? array() : array_keys($values['notification_types']); - - $this->notificationFilter->saveUserFilter($user_id, $filter); - $this->notificationFilter->saveUserSelectedProjects($user_id, $projects); - $this->notificationType->saveUserSelectedTypes($user_id, $types); - } - else { - $this->disableNotification($user_id); - } - - $this->db->closeTransaction(); - } - - /** - * Read user settings to display the form - * - * @access public - * @param integer $user_id User id - * @return array - */ - public function readSettings($user_id) - { - $values = $this->db->table(User::TABLE)->eq('id', $user_id)->columns('notifications_enabled', 'notifications_filter')->findOne(); - $values['notification_types'] = $this->notificationType->getUserSelectedTypes($user_id); - $values['notification_projects'] = $this->notificationFilter->getUserSelectedProjects($user_id); - return $values; - } - - /** - * Get a list of project members with notification enabled - * - * @access private - * @param integer $project_id Project id - * @param integer $exclude_user_id User id to exclude - * @return array - */ - private function getProjectMembersWithNotificationEnabled($project_id, $exclude_user_id) - { - return $this->db - ->table(ProjectPermission::TABLE) - ->columns(User::TABLE.'.id', User::TABLE.'.username', User::TABLE.'.name', User::TABLE.'.email', User::TABLE.'.language', User::TABLE.'.notifications_filter') - ->join(User::TABLE, 'id', 'user_id') - ->eq('project_id', $project_id) - ->eq('notifications_enabled', '1') - ->neq(User::TABLE.'.id', $exclude_user_id) - ->findAll(); - } - - /** - * Get a list of project members with notification enabled - * - * @access private - * @param integer $exclude_user_id User id to exclude - * @return array - */ - private function getEverybodyWithNotificationEnabled($exclude_user_id) - { - return $this->db - ->table(User::TABLE) - ->columns(User::TABLE.'.id', User::TABLE.'.username', User::TABLE.'.name', User::TABLE.'.email', User::TABLE.'.language', User::TABLE.'.notifications_filter') - ->eq('notifications_enabled', '1') - ->neq(User::TABLE.'.id', $exclude_user_id) - ->findAll(); - } -} diff --git a/app/Model/NotificationFilter.php b/app/Model/NotificationFilter.php deleted file mode 100644 index f1ad367b..00000000 --- a/app/Model/NotificationFilter.php +++ /dev/null @@ -1,199 +0,0 @@ - t('All tasks'), - self::FILTER_ASSIGNEE => t('Only for tasks assigned to me'), - self::FILTER_CREATOR => t('Only for tasks created by me'), - self::FILTER_BOTH => t('Only for tasks created by me and assigned to me'), - ); - } - - /** - * Get user selected filter - * - * @access public - * @param integer $user_id - * @return integer - */ - public function getUserSelectedFilter($user_id) - { - return $this->db->table(User::TABLE)->eq('id', $user_id)->findOneColumn('notifications_filter'); - } - - /** - * Save selected filter for a user - * - * @access public - * @param integer $user_id - * @param string $filter - */ - public function saveUserFilter($user_id, $filter) - { - $this->db->table(User::TABLE)->eq('id', $user_id)->update(array( - 'notifications_filter' => $filter, - )); - } - - /** - * Get user selected projects - * - * @access public - * @param integer $user_id - * @return array - */ - public function getUserSelectedProjects($user_id) - { - return $this->db->table(self::PROJECT_TABLE)->eq('user_id', $user_id)->findAllByColumn('project_id'); - } - - /** - * Save selected projects for a user - * - * @access public - * @param integer $user_id - * @param integer[] $project_ids - */ - public function saveUserSelectedProjects($user_id, array $project_ids) - { - $this->db->table(self::PROJECT_TABLE)->eq('user_id', $user_id)->remove(); - - foreach ($project_ids as $project_id) { - $this->db->table(self::PROJECT_TABLE)->insert(array( - 'user_id' => $user_id, - 'project_id' => $project_id, - )); - } - } - - /** - * Return true if the user should receive notification - * - * @access public - * @param array $user - * @param array $event_data - * @return boolean - */ - public function shouldReceiveNotification(array $user, array $event_data) - { - $filters = array( - 'filterNone', - 'filterAssignee', - 'filterCreator', - 'filterBoth', - ); - - foreach ($filters as $filter) { - if ($this->$filter($user, $event_data)) { - return $this->filterProject($user, $event_data); - } - } - - return false; - } - - /** - * Return true if the user will receive all notifications - * - * @access public - * @param array $user - * @return boolean - */ - public function filterNone(array $user) - { - return $user['notifications_filter'] == self::FILTER_NONE; - } - - /** - * Return true if the user is the assignee and selected the filter "assignee" - * - * @access public - * @param array $user - * @param array $event_data - * @return boolean - */ - public function filterAssignee(array $user, array $event_data) - { - return $user['notifications_filter'] == self::FILTER_ASSIGNEE && $event_data['task']['owner_id'] == $user['id']; - } - - /** - * Return true if the user is the creator and enabled the filter "creator" - * - * @access public - * @param array $user - * @param array $event_data - * @return boolean - */ - public function filterCreator(array $user, array $event_data) - { - return $user['notifications_filter'] == self::FILTER_CREATOR && $event_data['task']['creator_id'] == $user['id']; - } - - /** - * Return true if the user is the assignee or the creator and selected the filter "both" - * - * @access public - * @param array $user - * @param array $event_data - * @return boolean - */ - public function filterBoth(array $user, array $event_data) - { - return $user['notifications_filter'] == self::FILTER_BOTH && - ($event_data['task']['creator_id'] == $user['id'] || $event_data['task']['owner_id'] == $user['id']); - } - - /** - * Return true if the user want to receive notification for the selected project - * - * @access public - * @param array $user - * @param array $event_data - * @return boolean - */ - public function filterProject(array $user, array $event_data) - { - $projects = $this->getUserSelectedProjects($user['id']); - - if (! empty($projects)) { - return in_array($event_data['task']['project_id'], $projects); - } - - return true; - } -} diff --git a/app/Model/NotificationType.php b/app/Model/NotificationType.php index b0514b19..9ec250ab 100644 --- a/app/Model/NotificationType.php +++ b/app/Model/NotificationType.php @@ -2,72 +2,82 @@ namespace Kanboard\Model; +use Pimple\Container; + /** - * Notification Type model + * Notification Type * * @package model * @author Frederic Guillot */ -class NotificationType extends Base +abstract class NotificationType extends Base { /** - * SQL table name + * Mail transport instances * - * @var string + * @access private + * @var \Pimple\Container */ - const TABLE = 'user_has_notification_types'; + private $classes; /** - * Types + * Mail transport instances * - * @var string + * @access private + * @var array */ - const TYPE_WEB = 'web'; - const TYPE_EMAIL = 'email'; + private $labels = array(); /** - * Get all notification types + * Constructor * * @access public - * @return array + * @param \Pimple\Container $container */ - public function getTypes() + public function __construct(Container $container) { - return array( - self::TYPE_EMAIL => t('Email'), - self::TYPE_WEB => t('Web'), - ); + parent::__construct($container); + $this->classes = new Container; } /** - * Get selected notification types for a given user + * Add a new notification type * * @access public - * @param integer $user_id - * @return array + * @param string $type + * @param string $label + * @param string $class */ - public function getUserSelectedTypes($user_id) + public function setType($type, $label, $class) { - return $this->db->table(self::TABLE)->eq('user_id', $user_id)->asc('notification_type')->findAllByColumn('notification_type'); + $container = $this->container; + $this->labels[$type] = $label; + + $this->classes[$type] = function() use ($class, $container) { + return new $class($container); + }; } /** - * Save notification types for a given user + * Get mail notification type instance * * @access public - * @param integer $user_id - * @param string[] $types - * @return boolean + * @param string $type + * @return NotificationInterface */ - public function saveUserSelectedTypes($user_id, array $types) + public function getType($type) { - $results = array(); - $this->db->table(self::TABLE)->eq('user_id', $user_id)->remove(); - - foreach ($types as $type) { - $results[] = $this->db->table(self::TABLE)->insert(array('user_id' => $user_id, 'notification_type' => $type)); - } + return $this->classes[$type]; + } - return ! in_array(false, $results); + /** + * Get all notification types with labels + * + * @access public + * @return array + */ + public function getTypes() + { + return $this->labels; } } diff --git a/app/Model/OverdueNotification.php b/app/Model/OverdueNotification.php index f44c8dd7..d8c2fef4 100644 --- a/app/Model/OverdueNotification.php +++ b/app/Model/OverdueNotification.php @@ -22,7 +22,7 @@ class OverdueNotification extends Base foreach ($this->groupByColumn($tasks, 'project_id') as $project_id => $project_tasks) { // Get the list of users that should receive notifications for each projects - $users = $this->notification->getUsersWithNotificationEnabled($project_id); + $users = $this->userNotification->getUsersWithNotificationEnabled($project_id); foreach ($users as $user) { $this->sendUserOverdueTaskNotifications($user, $project_tasks); @@ -44,13 +44,13 @@ class OverdueNotification extends Base $user_tasks = array(); foreach ($tasks as $task) { - if ($this->notificationFilter->shouldReceiveNotification($user, array('task' => $task))) { + if ($this->userNotificationFilter->shouldReceiveNotification($user, array('task' => $task))) { $user_tasks[] = $task; } } if (! empty($user_tasks)) { - $this->notification->sendUserNotification( + $this->userNotification->sendUserNotification( $user, Task::EVENT_OVERDUE, array('tasks' => $user_tasks, 'project_name' => $tasks[0]['project_name']) diff --git a/app/Model/UserNotification.php b/app/Model/UserNotification.php new file mode 100644 index 00000000..b4ee77a9 --- /dev/null +++ b/app/Model/UserNotification.php @@ -0,0 +1,185 @@ +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); + } + } + + // Restore locales + $this->config->setupTranslations(); + } + } + + /** + * Send notification to someone + * + * @access public + * @param array $user User + * @param string $event_name + * @param array $event_data + */ + public function sendUserNotification(array $user, $event_name, array $event_data) + { + Translator::unload(); + + // Use the user language otherwise use the application language (do not use the session language) + if (! empty($user['language'])) { + Translator::load($user['language']); + } + else { + Translator::load($this->config->get('application_language', 'en_US')); + } + + foreach ($this->userNotificationType->getSelectedTypes($user['id']) as $type) { + $this->userNotificationType->getType($type)->notifyUser($user, $event_name, $event_data); + } + } + + /** + * Get a list of people with notifications enabled + * + * @access public + * @param integer $project_id Project id + * @param integer $exclude_user_id User id to exclude + * @return array + */ + public function getUsersWithNotificationEnabled($project_id, $exclude_user_id = 0) + { + if ($this->projectPermission->isEverybodyAllowed($project_id)) { + return $this->getEverybodyWithNotificationEnabled($exclude_user_id); + } + + return $this->getProjectMembersWithNotificationEnabled($project_id, $exclude_user_id); + } + + /** + * Enable notification for someone + * + * @access public + * @param integer $user_id + * @return boolean + */ + public function enableNotification($user_id) + { + return $this->db->table(User::TABLE)->eq('id', $user_id)->update(array('notifications_enabled' => 1)); + } + + /** + * Disable notification for someone + * + * @access public + * @param integer $user_id + * @return boolean + */ + public function disableNotification($user_id) + { + return $this->db->table(User::TABLE)->eq('id', $user_id)->update(array('notifications_enabled' => 0)); + } + + /** + * Save settings for the given user + * + * @access public + * @param integer $user_id User id + * @param array $values Form values + */ + public function saveSettings($user_id, array $values) + { + $this->db->startTransaction(); + + if (isset($values['notifications_enabled']) && $values['notifications_enabled'] == 1) { + $this->enableNotification($user_id); + + $filter = empty($values['notifications_filter']) ? UserNotificationFilter::FILTER_BOTH : $values['notifications_filter']; + $projects = empty($values['notification_projects']) ? array() : array_keys($values['notification_projects']); + $types = empty($values['notification_types']) ? array() : array_keys($values['notification_types']); + + $this->userNotificationFilter->saveFilter($user_id, $filter); + $this->userNotificationFilter->saveSelectedProjects($user_id, $projects); + $this->userNotificationType->saveSelectedTypes($user_id, $types); + } + else { + $this->disableNotification($user_id); + } + + $this->db->closeTransaction(); + } + + /** + * Read user settings to display the form + * + * @access public + * @param integer $user_id User id + * @return array + */ + public function readSettings($user_id) + { + $values = $this->db->table(User::TABLE)->eq('id', $user_id)->columns('notifications_enabled', 'notifications_filter')->findOne(); + $values['notification_types'] = $this->userNotificationType->getSelectedTypes($user_id); + $values['notification_projects'] = $this->userNotificationFilter->getSelectedProjects($user_id); + return $values; + } + + /** + * Get a list of project members with notification enabled + * + * @access private + * @param integer $project_id Project id + * @param integer $exclude_user_id User id to exclude + * @return array + */ + private function getProjectMembersWithNotificationEnabled($project_id, $exclude_user_id) + { + return $this->db + ->table(ProjectPermission::TABLE) + ->columns(User::TABLE.'.id', User::TABLE.'.username', User::TABLE.'.name', User::TABLE.'.email', User::TABLE.'.language', User::TABLE.'.notifications_filter') + ->join(User::TABLE, 'id', 'user_id') + ->eq('project_id', $project_id) + ->eq('notifications_enabled', '1') + ->neq(User::TABLE.'.id', $exclude_user_id) + ->findAll(); + } + + /** + * Get a list of project members with notification enabled + * + * @access private + * @param integer $exclude_user_id User id to exclude + * @return array + */ + private function getEverybodyWithNotificationEnabled($exclude_user_id) + { + return $this->db + ->table(User::TABLE) + ->columns(User::TABLE.'.id', User::TABLE.'.username', User::TABLE.'.name', User::TABLE.'.email', User::TABLE.'.language', User::TABLE.'.notifications_filter') + ->eq('notifications_enabled', '1') + ->neq(User::TABLE.'.id', $exclude_user_id) + ->findAll(); + } +} diff --git a/app/Model/UserNotificationFilter.php b/app/Model/UserNotificationFilter.php new file mode 100644 index 00000000..d4afd278 --- /dev/null +++ b/app/Model/UserNotificationFilter.php @@ -0,0 +1,199 @@ + t('All tasks'), + self::FILTER_ASSIGNEE => t('Only for tasks assigned to me'), + self::FILTER_CREATOR => t('Only for tasks created by me'), + self::FILTER_BOTH => t('Only for tasks created by me and assigned to me'), + ); + } + + /** + * Get user selected filter + * + * @access public + * @param integer $user_id + * @return integer + */ + public function getSelectedFilter($user_id) + { + return $this->db->table(User::TABLE)->eq('id', $user_id)->findOneColumn('notifications_filter'); + } + + /** + * Save selected filter for a user + * + * @access public + * @param integer $user_id + * @param string $filter + */ + public function saveFilter($user_id, $filter) + { + $this->db->table(User::TABLE)->eq('id', $user_id)->update(array( + 'notifications_filter' => $filter, + )); + } + + /** + * Get user selected projects + * + * @access public + * @param integer $user_id + * @return array + */ + public function getSelectedProjects($user_id) + { + return $this->db->table(self::PROJECT_TABLE)->eq('user_id', $user_id)->findAllByColumn('project_id'); + } + + /** + * Save selected projects for a user + * + * @access public + * @param integer $user_id + * @param integer[] $project_ids + */ + public function saveSelectedProjects($user_id, array $project_ids) + { + $this->db->table(self::PROJECT_TABLE)->eq('user_id', $user_id)->remove(); + + foreach ($project_ids as $project_id) { + $this->db->table(self::PROJECT_TABLE)->insert(array( + 'user_id' => $user_id, + 'project_id' => $project_id, + )); + } + } + + /** + * Return true if the user should receive notification + * + * @access public + * @param array $user + * @param array $event_data + * @return boolean + */ + public function shouldReceiveNotification(array $user, array $event_data) + { + $filters = array( + 'filterNone', + 'filterAssignee', + 'filterCreator', + 'filterBoth', + ); + + foreach ($filters as $filter) { + if ($this->$filter($user, $event_data)) { + return $this->filterProject($user, $event_data); + } + } + + return false; + } + + /** + * Return true if the user will receive all notifications + * + * @access public + * @param array $user + * @return boolean + */ + public function filterNone(array $user) + { + return $user['notifications_filter'] == self::FILTER_NONE; + } + + /** + * Return true if the user is the assignee and selected the filter "assignee" + * + * @access public + * @param array $user + * @param array $event_data + * @return boolean + */ + public function filterAssignee(array $user, array $event_data) + { + return $user['notifications_filter'] == self::FILTER_ASSIGNEE && $event_data['task']['owner_id'] == $user['id']; + } + + /** + * Return true if the user is the creator and enabled the filter "creator" + * + * @access public + * @param array $user + * @param array $event_data + * @return boolean + */ + public function filterCreator(array $user, array $event_data) + { + return $user['notifications_filter'] == self::FILTER_CREATOR && $event_data['task']['creator_id'] == $user['id']; + } + + /** + * Return true if the user is the assignee or the creator and selected the filter "both" + * + * @access public + * @param array $user + * @param array $event_data + * @return boolean + */ + public function filterBoth(array $user, array $event_data) + { + return $user['notifications_filter'] == self::FILTER_BOTH && + ($event_data['task']['creator_id'] == $user['id'] || $event_data['task']['owner_id'] == $user['id']); + } + + /** + * Return true if the user want to receive notification for the selected project + * + * @access public + * @param array $user + * @param array $event_data + * @return boolean + */ + public function filterProject(array $user, array $event_data) + { + $projects = $this->getSelectedProjects($user['id']); + + if (! empty($projects)) { + return in_array($event_data['task']['project_id'], $projects); + } + + return true; + } +} diff --git a/app/Model/UserNotificationType.php b/app/Model/UserNotificationType.php new file mode 100644 index 00000000..d2613440 --- /dev/null +++ b/app/Model/UserNotificationType.php @@ -0,0 +1,51 @@ +db->table(self::TABLE)->eq('user_id', $user_id)->asc('notification_type')->findAllByColumn('notification_type'); + } + + /** + * Save notification types for a given user + * + * @access public + * @param integer $user_id + * @param string[] $types + * @return boolean + */ + public function saveSelectedTypes($user_id, array $types) + { + $results = array(); + $this->db->table(self::TABLE)->eq('user_id', $user_id)->remove(); + + foreach ($types as $type) { + $results[] = $this->db->table(self::TABLE)->insert(array('user_id' => $user_id, 'notification_type' => $type)); + } + + return ! in_array(false, $results); + } +} diff --git a/app/Model/UserUnreadNotification.php b/app/Model/UserUnreadNotification.php new file mode 100644 index 00000000..98a337a2 --- /dev/null +++ b/app/Model/UserUnreadNotification.php @@ -0,0 +1,154 @@ +db->table(self::TABLE)->insert(array( + 'user_id' => $user_id, + 'date_creation' => time(), + 'event_name' => $event_name, + 'event_data' => json_encode($event_data), + )); + } + + /** + * Get all notifications for a user + * + * @access public + * @param integer $user_id + * @return array + */ + public function getAll($user_id) + { + $events = $this->db->table(self::TABLE)->eq('user_id', $user_id)->asc('date_creation')->findAll(); + + foreach ($events as &$event) { + $event['event_data'] = json_decode($event['event_data'], true); + $event['title'] = $this->getTitleFromEvent($event['event_name'], $event['event_data']); + } + + return $events; + } + + /** + * Mark a notification as read + * + * @access public + * @param integer $user_id + * @param integer $notification_id + * @return boolean + */ + public function markAsRead($user_id, $notification_id) + { + return $this->db->table(self::TABLE)->eq('id', $notification_id)->eq('user_id', $user_id)->remove(); + } + + /** + * Mark all notifications as read for a user + * + * @access public + * @param integer $user_id + * @return boolean + */ + public function markAllAsRead($user_id) + { + return $this->db->table(self::TABLE)->eq('user_id', $user_id)->remove(); + } + + /** + * Return true if the user as unread notifications + * + * @access public + * @param integer $user_id + * @return boolean + */ + public function hasNotifications($user_id) + { + return $this->db->table(self::TABLE)->eq('user_id', $user_id)->exists(); + } + + /** + * Get title from event + * + * @access public + * @param string $event_name + * @param array $event_data + * @return string + */ + public function getTitleFromEvent($event_name, array $event_data) + { + switch ($event_name) { + case File::EVENT_CREATE: + $title = t('New attachment on task #%d: %s', $event_data['file']['task_id'], $event_data['file']['name']); + break; + case Comment::EVENT_CREATE: + $title = t('New comment on task #%d', $event_data['comment']['task_id']); + break; + case Comment::EVENT_UPDATE: + $title = t('Comment updated on task #%d', $event_data['comment']['task_id']); + break; + case Subtask::EVENT_CREATE: + $title = t('New subtask on task #%d', $event_data['subtask']['task_id']); + break; + case Subtask::EVENT_UPDATE: + $title = t('Subtask updated on task #%d', $event_data['subtask']['task_id']); + break; + case Task::EVENT_CREATE: + $title = t('New task #%d: %s', $event_data['task']['id'], $event_data['task']['title']); + break; + case Task::EVENT_UPDATE: + $title = t('Task updated #%d', $event_data['task']['id']); + break; + case Task::EVENT_CLOSE: + $title = t('Task #%d closed', $event_data['task']['id']); + break; + case Task::EVENT_OPEN: + $title = t('Task #%d opened', $event_data['task']['id']); + break; + case Task::EVENT_MOVE_COLUMN: + $title = t('Column changed for task #%d', $event_data['task']['id']); + break; + case Task::EVENT_MOVE_POSITION: + $title = t('New position for task #%d', $event_data['task']['id']); + break; + case Task::EVENT_MOVE_SWIMLANE: + $title = t('Swimlane changed for task #%d', $event_data['task']['id']); + break; + case Task::EVENT_ASSIGNEE_CHANGE: + $title = t('Assignee changed on task #%d', $event_data['task']['id']); + break; + case Task::EVENT_OVERDUE: + $nb = count($event_data['tasks']); + $title = $nb > 1 ? t('%d overdue tasks', $nb) : t('Task #%d is overdue', $event_data['tasks'][0]['id']); + break; + default: + $title = e('Notification'); + } + + return $title; + } +} diff --git a/app/Model/WebNotification.php b/app/Model/WebNotification.php deleted file mode 100644 index 02bcc956..00000000 --- a/app/Model/WebNotification.php +++ /dev/null @@ -1,156 +0,0 @@ -db->table(self::TABLE)->insert(array( - 'user_id' => $user['id'], - 'date_creation' => time(), - 'event_name' => $event_name, - 'event_data' => json_encode($event_data), - )); - } - - /** - * Get all notifications for a user - * - * @access public - * @param integer $user_id - * @return array - */ - public function getAll($user_id) - { - $events = $this->db->table(self::TABLE)->eq('user_id', $user_id)->asc('date_creation')->findAll(); - - foreach ($events as &$event) { - $event['event_data'] = json_decode($event['event_data'], true); - $event['title'] = $this->getTitleFromEvent($event['event_name'], $event['event_data']); - } - - return $events; - } - - /** - * Mark a notification as read - * - * @access public - * @param integer $user_id - * @param integer $notification_id - * @return boolean - */ - public function markAsRead($user_id, $notification_id) - { - return $this->db->table(self::TABLE)->eq('id', $notification_id)->eq('user_id', $user_id)->remove(); - } - - /** - * Mark all notifications as read for a user - * - * @access public - * @param integer $user_id - * @return boolean - */ - public function markAllAsRead($user_id) - { - return $this->db->table(self::TABLE)->eq('user_id', $user_id)->remove(); - } - - /** - * Return true if the user as unread notifications - * - * @access public - * @param integer $user_id - * @return boolean - */ - public function hasNotifications($user_id) - { - return $this->db->table(self::TABLE)->eq('user_id', $user_id)->exists(); - } - - /** - * Get title from event - * - * @access public - * @param string $event_name - * @param array $event_data - * @return string - */ - public function getTitleFromEvent($event_name, array $event_data) - { - switch ($event_name) { - case File::EVENT_CREATE: - $title = t('New attachment on task #%d: %s', $event_data['file']['task_id'], $event_data['file']['name']); - break; - case Comment::EVENT_CREATE: - $title = t('New comment on task #%d', $event_data['comment']['task_id']); - break; - case Comment::EVENT_UPDATE: - $title = t('Comment updated on task #%d', $event_data['comment']['task_id']); - break; - case Subtask::EVENT_CREATE: - $title = t('New subtask on task #%d', $event_data['subtask']['task_id']); - break; - case Subtask::EVENT_UPDATE: - $title = t('Subtask updated on task #%d', $event_data['subtask']['task_id']); - break; - case Task::EVENT_CREATE: - $title = t('New task #%d: %s', $event_data['task']['id'], $event_data['task']['title']); - break; - case Task::EVENT_UPDATE: - $title = t('Task updated #%d', $event_data['task']['id']); - break; - case Task::EVENT_CLOSE: - $title = t('Task #%d closed', $event_data['task']['id']); - break; - case Task::EVENT_OPEN: - $title = t('Task #%d opened', $event_data['task']['id']); - break; - case Task::EVENT_MOVE_COLUMN: - $title = t('Column changed for task #%d', $event_data['task']['id']); - break; - case Task::EVENT_MOVE_POSITION: - $title = t('New position for task #%d', $event_data['task']['id']); - break; - case Task::EVENT_MOVE_SWIMLANE: - $title = t('Swimlane changed for task #%d', $event_data['task']['id']); - break; - case Task::EVENT_ASSIGNEE_CHANGE: - $title = t('Assignee changed on task #%d', $event_data['task']['id']); - break; - case Task::EVENT_OVERDUE: - $nb = count($event_data['tasks']); - $title = $nb > 1 ? t('%d overdue tasks', $nb) : t('Task #%d is overdue', $event_data['tasks'][0]['id']); - break; - default: - $title = e('Notification'); - } - - return $title; - } -} diff --git a/app/Notification/Mail.php b/app/Notification/Mail.php new file mode 100644 index 00000000..69b8888d --- /dev/null +++ b/app/Notification/Mail.php @@ -0,0 +1,140 @@ +emailClient->send( + $user['email'], + $user['name'] ?: $user['username'], + $this->getMailSubject($event_name, $event_data), + $this->getMailContent($event_name, $event_data) + ); + } + } + + /** + * Send notification to a project + * + * @access public + * @param array $project + * @param string $event_name + * @param array $event_data + */ + public function notifyProject(array $project, $event_name, array $event_data) + { + + } + + /** + * Get the mail content for a given template name + * + * @access public + * @param string $event_name Event name + * @param array $event_data Event data + * @return string + */ + public function getMailContent($event_name, array $event_data) + { + return $this->template->render( + 'notification/'.str_replace('.', '_', $event_name), + $event_data + array('application_url' => $this->config->get('application_url')) + ); + } + + /** + * Get the mail subject for a given template name + * + * @access public + * @param string $event_name Event name + * @param array $event_data Event data + * @return string + */ + public function getMailSubject($event_name, array $event_data) + { + switch ($event_name) { + case File::EVENT_CREATE: + $subject = $this->getStandardMailSubject(e('New attachment'), $event_data); + break; + case Comment::EVENT_CREATE: + $subject = $this->getStandardMailSubject(e('New comment'), $event_data); + break; + case Comment::EVENT_UPDATE: + $subject = $this->getStandardMailSubject(e('Comment updated'), $event_data); + break; + case Subtask::EVENT_CREATE: + $subject = $this->getStandardMailSubject(e('New subtask'), $event_data); + break; + case Subtask::EVENT_UPDATE: + $subject = $this->getStandardMailSubject(e('Subtask updated'), $event_data); + break; + case Task::EVENT_CREATE: + $subject = $this->getStandardMailSubject(e('New task'), $event_data); + break; + case Task::EVENT_UPDATE: + $subject = $this->getStandardMailSubject(e('Task updated'), $event_data); + break; + case Task::EVENT_CLOSE: + $subject = $this->getStandardMailSubject(e('Task closed'), $event_data); + break; + case Task::EVENT_OPEN: + $subject = $this->getStandardMailSubject(e('Task opened'), $event_data); + break; + case Task::EVENT_MOVE_COLUMN: + $subject = $this->getStandardMailSubject(e('Column change'), $event_data); + break; + case Task::EVENT_MOVE_POSITION: + $subject = $this->getStandardMailSubject(e('Position change'), $event_data); + break; + case Task::EVENT_MOVE_SWIMLANE: + $subject = $this->getStandardMailSubject(e('Swimlane change'), $event_data); + break; + case Task::EVENT_ASSIGNEE_CHANGE: + $subject = $this->getStandardMailSubject(e('Assignee change'), $event_data); + break; + case Task::EVENT_OVERDUE: + $subject = e('[%s] Overdue tasks', $event_data['project_name']); + break; + default: + $subject = e('Notification'); + } + + return $subject; + } + + /** + * Get the mail subject for a given label + * + * @access private + * @param string $label Label + * @param array $data Template data + * @return string + */ + private function getStandardMailSubject($label, array $data) + { + return sprintf('[%s][%s] %s (#%d)', $data['task']['project_name'], $label, $data['task']['title'], $data['task']['id']); + } +} diff --git a/app/Notification/NotificationInterface.php b/app/Notification/NotificationInterface.php new file mode 100644 index 00000000..8431a77c --- /dev/null +++ b/app/Notification/NotificationInterface.php @@ -0,0 +1,32 @@ +userUnreadNotification->create($user['id'], $event_name, $event_data); + } + + /** + * Send notification to a project + * + * @access public + * @param array $project + * @param string $event_name + * @param array $event_data + */ + public function notifyProject(array $project, $event_name, array $event_data) + { + } +} diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 9df2dede..322c1a9b 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -8,9 +8,7 @@ use Kanboard\Core\ObjectStorage\FileStorage; use Kanboard\Core\Paginator; use Kanboard\Core\OAuth2; use Kanboard\Core\Tool; -use Kanboard\Model\Config; -use Kanboard\Model\Project; -use Kanboard\Model\Webhook; +use Kanboard\Model\UserNotificationType; use Pimple\Container; use Pimple\ServiceProviderInterface; use League\HTMLToMarkdown\HtmlConverter; @@ -32,12 +30,7 @@ class ClassProvider implements ServiceProviderInterface 'File', 'LastLogin', 'Link', - 'Notification', - 'NotificationType', - 'NotificationFilter', 'OverdueNotification', - 'WebNotification', - 'EmailNotification', 'Project', 'ProjectActivity', 'ProjectAnalytic', @@ -68,6 +61,10 @@ class ClassProvider implements ServiceProviderInterface 'User', 'UserImport', 'UserSession', + 'UserNotification', + 'UserNotificationType', + 'UserNotificationFilter', + 'UserUnreadNotification', 'Webhook', ), 'Formatter' => array( @@ -131,6 +128,13 @@ class ClassProvider implements ServiceProviderInterface return $mailer; }; + $container['userNotificationType'] = function($container) { + $type = new UserNotificationType($container); + $type->setType('email', t('Email'), '\Kanboard\Notification\Mail'); + $type->setType('web', t('Web'), '\Kanboard\Notification\Web'); + return $type; + }; + $container['pluginLoader'] = new Loader($container); $container['cspRules'] = array('style-src' => "'self' 'unsafe-inline'", 'img-src' => '* data:'); diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php index 610fbadb..07ce00a1 100644 --- a/app/Subscriber/NotificationSubscriber.php +++ b/app/Subscriber/NotificationSubscriber.php @@ -32,7 +32,7 @@ class NotificationSubscriber extends \Kanboard\Core\Base implements EventSubscri public function execute(GenericEvent $event, $event_name) { - $this->notification->sendNotifications($event_name, $this->getEventData($event)); + $this->userNotification->sendNotifications($event_name, $this->getEventData($event)); } public function getEventData(GenericEvent $event) diff --git a/app/Template/app/notifications.php b/app/Template/app/notifications.php index 4f7dd353..511f377b 100644 --- a/app/Template/app/notifications.php +++ b/app/Template/app/notifications.php @@ -8,7 +8,7 @@ @@ -53,7 +53,7 @@ - url->link(t('Mark as read'), 'webnotification', 'remove', array('user_id' => $user['id'], 'notification_id' => $notification['id'])) ?> + url->link(t('Mark as read'), 'webNotification', 'remove', array('user_id' => $user['id'], 'notification_id' => $notification['id'])) ?> diff --git a/tests/units/Base.php b/tests/units/Base.php index 3b7ffa2a..fe054344 100644 --- a/tests/units/Base.php +++ b/tests/units/Base.php @@ -88,6 +88,12 @@ abstract class Base extends PHPUnit_Framework_TestCase $this->container['logger']->setLogger(new File('/dev/null')); $this->container['httpClient'] = new FakeHttpClient; $this->container['emailClient'] = $this->getMockBuilder('EmailClient')->setMethods(array('send'))->getMock(); + + $this->container['userNotificationType'] = $this + ->getMockBuilder('\Kanboard\Model\UserNotificationType') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('getType')) + ->getMock(); } public function tearDown() diff --git a/tests/units/Model/EmailNotificationTest.php b/tests/units/Model/EmailNotificationTest.php deleted file mode 100644 index 342f0aa9..00000000 --- a/tests/units/Model/EmailNotificationTest.php +++ /dev/null @@ -1,118 +0,0 @@ -container); - $p = new Project($this->container); - $tf = new TaskFinder($this->container); - $tc = new TaskCreation($this->container); - $s = new Subtask($this->container); - $c = new Comment($this->container); - $f = new File($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'test', 'task_id' => 1))); - $this->assertEquals(1, $c->create(array('comment' => 'test', 'task_id' => 1, 'user_id' => 1))); - $this->assertEquals(1, $f->create(1, 'test', 'blah', 123)); - - $task = $tf->getDetails(1); - $subtask = $s->getById(1, true); - $comment = $c->getById(1); - $file = $c->getById(1); - - $this->assertNotEmpty($task); - $this->assertNotEmpty($subtask); - $this->assertNotEmpty($comment); - $this->assertNotEmpty($file); - - foreach (NotificationSubscriber::getSubscribedEvents() as $event => $values) { - $this->assertNotEmpty($en->getMailContent($event, array( - 'task' => $task, - 'comment' => $comment, - 'subtask' => $subtask, - 'file' => $file, - 'changes' => array()) - )); - - $this->assertNotEmpty($en->getMailSubject($event, array( - 'task' => $task, - 'comment' => $comment, - 'subtask' => $subtask, - 'file' => $file, - 'changes' => array()) - )); - } - } - - public function testSendWithEmailAddress() - { - $en = new EmailNotification($this->container); - $p = new Project($this->container); - $tf = new TaskFinder($this->container); - $tc = new TaskCreation($this->container); - $u = new User($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - $this->assertTrue($u->update(array('id' => 1, 'email' => 'test@localhost'))); - - $this->container['emailClient'] = $this - ->getMockBuilder('\Kanboard\Core\Mail\Client') - ->setConstructorArgs(array($this->container)) - ->setMethods(array('send')) - ->getMock(); - - $this->container['emailClient'] - ->expects($this->once()) - ->method('send') - ->with( - $this->equalTo('test@localhost'), - $this->equalTo('admin'), - $this->equalTo('[test][New task] test (#1)'), - $this->stringContains('test') - ); - - $en->send($u->getById(1), Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); - } - - public function testSendWithoutEmailAddress() - { - $en = new EmailNotification($this->container); - $p = new Project($this->container); - $tf = new TaskFinder($this->container); - $tc = new TaskCreation($this->container); - $u = new User($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - - $this->container['emailClient'] = $this - ->getMockBuilder('\Kanboard\Core\Mail\Client') - ->setConstructorArgs(array($this->container)) - ->setMethods(array('send')) - ->getMock(); - - $this->container['emailClient'] - ->expects($this->never()) - ->method('send'); - - $en->send($u->getById(1), Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); - } -} diff --git a/tests/units/Model/NotificationFilterTest.php b/tests/units/Model/NotificationFilterTest.php deleted file mode 100644 index 2f8cdc8a..00000000 --- a/tests/units/Model/NotificationFilterTest.php +++ /dev/null @@ -1,193 +0,0 @@ -container); - $filters = $nf->getFilters(); - $this->assertArrayHasKey(NotificationFilter::FILTER_NONE, $filters); - $this->assertArrayHasKey(NotificationFilter::FILTER_BOTH, $filters); - $this->assertArrayHasKey(NotificationFilter::FILTER_CREATOR, $filters); - $this->assertArrayHasKey(NotificationFilter::FILTER_ASSIGNEE, $filters); - } - - public function testSaveProjectFilter() - { - $nf = new NotificationFilter($this->container); - $p = new Project($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - $this->assertEquals(2, $p->create(array('name' => 'UnitTest2'))); - - $this->assertEmpty($nf->getUserSelectedProjects(1)); - $nf->saveUserSelectedProjects(1, array(1, 2)); - $this->assertEquals(array(1, 2), $nf->getUserSelectedProjects(1)); - } - - public function testSaveUserFilter() - { - $nf = new NotificationFilter($this->container); - - $this->assertEquals(NotificationFilter::FILTER_BOTH, $nf->getUserSelectedFilter(1)); - $nf->saveUserFilter(1, NotificationFilter::FILTER_CREATOR); - $this->assertEquals(NotificationFilter::FILTER_CREATOR, $nf->getUserSelectedFilter(1)); - } - - public function testFilterNone() - { - $u = new User($this->container); - $n = new NotificationFilter($this->container); - - $this->assertEquals(2, $u->create(array('username' => 'user1', 'notifications_filter' => NotificationFilter::FILTER_NONE))); - $this->assertTrue($n->filterNone($u->getById(2), array())); - - $this->assertEquals(3, $u->create(array('username' => 'user2', 'notifications_filter' => NotificationFilter::FILTER_BOTH))); - $this->assertFalse($n->filterNone($u->getById(3), array())); - } - - public function testFilterCreator() - { - $u = new User($this->container); - $n = new NotificationFilter($this->container); - - $this->assertEquals(2, $u->create(array('username' => 'user1', 'notifications_filter' => NotificationFilter::FILTER_CREATOR))); - $this->assertTrue($n->filterCreator($u->getById(2), array('task' => array('creator_id' => 2)))); - - $this->assertEquals(3, $u->create(array('username' => 'user2', 'notifications_filter' => NotificationFilter::FILTER_CREATOR))); - $this->assertFalse($n->filterCreator($u->getById(3), array('task' => array('creator_id' => 1)))); - - $this->assertEquals(4, $u->create(array('username' => 'user3', 'notifications_filter' => NotificationFilter::FILTER_NONE))); - $this->assertFalse($n->filterCreator($u->getById(4), array('task' => array('creator_id' => 2)))); - } - - public function testFilterAssignee() - { - $u = new User($this->container); - $n = new NotificationFilter($this->container); - - $this->assertEquals(2, $u->create(array('username' => 'user1', 'notifications_filter' => NotificationFilter::FILTER_ASSIGNEE))); - $this->assertTrue($n->filterAssignee($u->getById(2), array('task' => array('owner_id' => 2)))); - - $this->assertEquals(3, $u->create(array('username' => 'user2', 'notifications_filter' => NotificationFilter::FILTER_ASSIGNEE))); - $this->assertFalse($n->filterAssignee($u->getById(3), array('task' => array('owner_id' => 1)))); - - $this->assertEquals(4, $u->create(array('username' => 'user3', 'notifications_filter' => NotificationFilter::FILTER_NONE))); - $this->assertFalse($n->filterAssignee($u->getById(4), array('task' => array('owner_id' => 2)))); - } - - public function testFilterBoth() - { - $u = new User($this->container); - $n = new NotificationFilter($this->container); - - $this->assertEquals(2, $u->create(array('username' => 'user1', 'notifications_filter' => NotificationFilter::FILTER_BOTH))); - $this->assertTrue($n->filterBoth($u->getById(2), array('task' => array('owner_id' => 2, 'creator_id' => 1)))); - $this->assertTrue($n->filterBoth($u->getById(2), array('task' => array('owner_id' => 0, 'creator_id' => 2)))); - - $this->assertEquals(3, $u->create(array('username' => 'user2', 'notifications_filter' => NotificationFilter::FILTER_BOTH))); - $this->assertFalse($n->filterBoth($u->getById(3), array('task' => array('owner_id' => 1, 'creator_id' => 1)))); - $this->assertFalse($n->filterBoth($u->getById(3), array('task' => array('owner_id' => 2, 'creator_id' => 1)))); - - $this->assertEquals(4, $u->create(array('username' => 'user3', 'notifications_filter' => NotificationFilter::FILTER_NONE))); - $this->assertFalse($n->filterBoth($u->getById(4), array('task' => array('owner_id' => 2, 'creator_id' => 1)))); - } - - public function testFilterProject() - { - $u = new User($this->container); - $n = new Notification($this->container); - $nf = new NotificationFilter($this->container); - $p = new Project($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - $this->assertEquals(2, $p->create(array('name' => 'UnitTest2'))); - - // No project selected - $this->assertTrue($nf->filterProject($u->getById(1), array())); - - // User that select only some projects - $this->assertEquals(2, $u->create(array('username' => 'user2', 'notifications_filter' => NotificationFilter::FILTER_NONE))); - $n->saveSettings(2, array('notifications_enabled' => 1, 'notification_projects' => array(2 => true))); - - $this->assertFalse($nf->filterProject($u->getById(2), array('task' => array('project_id' => 1)))); - $this->assertTrue($nf->filterProject($u->getById(2), array('task' => array('project_id' => 2)))); - } - - public function testFilterUserWithNoFilter() - { - $u = new User($this->container); - $n = new NotificationFilter($this->container); - $p = new Project($this->container); - - $this->assertEquals(2, $u->create(array('username' => 'user2', 'notifications_filter' => NotificationFilter::FILTER_NONE))); - - $this->assertTrue($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1)))); - } - - public function testFilterUserWithAssigneeFilter() - { - $u = new User($this->container); - $n = new NotificationFilter($this->container); - $p = new Project($this->container); - - $this->assertEquals(2, $u->create(array('username' => 'user2', 'notifications_filter' => NotificationFilter::FILTER_ASSIGNEE))); - - $this->assertTrue($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'owner_id' => 2)))); - $this->assertFalse($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'owner_id' => 1)))); - } - - public function testFilterUserWithCreatorFilter() - { - $u = new User($this->container); - $n = new NotificationFilter($this->container); - $p = new Project($this->container); - - $this->assertEquals(2, $u->create(array('username' => 'user2', 'notifications_filter' => NotificationFilter::FILTER_CREATOR))); - - $this->assertTrue($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 2)))); - $this->assertFalse($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 1)))); - } - - public function testFilterUserWithBothFilter() - { - $u = new User($this->container); - $n = new NotificationFilter($this->container); - $p = new Project($this->container); - - $this->assertEquals(2, $u->create(array('username' => 'user2', 'notifications_filter' => NotificationFilter::FILTER_BOTH))); - - $this->assertTrue($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 2, 'owner_id' => 3)))); - $this->assertTrue($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 0, 'owner_id' => 2)))); - $this->assertFalse($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 4, 'owner_id' => 1)))); - $this->assertFalse($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 5, 'owner_id' => 0)))); - } - - public function testFilterUserWithBothFilterAndProjectSelected() - { - $u = new User($this->container); - $n = new Notification($this->container); - $nf = new NotificationFilter($this->container); - $p = new Project($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - $this->assertEquals(2, $p->create(array('name' => 'UnitTest2'))); - - $this->assertEquals(2, $u->create(array('username' => 'user2', 'notifications_filter' => NotificationFilter::FILTER_BOTH))); - - $n->saveSettings(2, array('notifications_enabled' => 1, 'notification_projects' => array(2 => true))); - - $this->assertFalse($nf->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 2, 'owner_id' => 3)))); - $this->assertFalse($nf->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 0, 'owner_id' => 2)))); - - $this->assertTrue($nf->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 2, 'creator_id' => 2, 'owner_id' => 3)))); - $this->assertTrue($nf->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 2, 'creator_id' => 0, 'owner_id' => 2)))); - } -} diff --git a/tests/units/Model/NotificationTest.php b/tests/units/Model/NotificationTest.php deleted file mode 100644 index 251ae1b2..00000000 --- a/tests/units/Model/NotificationTest.php +++ /dev/null @@ -1,197 +0,0 @@ -container); - $p = new Project($this->container); - $n = new Notification($this->container); - $pp = new ProjectPermission($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - $this->assertEquals(2, $u->create(array('username' => 'user1'))); - $this->assertTrue($pp->addMember(1, 2)); - - $this->assertEmpty($n->getUsersWithNotificationEnabled(1)); - $n->enableNotification(2); - $this->assertNotEmpty($n->getUsersWithNotificationEnabled(1)); - $n->disableNotification(2); - $this->assertEmpty($n->getUsersWithNotificationEnabled(1)); - } - - public function testReadWriteSettings() - { - $n = new Notification($this->container); - $p = new Project($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - - $n->saveSettings(1, array( - 'notifications_enabled' => 1, - 'notifications_filter' => NotificationFilter::FILTER_CREATOR, - 'notification_types' => array(NotificationType::TYPE_EMAIL => 1), - 'notification_projects' => array(), - )); - - $settings = $n->readSettings(1); - $this->assertNotEmpty($settings); - $this->assertEquals(1, $settings['notifications_enabled']); - $this->assertEquals(NotificationFilter::FILTER_CREATOR, $settings['notifications_filter']); - $this->assertEquals(array(NotificationType::TYPE_EMAIL), $settings['notification_types']); - $this->assertEmpty($settings['notification_projects']); - - $n->saveSettings(1, array( - 'notifications_enabled' => 0, - )); - - $settings = $n->readSettings(1); - $this->assertNotEmpty($settings); - $this->assertEquals(0, $settings['notifications_enabled']); - - $n->saveSettings(1, array( - 'notifications_enabled' => 1, - 'notifications_filter' => NotificationFilter::FILTER_ASSIGNEE, - 'notification_types' => array(NotificationType::TYPE_WEB => 1, NotificationType::TYPE_EMAIL => 1), - 'notification_projects' => array(1 => 1), - )); - - $settings = $n->readSettings(1); - $this->assertNotEmpty($settings); - $this->assertEquals(1, $settings['notifications_enabled']); - $this->assertEquals(NotificationFilter::FILTER_ASSIGNEE, $settings['notifications_filter']); - $this->assertEquals(array(NotificationType::TYPE_EMAIL, NotificationType::TYPE_WEB), $settings['notification_types']); - $this->assertEquals(array(1), $settings['notification_projects']); - } - - public function testGetProjectMembersWithNotifications() - { - $u = new User($this->container); - $p = new Project($this->container); - $n = new Notification($this->container); - $pp = new ProjectPermission($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - - // Email + Notifications enabled - $this->assertNotFalse($u->create(array('username' => 'user1', 'email' => 'user1@here', 'notifications_enabled' => 1))); - - // No email + Notifications enabled - $this->assertNotFalse($u->create(array('username' => 'user2', 'email' => '', 'notifications_enabled' => 1))); - - // Email + Notifications enabled - $this->assertNotFalse($u->create(array('username' => 'user3', 'email' => 'user3@here', 'notifications_enabled' => 1))); - - // No email + notifications disabled - $this->assertNotFalse($u->create(array('username' => 'user4'))); - - // Nobody is member of any projects - $this->assertEmpty($pp->getMembers(1)); - $this->assertEmpty($n->getUsersWithNotificationEnabled(1)); - - // We allow all users to be member of our projects - $this->assertTrue($pp->addMember(1, 1)); - $this->assertTrue($pp->addMember(1, 2)); - $this->assertTrue($pp->addMember(1, 3)); - $this->assertTrue($pp->addMember(1, 4)); - - $this->assertNotEmpty($pp->getMembers(1)); - $users = $n->getUsersWithNotificationEnabled(1); - - $this->assertNotEmpty($users); - $this->assertCount(3, $users); - $this->assertEquals('user1@here', $users[0]['email']); - $this->assertEquals('', $users[1]['email']); - $this->assertEquals('user3@here', $users[2]['email']); - } - - public function testGetUsersWithNotificationsWhenEverybodyAllowed() - { - $u = new User($this->container); - $p = new Project($this->container); - $n = new Notification($this->container); - $pp = new ProjectPermission($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1', 'is_everybody_allowed' => 1))); - $this->assertTrue($pp->isEverybodyAllowed(1)); - - // Email + Notifications enabled - $this->assertNotFalse($u->create(array('username' => 'user1', 'email' => 'user1@here', 'notifications_enabled' => 1))); - - // No email + Notifications enabled - $this->assertNotFalse($u->create(array('username' => 'user2', 'email' => '', 'notifications_enabled' => 1))); - - // Email + Notifications enabled - $this->assertNotFalse($u->create(array('username' => 'user3', 'email' => 'user3@here', 'notifications_enabled' => 1))); - - // No email + notifications disabled - $this->assertNotFalse($u->create(array('username' => 'user4'))); - - $users = $n->getUsersWithNotificationEnabled(1); - - $this->assertNotEmpty($users); - $this->assertCount(3, $users); - $this->assertEquals('user1@here', $users[0]['email']); - $this->assertEquals('', $users[1]['email']); - $this->assertEquals('user3@here', $users[2]['email']); - } - - public function testSendNotifications() - { - $u = new User($this->container); - $n = new Notification($this->container); - $p = new Project($this->container); - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $pp = new ProjectPermission($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1', 'is_everybody_allowed' => 1))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - $this->assertTrue($u->update(array('id' => 1, 'email' => 'test@localhost'))); - $this->assertTrue($pp->isEverybodyAllowed(1)); - - $n->saveSettings(1, array( - 'notifications_enabled' => 1, - 'notifications_filter' => NotificationFilter::FILTER_NONE, - 'notification_types' => array(NotificationType::TYPE_WEB => 1, NotificationType::TYPE_EMAIL => 1), - )); - - $this->container['emailNotification'] = $this - ->getMockBuilder('\Kanboard\Model\EmailNotification') - ->setConstructorArgs(array($this->container)) - ->setMethods(array('send')) - ->getMock(); - - $this->container['webNotification'] = $this - ->getMockBuilder('\Kanboard\Model\WebNotification') - ->setConstructorArgs(array($this->container)) - ->setMethods(array('send')) - ->getMock(); - - $this->container['emailNotification'] - ->expects($this->once()) - ->method('send'); - - $this->container['webNotification'] - ->expects($this->once()) - ->method('send'); - - $n->sendNotifications(Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); - } -} diff --git a/tests/units/Model/NotificationTypeTest.php b/tests/units/Model/NotificationTypeTest.php deleted file mode 100644 index bf3c78a0..00000000 --- a/tests/units/Model/NotificationTypeTest.php +++ /dev/null @@ -1,26 +0,0 @@ -container); - $this->assertEquals(array('email' => 'Email', 'web' => 'Web'), $nt->getTypes()); - } - - public function testGetUserNotificationTypes() - { - $nt = new NotificationType($this->container); - $types = $nt->getUserSelectedTypes(1); - $this->assertEmpty($types); - - $this->assertTrue($nt->saveUserSelectedTypes(1, array('email', 'web'))); - $types = $nt->getUserSelectedTypes(1); - $this->assertNotEmpty($types); - $this->assertEquals(array('email', 'web'), $types); - } -} diff --git a/tests/units/Model/UserNotificationFilterTest.php b/tests/units/Model/UserNotificationFilterTest.php new file mode 100644 index 00000000..0b5f1d98 --- /dev/null +++ b/tests/units/Model/UserNotificationFilterTest.php @@ -0,0 +1,193 @@ +container); + $filters = $nf->getFilters(); + $this->assertArrayHasKey(UserNotificationFilter::FILTER_NONE, $filters); + $this->assertArrayHasKey(UserNotificationFilter::FILTER_BOTH, $filters); + $this->assertArrayHasKey(UserNotificationFilter::FILTER_CREATOR, $filters); + $this->assertArrayHasKey(UserNotificationFilter::FILTER_ASSIGNEE, $filters); + } + + public function testSaveProjectFilter() + { + $nf = new UserNotificationFilter($this->container); + $p = new Project($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); + $this->assertEquals(2, $p->create(array('name' => 'UnitTest2'))); + + $this->assertEmpty($nf->getSelectedProjects(1)); + $nf->saveSelectedProjects(1, array(1, 2)); + $this->assertEquals(array(1, 2), $nf->getSelectedProjects(1)); + } + + public function testSaveUserFilter() + { + $nf = new UserNotificationFilter($this->container); + + $this->assertEquals(UserNotificationFilter::FILTER_BOTH, $nf->getSelectedFilter(1)); + $nf->saveFilter(1, UserNotificationFilter::FILTER_CREATOR); + $this->assertEquals(UserNotificationFilter::FILTER_CREATOR, $nf->getSelectedFilter(1)); + } + + public function testFilterNone() + { + $u = new User($this->container); + $n = new UserNotificationFilter($this->container); + + $this->assertEquals(2, $u->create(array('username' => 'user1', 'notifications_filter' => UserNotificationFilter::FILTER_NONE))); + $this->assertTrue($n->filterNone($u->getById(2), array())); + + $this->assertEquals(3, $u->create(array('username' => 'user2', 'notifications_filter' => UserNotificationFilter::FILTER_BOTH))); + $this->assertFalse($n->filterNone($u->getById(3), array())); + } + + public function testFilterCreator() + { + $u = new User($this->container); + $n = new UserNotificationFilter($this->container); + + $this->assertEquals(2, $u->create(array('username' => 'user1', 'notifications_filter' => UserNotificationFilter::FILTER_CREATOR))); + $this->assertTrue($n->filterCreator($u->getById(2), array('task' => array('creator_id' => 2)))); + + $this->assertEquals(3, $u->create(array('username' => 'user2', 'notifications_filter' => UserNotificationFilter::FILTER_CREATOR))); + $this->assertFalse($n->filterCreator($u->getById(3), array('task' => array('creator_id' => 1)))); + + $this->assertEquals(4, $u->create(array('username' => 'user3', 'notifications_filter' => UserNotificationFilter::FILTER_NONE))); + $this->assertFalse($n->filterCreator($u->getById(4), array('task' => array('creator_id' => 2)))); + } + + public function testFilterAssignee() + { + $u = new User($this->container); + $n = new UserNotificationFilter($this->container); + + $this->assertEquals(2, $u->create(array('username' => 'user1', 'notifications_filter' => UserNotificationFilter::FILTER_ASSIGNEE))); + $this->assertTrue($n->filterAssignee($u->getById(2), array('task' => array('owner_id' => 2)))); + + $this->assertEquals(3, $u->create(array('username' => 'user2', 'notifications_filter' => UserNotificationFilter::FILTER_ASSIGNEE))); + $this->assertFalse($n->filterAssignee($u->getById(3), array('task' => array('owner_id' => 1)))); + + $this->assertEquals(4, $u->create(array('username' => 'user3', 'notifications_filter' => UserNotificationFilter::FILTER_NONE))); + $this->assertFalse($n->filterAssignee($u->getById(4), array('task' => array('owner_id' => 2)))); + } + + public function testFilterBoth() + { + $u = new User($this->container); + $n = new UserNotificationFilter($this->container); + + $this->assertEquals(2, $u->create(array('username' => 'user1', 'notifications_filter' => UserNotificationFilter::FILTER_BOTH))); + $this->assertTrue($n->filterBoth($u->getById(2), array('task' => array('owner_id' => 2, 'creator_id' => 1)))); + $this->assertTrue($n->filterBoth($u->getById(2), array('task' => array('owner_id' => 0, 'creator_id' => 2)))); + + $this->assertEquals(3, $u->create(array('username' => 'user2', 'notifications_filter' => UserNotificationFilter::FILTER_BOTH))); + $this->assertFalse($n->filterBoth($u->getById(3), array('task' => array('owner_id' => 1, 'creator_id' => 1)))); + $this->assertFalse($n->filterBoth($u->getById(3), array('task' => array('owner_id' => 2, 'creator_id' => 1)))); + + $this->assertEquals(4, $u->create(array('username' => 'user3', 'notifications_filter' => UserNotificationFilter::FILTER_NONE))); + $this->assertFalse($n->filterBoth($u->getById(4), array('task' => array('owner_id' => 2, 'creator_id' => 1)))); + } + + public function testFilterProject() + { + $u = new User($this->container); + $n = new UserNotification($this->container); + $nf = new UserNotificationFilter($this->container); + $p = new Project($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); + $this->assertEquals(2, $p->create(array('name' => 'UnitTest2'))); + + // No project selected + $this->assertTrue($nf->filterProject($u->getById(1), array())); + + // User that select only some projects + $this->assertEquals(2, $u->create(array('username' => 'user2', 'notifications_filter' => UserNotificationFilter::FILTER_NONE))); + $n->saveSettings(2, array('notifications_enabled' => 1, 'notification_projects' => array(2 => true))); + + $this->assertFalse($nf->filterProject($u->getById(2), array('task' => array('project_id' => 1)))); + $this->assertTrue($nf->filterProject($u->getById(2), array('task' => array('project_id' => 2)))); + } + + public function testFilterUserWithNoFilter() + { + $u = new User($this->container); + $n = new UserNotificationFilter($this->container); + $p = new Project($this->container); + + $this->assertEquals(2, $u->create(array('username' => 'user2', 'notifications_filter' => UserNotificationFilter::FILTER_NONE))); + + $this->assertTrue($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1)))); + } + + public function testFilterUserWithAssigneeFilter() + { + $u = new User($this->container); + $n = new UserNotificationFilter($this->container); + $p = new Project($this->container); + + $this->assertEquals(2, $u->create(array('username' => 'user2', 'notifications_filter' => UserNotificationFilter::FILTER_ASSIGNEE))); + + $this->assertTrue($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'owner_id' => 2)))); + $this->assertFalse($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'owner_id' => 1)))); + } + + public function testFilterUserWithCreatorFilter() + { + $u = new User($this->container); + $n = new UserNotificationFilter($this->container); + $p = new Project($this->container); + + $this->assertEquals(2, $u->create(array('username' => 'user2', 'notifications_filter' => UserNotificationFilter::FILTER_CREATOR))); + + $this->assertTrue($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 2)))); + $this->assertFalse($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 1)))); + } + + public function testFilterUserWithBothFilter() + { + $u = new User($this->container); + $n = new UserNotificationFilter($this->container); + $p = new Project($this->container); + + $this->assertEquals(2, $u->create(array('username' => 'user2', 'notifications_filter' => UserNotificationFilter::FILTER_BOTH))); + + $this->assertTrue($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 2, 'owner_id' => 3)))); + $this->assertTrue($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 0, 'owner_id' => 2)))); + $this->assertFalse($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 4, 'owner_id' => 1)))); + $this->assertFalse($n->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 5, 'owner_id' => 0)))); + } + + public function testFilterUserWithBothFilterAndProjectSelected() + { + $u = new User($this->container); + $n = new UserNotification($this->container); + $nf = new UserNotificationFilter($this->container); + $p = new Project($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); + $this->assertEquals(2, $p->create(array('name' => 'UnitTest2'))); + + $this->assertEquals(2, $u->create(array('username' => 'user2', 'notifications_filter' => UserNotificationFilter::FILTER_BOTH))); + + $n->saveSettings(2, array('notifications_enabled' => 1, 'notification_projects' => array(2 => true))); + + $this->assertFalse($nf->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 2, 'owner_id' => 3)))); + $this->assertFalse($nf->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 1, 'creator_id' => 0, 'owner_id' => 2)))); + + $this->assertTrue($nf->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 2, 'creator_id' => 2, 'owner_id' => 3)))); + $this->assertTrue($nf->shouldReceiveNotification($u->getById(2), array('task' => array('project_id' => 2, 'creator_id' => 0, 'owner_id' => 2)))); + } +} diff --git a/tests/units/Model/UserNotificationTest.php b/tests/units/Model/UserNotificationTest.php new file mode 100644 index 00000000..8d7dec60 --- /dev/null +++ b/tests/units/Model/UserNotificationTest.php @@ -0,0 +1,198 @@ +container); + $p = new Project($this->container); + $n = new UserNotification($this->container); + $pp = new ProjectPermission($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); + $this->assertEquals(2, $u->create(array('username' => 'user1'))); + $this->assertTrue($pp->addMember(1, 2)); + + $this->assertEmpty($n->getUsersWithNotificationEnabled(1)); + $n->enableNotification(2); + $this->assertNotEmpty($n->getUsersWithNotificationEnabled(1)); + $n->disableNotification(2); + $this->assertEmpty($n->getUsersWithNotificationEnabled(1)); + } + + public function testReadWriteSettings() + { + $n = new UserNotification($this->container); + $p = new Project($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); + + $n->saveSettings(1, array( + 'notifications_enabled' => 1, + 'notifications_filter' => UserNotificationFilter::FILTER_CREATOR, + 'notification_types' => array('email' => 1), + 'notification_projects' => array(), + )); + + $settings = $n->readSettings(1); + $this->assertNotEmpty($settings); + $this->assertEquals(1, $settings['notifications_enabled']); + $this->assertEquals(UserNotificationFilter::FILTER_CREATOR, $settings['notifications_filter']); + $this->assertEquals(array('email'), $settings['notification_types']); + $this->assertEmpty($settings['notification_projects']); + + $n->saveSettings(1, array( + 'notifications_enabled' => 0, + )); + + $settings = $n->readSettings(1); + $this->assertNotEmpty($settings); + $this->assertEquals(0, $settings['notifications_enabled']); + + $n->saveSettings(1, array( + 'notifications_enabled' => 1, + 'notifications_filter' => UserNotificationFilter::FILTER_ASSIGNEE, + 'notification_types' => array('web' => 1, 'email' => 1), + 'notification_projects' => array(1 => 1), + )); + + $settings = $n->readSettings(1); + $this->assertNotEmpty($settings); + $this->assertEquals(1, $settings['notifications_enabled']); + $this->assertEquals(UserNotificationFilter::FILTER_ASSIGNEE, $settings['notifications_filter']); + $this->assertEquals(array('email', 'web'), $settings['notification_types']); + $this->assertEquals(array(1), $settings['notification_projects']); + } + + public function testGetProjectMembersWithNotifications() + { + $u = new User($this->container); + $p = new Project($this->container); + $n = new UserNotification($this->container); + $pp = new ProjectPermission($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); + + // Email + Notifications enabled + $this->assertNotFalse($u->create(array('username' => 'user1', 'email' => 'user1@here', 'notifications_enabled' => 1))); + + // No email + Notifications enabled + $this->assertNotFalse($u->create(array('username' => 'user2', 'email' => '', 'notifications_enabled' => 1))); + + // Email + Notifications enabled + $this->assertNotFalse($u->create(array('username' => 'user3', 'email' => 'user3@here', 'notifications_enabled' => 1))); + + // No email + notifications disabled + $this->assertNotFalse($u->create(array('username' => 'user4'))); + + // Nobody is member of any projects + $this->assertEmpty($pp->getMembers(1)); + $this->assertEmpty($n->getUsersWithNotificationEnabled(1)); + + // We allow all users to be member of our projects + $this->assertTrue($pp->addMember(1, 1)); + $this->assertTrue($pp->addMember(1, 2)); + $this->assertTrue($pp->addMember(1, 3)); + $this->assertTrue($pp->addMember(1, 4)); + + $this->assertNotEmpty($pp->getMembers(1)); + $users = $n->getUsersWithNotificationEnabled(1); + + $this->assertNotEmpty($users); + $this->assertCount(3, $users); + $this->assertEquals('user1@here', $users[0]['email']); + $this->assertEquals('', $users[1]['email']); + $this->assertEquals('user3@here', $users[2]['email']); + } + + public function testGetUsersWithNotificationsWhenEverybodyAllowed() + { + $u = new User($this->container); + $p = new Project($this->container); + $n = new UserNotification($this->container); + $pp = new ProjectPermission($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'UnitTest1', 'is_everybody_allowed' => 1))); + $this->assertTrue($pp->isEverybodyAllowed(1)); + + // Email + Notifications enabled + $this->assertNotFalse($u->create(array('username' => 'user1', 'email' => 'user1@here', 'notifications_enabled' => 1))); + + // No email + Notifications enabled + $this->assertNotFalse($u->create(array('username' => 'user2', 'email' => '', 'notifications_enabled' => 1))); + + // Email + Notifications enabled + $this->assertNotFalse($u->create(array('username' => 'user3', 'email' => 'user3@here', 'notifications_enabled' => 1))); + + // No email + notifications disabled + $this->assertNotFalse($u->create(array('username' => 'user4'))); + + $users = $n->getUsersWithNotificationEnabled(1); + + $this->assertNotEmpty($users); + $this->assertCount(3, $users); + $this->assertEquals('user1@here', $users[0]['email']); + $this->assertEquals('', $users[1]['email']); + $this->assertEquals('user3@here', $users[2]['email']); + } + + public function testSendNotifications() + { + $u = new User($this->container); + $n = new UserNotification($this->container); + $p = new Project($this->container); + $tc = new TaskCreation($this->container); + $tf = new TaskFinder($this->container); + $pp = new ProjectPermission($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'UnitTest1', 'is_everybody_allowed' => 1))); + $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); + $this->assertTrue($u->update(array('id' => 1, 'email' => 'test@localhost'))); + $this->assertTrue($pp->isEverybodyAllowed(1)); + + $n->saveSettings(1, array( + 'notifications_enabled' => 1, + 'notifications_filter' => UserNotificationFilter::FILTER_NONE, + 'notification_types' => array('web' => 1, 'email' => 1), + )); + + $notifier = $this + ->getMockBuilder('Stdclass') + ->setMethods(array('notifyUser')) + ->getMock(); + + $notifier + ->expects($this->exactly(2)) + ->method('notifyUser'); + + $this->container['userNotificationType'] + ->expects($this->at(0)) + ->method('getType') + ->with($this->equalTo('email')) + ->will($this->returnValue($notifier)); + + $this->container['userNotificationType'] + ->expects($this->at(1)) + ->method('getType') + ->with($this->equalTo('web')) + ->will($this->returnValue($notifier)); + + $n->sendNotifications(Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); + } +} diff --git a/tests/units/Model/UserNotificationTypeTest.php b/tests/units/Model/UserNotificationTypeTest.php new file mode 100644 index 00000000..a0a1491d --- /dev/null +++ b/tests/units/Model/UserNotificationTypeTest.php @@ -0,0 +1,30 @@ +container); + $this->assertEmpty($nt->getTypes()); + + $nt->setType('email', 'Email', 'Something'); + $nt->setType('web', 'Web', 'Something'); + $this->assertEquals(array('email' => 'Email', 'web' => 'Web'), $nt->getTypes()); + } + + public function testGetUserNotificationTypes() + { + $nt = new UserNotificationType($this->container); + $types = $nt->getSelectedTypes(1); + $this->assertEmpty($types); + + $this->assertTrue($nt->saveSelectedTypes(1, array('email', 'web'))); + $types = $nt->getSelectedTypes(1); + $this->assertNotEmpty($types); + $this->assertEquals(array('email', 'web'), $types); + } +} diff --git a/tests/units/Model/UserUnreadNotificationTest.php b/tests/units/Model/UserUnreadNotificationTest.php new file mode 100644 index 00000000..130a6eba --- /dev/null +++ b/tests/units/Model/UserUnreadNotificationTest.php @@ -0,0 +1,141 @@ +container); + $p = new Project($this->container); + $tf = new TaskFinder($this->container); + $tc = new TaskCreation($this->container); + $s = new Subtask($this->container); + $c = new Comment($this->container); + $f = new File($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'test'))); + $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $s->create(array('title' => 'test', 'task_id' => 1))); + $this->assertEquals(1, $c->create(array('comment' => 'test', 'task_id' => 1, 'user_id' => 1))); + $this->assertEquals(1, $f->create(1, 'test', 'blah', 123)); + + $task = $tf->getDetails(1); + $subtask = $s->getById(1, true); + $comment = $c->getById(1); + $file = $c->getById(1); + + $this->assertNotEmpty($task); + $this->assertNotEmpty($subtask); + $this->assertNotEmpty($comment); + $this->assertNotEmpty($file); + + foreach (NotificationSubscriber::getSubscribedEvents() as $event_name => $values) { + $title = $wn->getTitleFromEvent($event_name, array( + 'task' => $task, + 'comment' => $comment, + 'subtask' => $subtask, + 'file' => $file, + 'changes' => array() + )); + + $this->assertNotEmpty($title); + } + + $this->assertNotEmpty($wn->getTitleFromEvent(Task::EVENT_OVERDUE, array('tasks' => array(array('id' => 1))))); + $this->assertNotEmpty($wn->getTitleFromEvent('unkown', array())); + } + + public function testHasNotification() + { + $wn = new UserUnreadNotification($this->container); + $p = new Project($this->container); + $tf = new TaskFinder($this->container); + $tc = new TaskCreation($this->container); + $u = new User($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'test'))); + $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); + + $this->assertFalse($wn->hasNotifications(1)); + + $wn->create(1, Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); + + $this->assertTrue($wn->hasNotifications(1)); + } + + public function testMarkAllAsRead() + { + $wn = new UserUnreadNotification($this->container); + $p = new Project($this->container); + $tf = new TaskFinder($this->container); + $tc = new TaskCreation($this->container); + $u = new User($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'test'))); + $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); + + $wn->create(1, Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); + + $this->assertTrue($wn->hasNotifications(1)); + $this->assertTrue($wn->markAllAsRead(1)); + + $this->assertFalse($wn->hasNotifications(1)); + $this->assertFalse($wn->markAllAsRead(1)); + } + + public function testMarkAsRead() + { + $wn = new UserUnreadNotification($this->container); + $p = new Project($this->container); + $tf = new TaskFinder($this->container); + $tc = new TaskCreation($this->container); + $u = new User($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'test'))); + $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); + + $wn->create(1, Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); + + $this->assertTrue($wn->hasNotifications(1)); + + $this->assertFalse($wn->markAsRead(2, 1)); + $this->assertTrue($wn->markAsRead(1, 1)); + + $this->assertFalse($wn->hasNotifications(1)); + $this->assertFalse($wn->markAsRead(1, 1)); + } + + public function testGetAll() + { + $wn = new UserUnreadNotification($this->container); + $p = new Project($this->container); + $tf = new TaskFinder($this->container); + $tc = new TaskCreation($this->container); + $u = new User($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'test'))); + $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); + + $wn->create(1, Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); + $wn->create(1, Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); + + $this->assertEmpty($wn->getAll(2)); + + $notifications = $wn->getAll(1); + $this->assertCount(2, $notifications); + $this->assertArrayHasKey('title', $notifications[0]); + $this->assertTrue(is_array($notifications[0]['event_data'])); + } +} diff --git a/tests/units/Model/WebNotificationTest.php b/tests/units/Model/WebNotificationTest.php deleted file mode 100644 index 8ed37692..00000000 --- a/tests/units/Model/WebNotificationTest.php +++ /dev/null @@ -1,141 +0,0 @@ -container); - $p = new Project($this->container); - $tf = new TaskFinder($this->container); - $tc = new TaskCreation($this->container); - $s = new Subtask($this->container); - $c = new Comment($this->container); - $f = new File($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'test', 'task_id' => 1))); - $this->assertEquals(1, $c->create(array('comment' => 'test', 'task_id' => 1, 'user_id' => 1))); - $this->assertEquals(1, $f->create(1, 'test', 'blah', 123)); - - $task = $tf->getDetails(1); - $subtask = $s->getById(1, true); - $comment = $c->getById(1); - $file = $c->getById(1); - - $this->assertNotEmpty($task); - $this->assertNotEmpty($subtask); - $this->assertNotEmpty($comment); - $this->assertNotEmpty($file); - - foreach (NotificationSubscriber::getSubscribedEvents() as $event_name => $values) { - $title = $wn->getTitleFromEvent($event_name, array( - 'task' => $task, - 'comment' => $comment, - 'subtask' => $subtask, - 'file' => $file, - 'changes' => array() - )); - - $this->assertNotEmpty($title); - } - - $this->assertNotEmpty($wn->getTitleFromEvent(Task::EVENT_OVERDUE, array('tasks' => array(array('id' => 1))))); - $this->assertNotEmpty($wn->getTitleFromEvent('unkown', array())); - } - - public function testHasNotification() - { - $wn = new WebNotification($this->container); - $p = new Project($this->container); - $tf = new TaskFinder($this->container); - $tc = new TaskCreation($this->container); - $u = new User($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - - $this->assertFalse($wn->hasNotifications(1)); - - $wn->send($u->getById(1), Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); - - $this->assertTrue($wn->hasNotifications(1)); - } - - public function testMarkAllAsRead() - { - $wn = new WebNotification($this->container); - $p = new Project($this->container); - $tf = new TaskFinder($this->container); - $tc = new TaskCreation($this->container); - $u = new User($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - - $wn->send($u->getById(1), Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); - - $this->assertTrue($wn->hasNotifications(1)); - $this->assertTrue($wn->markAllAsRead(1)); - - $this->assertFalse($wn->hasNotifications(1)); - $this->assertFalse($wn->markAllAsRead(1)); - } - - public function testMarkAsRead() - { - $wn = new WebNotification($this->container); - $p = new Project($this->container); - $tf = new TaskFinder($this->container); - $tc = new TaskCreation($this->container); - $u = new User($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - - $wn->send($u->getById(1), Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); - - $this->assertTrue($wn->hasNotifications(1)); - - $this->assertFalse($wn->markAsRead(2, 1)); - $this->assertTrue($wn->markAsRead(1, 1)); - - $this->assertFalse($wn->hasNotifications(1)); - $this->assertFalse($wn->markAsRead(1, 1)); - } - - public function testGetAll() - { - $wn = new WebNotification($this->container); - $p = new Project($this->container); - $tf = new TaskFinder($this->container); - $tc = new TaskCreation($this->container); - $u = new User($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - - $wn->send($u->getById(1), Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); - $wn->send($u->getById(1), Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); - - $this->assertEmpty($wn->getAll(2)); - - $notifications = $wn->getAll(1); - $this->assertCount(2, $notifications); - $this->assertArrayHasKey('title', $notifications[0]); - $this->assertTrue(is_array($notifications[0]['event_data'])); - } -} diff --git a/tests/units/Notification/MailTest.php b/tests/units/Notification/MailTest.php new file mode 100644 index 00000000..3aa1a39c --- /dev/null +++ b/tests/units/Notification/MailTest.php @@ -0,0 +1,118 @@ +container); + $p = new Project($this->container); + $tf = new TaskFinder($this->container); + $tc = new TaskCreation($this->container); + $s = new Subtask($this->container); + $c = new Comment($this->container); + $f = new File($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'test'))); + $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $s->create(array('title' => 'test', 'task_id' => 1))); + $this->assertEquals(1, $c->create(array('comment' => 'test', 'task_id' => 1, 'user_id' => 1))); + $this->assertEquals(1, $f->create(1, 'test', 'blah', 123)); + + $task = $tf->getDetails(1); + $subtask = $s->getById(1, true); + $comment = $c->getById(1); + $file = $c->getById(1); + + $this->assertNotEmpty($task); + $this->assertNotEmpty($subtask); + $this->assertNotEmpty($comment); + $this->assertNotEmpty($file); + + foreach (NotificationSubscriber::getSubscribedEvents() as $event => $values) { + $this->assertNotEmpty($en->getMailContent($event, array( + 'task' => $task, + 'comment' => $comment, + 'subtask' => $subtask, + 'file' => $file, + 'changes' => array()) + )); + + $this->assertNotEmpty($en->getMailSubject($event, array( + 'task' => $task, + 'comment' => $comment, + 'subtask' => $subtask, + 'file' => $file, + 'changes' => array()) + )); + } + } + + public function testSendWithEmailAddress() + { + $en = new Mail($this->container); + $p = new Project($this->container); + $tf = new TaskFinder($this->container); + $tc = new TaskCreation($this->container); + $u = new User($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'test'))); + $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); + $this->assertTrue($u->update(array('id' => 1, 'email' => 'test@localhost'))); + + $this->container['emailClient'] = $this + ->getMockBuilder('\Kanboard\Core\Mail\Client') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('send')) + ->getMock(); + + $this->container['emailClient'] + ->expects($this->once()) + ->method('send') + ->with( + $this->equalTo('test@localhost'), + $this->equalTo('admin'), + $this->equalTo('[test][New task] test (#1)'), + $this->stringContains('test') + ); + + $en->notifyUser($u->getById(1), Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); + } + + public function testSendWithoutEmailAddress() + { + $en = new Mail($this->container); + $p = new Project($this->container); + $tf = new TaskFinder($this->container); + $tc = new TaskCreation($this->container); + $u = new User($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'test'))); + $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); + + $this->container['emailClient'] = $this + ->getMockBuilder('\Kanboard\Core\Mail\Client') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('send')) + ->getMock(); + + $this->container['emailClient'] + ->expects($this->never()) + ->method('send'); + + $en->notifyUser($u->getById(1), Task::EVENT_CREATE, array('task' => $tf->getDetails(1))); + } +} -- cgit v1.2.3