From e9fedf3e5cd63aea4da7a71f6647ee427c62fa49 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 5 Dec 2015 20:31:27 -0500 Subject: Rewrite of the authentication and authorization system --- app/Model/ProjectUserRole.php | 263 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 app/Model/ProjectUserRole.php (limited to 'app/Model/ProjectUserRole.php') diff --git a/app/Model/ProjectUserRole.php b/app/Model/ProjectUserRole.php new file mode 100644 index 00000000..28e6c8c6 --- /dev/null +++ b/app/Model/ProjectUserRole.php @@ -0,0 +1,263 @@ +db + ->hashtable(Project::TABLE) + ->beginOr() + ->eq(self::TABLE.'.user_id', $user_id) + ->eq(Project::TABLE.'.is_everybody_allowed', 1) + ->closeOr() + ->in(Project::TABLE.'.is_active', $status) + ->join(self::TABLE, 'project_id', 'id') + ->getAll(Project::TABLE.'.id', Project::TABLE.'.name'); + + $groupProjects = $this->projectGroupRole->getProjectsByUser($user_id, $status); + $groups = $userProjects + $groupProjects; + + asort($groups); + + return $groups; + } + + /** + * For a given project get the role of the specified user + * + * @access public + * @param integer $project_id + * @param integer $user_id + * @return string + */ + public function getUserRole($project_id, $user_id) + { + if ($this->projectPermission->isEverybodyAllowed($project_id)) { + return Role::PROJECT_MEMBER; + } + + $role = $this->db->table(self::TABLE)->eq('user_id', $user_id)->eq('project_id', $project_id)->findOneColumn('role'); + + if (empty($role)) { + $role = $this->projectGroupRole->getUserRole($project_id, $user_id); + } + + return $role; + } + + /** + * Get all users associated directly to the project + * + * @access public + * @param integer $project_id + * @return array + */ + public function getUsers($project_id) + { + return $this->db->table(self::TABLE) + ->columns(User::TABLE.'.id', User::TABLE.'.username', User::TABLE.'.name', self::TABLE.'.role') + ->join(User::TABLE, 'id', 'user_id') + ->eq('project_id', $project_id) + ->asc(User::TABLE.'.username') + ->asc(User::TABLE.'.name') + ->findAll(); + } + + /** + * Get all users (fetch users from groups) + * + * @access public + * @param integer $project_id + * @return array + */ + public function getAllUsers($project_id) + { + $userMembers = $this->getUsers($project_id); + $groupMembers = $this->projectGroupRole->getUsers($project_id); + $members = array_merge($userMembers, $groupMembers); + + return $this->user->prepareList($members); + } + + /** + * Get users grouped by role + * + * @access public + * @param integer $project_id Project id + * @return array + */ + public function getAllUsersGroupedByRole($project_id) + { + $users = array(); + + $userMembers = $this->getUsers($project_id); + $groupMembers = $this->projectGroupRole->getUsers($project_id); + $members = array_merge($userMembers, $groupMembers); + + foreach ($members as $user) { + if (! isset($users[$user['role']])) { + $users[$user['role']] = array(); + } + + $users[$user['role']][$user['id']] = $user['name'] ?: $user['username']; + } + + return $users; + } + + /** + * Get list of users that can be assigned to a task (only Manager and Member) + * + * @access public + * @param integer $project_id + * @return array + */ + public function getAssignableUsers($project_id) + { + if ($this->projectPermission->isEverybodyAllowed($project_id)) { + return $this->user->getList(); + } + + $userMembers = $this->db->table(self::TABLE) + ->columns(User::TABLE.'.id', User::TABLE.'.username', User::TABLE.'.name') + ->join(User::TABLE, 'id', 'user_id') + ->eq('project_id', $project_id) + ->in(self::TABLE.'.role', array(Role::PROJECT_MANAGER, Role::PROJECT_MEMBER)) + ->findAll(); + + $groupMembers = $this->projectGroupRole->getAssignableUsers($project_id); + $members = array_merge($userMembers, $groupMembers); + + return $this->user->prepareList($members); + } + + /** + * Get list of users that can be assigned to a task (only Manager and Member) + * + * @access public + * @param integer $project_id Project id + * @param bool $unassigned Prepend the 'Unassigned' value + * @param bool $everybody Prepend the 'Everbody' value + * @param bool $singleUser If there is only one user return only this user + * @return array + */ + public function getAssignableUsersList($project_id, $unassigned = true, $everybody = false, $singleUser = false) + { + $users = $this->getAssignableUsers($project_id); + + if ($singleUser && count($users) === 1) { + return $users; + } + + if ($unassigned) { + $users = array(t('Unassigned')) + $users; + } + + if ($everybody) { + $users = array(User::EVERYBODY_ID => t('Everybody')) + $users; + } + + return $users; + } + + /** + * Add a user to the project + * + * @access public + * @param integer $project_id + * @param integer $user_id + * @param string $role + * @return boolean + */ + public function addUser($project_id, $user_id, $role) + { + return $this->db->table(self::TABLE)->insert(array( + 'user_id' => $user_id, + 'project_id' => $project_id, + 'role' => $role, + )); + } + + /** + * Remove a user from the project + * + * @access public + * @param integer $project_id + * @param integer $user_id + * @return boolean + */ + public function removeUser($project_id, $user_id) + { + return $this->db->table(self::TABLE)->eq('user_id', $user_id)->eq('project_id', $project_id)->remove(); + } + + /** + * Change a user role for the project + * + * @access public + * @param integer $project_id + * @param integer $user_id + * @param string $role + * @return boolean + */ + public function changeUserRole($project_id, $user_id, $role) + { + return $this->db->table(self::TABLE) + ->eq('user_id', $user_id) + ->eq('project_id', $project_id) + ->update(array( + 'role' => $role, + )); + } + + /** + * Copy user access from a project to another one + * + * @param integer $project_src_id Project Template + * @return integer $project_dst_id Project that receives the copy + * @return boolean + */ + public function duplicate($project_src_id, $project_dst_id) + { + $rows = $this->db->table(self::TABLE)->eq('project_id', $project_src_id)->findAll(); + + foreach ($rows as $row) { + $result = $this->db->table(self::TABLE)->save(array( + 'project_id' => $project_dst_id, + 'user_id' => $row['user_id'], + 'role' => $row['role'], + )); + + if (! $result) { + return false; + } + } + + return true; + } +} -- cgit v1.2.3 From c83f589b22cd548c6de10bfb0c18f767ba7dffd8 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Thu, 17 Dec 2015 21:38:13 -0500 Subject: Show only active projects in board selector --- app/Controller/Activity.php | 2 +- app/Controller/Analytic.php | 2 +- app/Controller/App.php | 2 +- app/Controller/Base.php | 6 +++--- app/Controller/Config.php | 2 +- app/Controller/Currency.php | 2 +- app/Controller/Doc.php | 2 +- app/Controller/Gantt.php | 2 +- app/Controller/Group.php | 10 +++++----- app/Controller/Link.php | 2 +- app/Controller/Project.php | 4 ++-- app/Controller/Projectuser.php | 2 +- app/Controller/User.php | 8 ++++---- app/Model/ProjectPermission.php | 2 +- app/Model/ProjectUserRole.php | 14 +++++++++++++- 15 files changed, 37 insertions(+), 25 deletions(-) (limited to 'app/Model/ProjectUserRole.php') diff --git a/app/Controller/Activity.php b/app/Controller/Activity.php index 71d5e94f..38658345 100644 --- a/app/Controller/Activity.php +++ b/app/Controller/Activity.php @@ -20,7 +20,7 @@ class Activity extends Base $project = $this->getProject(); $this->response->html($this->template->layout('activity/project', array( - 'board_selector' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), 'events' => $this->projectActivity->getProject($project['id']), 'project' => $project, 'title' => t('%s\'s activity', $project['name']) diff --git a/app/Controller/Analytic.php b/app/Controller/Analytic.php index bebb13fa..b2e27c58 100644 --- a/app/Controller/Analytic.php +++ b/app/Controller/Analytic.php @@ -21,7 +21,7 @@ class Analytic extends Base */ private function layout($template, array $params) { - $params['board_selector'] = $this->projectUserRole->getProjectsByUser($this->userSession->getId()); + $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); $params['content_for_sublayout'] = $this->template->render($template, $params); return $this->template->layout('analytic/layout', $params); diff --git a/app/Controller/App.php b/app/Controller/App.php index c596b4a8..bdd7fbcf 100644 --- a/app/Controller/App.php +++ b/app/Controller/App.php @@ -22,7 +22,7 @@ class App extends Base */ private function layout($template, array $params) { - $params['board_selector'] = $this->projectUserRole->getProjectsByUser($this->userSession->getId()); + $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); $params['content_for_sublayout'] = $this->template->render($template, $params); return $this->template->layout('app/layout', $params); diff --git a/app/Controller/Base.php b/app/Controller/Base.php index 35ceee09..6d0ecae9 100644 --- a/app/Controller/Base.php +++ b/app/Controller/Base.php @@ -190,7 +190,7 @@ abstract class Base extends \Kanboard\Core\Base $content = $this->template->render($template, $params); $params['task_content_for_layout'] = $content; $params['title'] = $params['task']['project_name'].' > '.$params['task']['title']; - $params['board_selector'] = $this->projectUserRole->getProjectsByUser($this->userSession->getId()); + $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); return $this->template->layout('task/layout', $params); } @@ -208,7 +208,7 @@ abstract class Base extends \Kanboard\Core\Base $content = $this->template->render($template, $params); $params['project_content_for_layout'] = $content; $params['title'] = $params['project']['name'] === $params['title'] ? $params['title'] : $params['project']['name'].' > '.$params['title']; - $params['board_selector'] = $this->projectUserRole->getProjectsByUser($this->userSession->getId()); + $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); $params['sidebar_template'] = $sidebar_template; return $this->template->layout('project/layout', $params); @@ -289,7 +289,7 @@ abstract class Base extends \Kanboard\Core\Base { $project = $this->getProject(); $search = $this->request->getStringParam('search', $this->userSession->getFilters($project['id'])); - $board_selector = $this->projectUserRole->getProjectsByUser($this->userSession->getId()); + $board_selector = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); unset($board_selector[$project['id']]); $filters = array( diff --git a/app/Controller/Config.php b/app/Controller/Config.php index c813c795..c7097da3 100644 --- a/app/Controller/Config.php +++ b/app/Controller/Config.php @@ -20,7 +20,7 @@ class Config extends Base */ private function layout($template, array $params) { - $params['board_selector'] = $this->projectUserRole->getProjectsByUser($this->userSession->getId()); + $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); $params['values'] = $this->config->getAll(); $params['errors'] = array(); $params['config_content_for_layout'] = $this->template->render($template, $params); diff --git a/app/Controller/Currency.php b/app/Controller/Currency.php index 89e38569..4c5b8ee8 100644 --- a/app/Controller/Currency.php +++ b/app/Controller/Currency.php @@ -20,7 +20,7 @@ class Currency extends Base */ private function layout($template, array $params) { - $params['board_selector'] = $this->projectUserRole->getProjectsByUser($this->userSession->getId()); + $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); $params['config_content_for_layout'] = $this->template->render($template, $params); return $this->template->layout('config/layout', $params); diff --git a/app/Controller/Doc.php b/app/Controller/Doc.php index 08561aa1..a233b120 100644 --- a/app/Controller/Doc.php +++ b/app/Controller/Doc.php @@ -53,7 +53,7 @@ class Doc extends Base } $this->response->html($this->template->layout('doc/show', $this->readFile($filename) + array( - 'board_selector' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), ))); } } diff --git a/app/Controller/Gantt.php b/app/Controller/Gantt.php index f3954a25..ac0e6fad 100644 --- a/app/Controller/Gantt.php +++ b/app/Controller/Gantt.php @@ -26,7 +26,7 @@ class Gantt extends Base $this->response->html($this->template->layout('gantt/projects', array( 'projects' => $this->projectGanttFormatter->filter($project_ids)->format(), 'title' => t('Gantt chart for all projects'), - 'board_selector' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), ))); } diff --git a/app/Controller/Group.php b/app/Controller/Group.php index 3e6505e9..3c9c4a07 100644 --- a/app/Controller/Group.php +++ b/app/Controller/Group.php @@ -25,7 +25,7 @@ class Group extends Base ->calculate(); $this->response->html($this->template->layout('group/index', array( - 'board_selector' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), 'title' => t('Groups').' ('.$paginator->getTotal().')', 'paginator' => $paginator, ))); @@ -49,7 +49,7 @@ class Group extends Base ->calculate(); $this->response->html($this->template->layout('group/users', array( - 'board_selector' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), 'title' => t('Members of %s', $group['name']).' ('.$paginator->getTotal().')', 'paginator' => $paginator, 'group' => $group, @@ -64,7 +64,7 @@ class Group extends Base public function create(array $values = array(), array $errors = array()) { $this->response->html($this->template->layout('group/create', array( - 'board_selector' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), 'errors' => $errors, 'values' => $values, 'title' => t('New group') @@ -105,7 +105,7 @@ class Group extends Base } $this->response->html($this->template->layout('group/edit', array( - 'board_selector' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), 'errors' => $errors, 'values' => $values, 'title' => t('Edit group') @@ -149,7 +149,7 @@ class Group extends Base } $this->response->html($this->template->layout('group/associate', array( - 'board_selector' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), 'users' => $this->user->prepareList($this->groupMember->getNotMembers($group_id)), 'group' => $group, 'errors' => $errors, diff --git a/app/Controller/Link.php b/app/Controller/Link.php index 33ec6688..2ae57b1a 100644 --- a/app/Controller/Link.php +++ b/app/Controller/Link.php @@ -21,7 +21,7 @@ class Link extends Base */ private function layout($template, array $params) { - $params['board_selector'] = $this->projectUserRole->getProjectsByUser($this->userSession->getId()); + $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); $params['config_content_for_layout'] = $this->template->render($template, $params); return $this->template->layout('config/layout', $params); diff --git a/app/Controller/Project.php b/app/Controller/Project.php index 80c95aa2..5e75db4e 100644 --- a/app/Controller/Project.php +++ b/app/Controller/Project.php @@ -33,7 +33,7 @@ class Project extends Base ->calculate(); $this->response->html($this->template->layout('project/index', array( - 'board_selector' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), 'paginator' => $paginator, 'nb_projects' => $nb_projects, 'title' => t('Projects').' ('.$nb_projects.')' @@ -302,7 +302,7 @@ class Project extends Base $is_private = isset($values['is_private']) && $values['is_private'] == 1; $this->response->html($this->template->layout('project/new', array( - 'board_selector' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), 'values' => $values, 'errors' => $errors, 'is_private' => $is_private, diff --git a/app/Controller/Projectuser.php b/app/Controller/Projectuser.php index 34595764..806ede77 100644 --- a/app/Controller/Projectuser.php +++ b/app/Controller/Projectuser.php @@ -24,7 +24,7 @@ class Projectuser extends Base */ private function layout($template, array $params) { - $params['board_selector'] = $this->projectUserRole->getProjectsByUser($this->userSession->getId()); + $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); $params['content_for_sublayout'] = $this->template->render($template, $params); $params['filter'] = array('user_id' => $params['user_id']); diff --git a/app/Controller/User.php b/app/Controller/User.php index 0968d5a5..8b6df44c 100644 --- a/app/Controller/User.php +++ b/app/Controller/User.php @@ -26,7 +26,7 @@ class User extends Base { $content = $this->template->render($template, $params); $params['user_content_for_layout'] = $content; - $params['board_selector'] = $this->projectUserRole->getProjectsByUser($this->userSession->getId()); + $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); if (isset($params['user'])) { $params['title'] = ($params['user']['name'] ?: $params['user']['username']).' (#'.$params['user']['id'].')'; @@ -51,7 +51,7 @@ class User extends Base $this->response->html( $this->template->layout('user/index', array( - 'board_selector' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), 'title' => t('Users').' ('.$paginator->getTotal().')', 'paginator' => $paginator, ))); @@ -72,7 +72,7 @@ class User extends Base $this->response->html( $this->template->layout('user/profile', array( - 'board_selector' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), 'title' => $user['name'] ?: $user['username'], 'user' => $user, ) @@ -92,7 +92,7 @@ class User extends Base 'timezones' => $this->config->getTimezones(true), 'languages' => $this->config->getLanguages(true), 'roles' => $this->role->getApplicationRoles(), - 'board_selector' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), 'projects' => $this->project->getList(), 'errors' => $errors, 'values' => $values + array('role' => Role::APP_USER), diff --git a/app/Model/ProjectPermission.php b/app/Model/ProjectPermission.php index f74b8587..4ad9bbf1 100644 --- a/app/Model/ProjectPermission.php +++ b/app/Model/ProjectPermission.php @@ -100,7 +100,7 @@ class ProjectPermission extends Base */ public function getActiveProjectIds($user_id) { - return array_keys($this->projectUserRole->getProjectsByUser($user_id, array(Project::ACTIVE))); + return array_keys($this->projectUserRole->getActiveProjectsByUser($user_id)); } /** diff --git a/app/Model/ProjectUserRole.php b/app/Model/ProjectUserRole.php index 28e6c8c6..b2c38622 100644 --- a/app/Model/ProjectUserRole.php +++ b/app/Model/ProjectUserRole.php @@ -20,7 +20,19 @@ class ProjectUserRole extends Base const TABLE = 'project_has_users'; /** - * Get the list of project visible by the given user + * Get the list of active project for the given user + * + * @access public + * @param integer $user_id + * @return array + */ + public function getActiveProjectsByUser($user_id) + { + return $this->getProjectsByUser($user_id, $status = array(Project::ACTIVE)); + } + + /** + * Get the list of project visible for the given user * * @access public * @param integer $user_id -- cgit v1.2.3 From a296ba5b18487d312acca2513d461a210a460fae Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 3 Jan 2016 16:43:13 -0500 Subject: Improve Automatic Actions plugin api --- ChangeLog | 27 +- app/Action/Base.php | 118 ++-- app/Action/CommentCreation.php | 17 +- app/Action/CommentCreationMoveTaskColumn.php | 94 +++ app/Action/TaskAssignCategoryColor.php | 11 + app/Action/TaskAssignCategoryLabel.php | 15 +- app/Action/TaskAssignCategoryLink.php | 13 +- app/Action/TaskAssignColorCategory.php | 11 + app/Action/TaskAssignColorColumn.php | 11 + app/Action/TaskAssignColorLink.php | 11 + app/Action/TaskAssignColorUser.php | 11 + app/Action/TaskAssignCurrentUser.php | 19 +- app/Action/TaskAssignCurrentUserColumn.php | 98 +++ app/Action/TaskAssignSpecificUser.php | 11 + app/Action/TaskAssignUser.php | 13 +- app/Action/TaskClose.php | 48 +- app/Action/TaskCloseColumn.php | 84 +++ app/Action/TaskCreation.php | 11 + app/Action/TaskDuplicateAnotherProject.php | 13 +- app/Action/TaskEmail.php | 11 + app/Action/TaskLogMoveAnotherColumn.php | 83 --- app/Action/TaskMoveAnotherProject.php | 11 + app/Action/TaskMoveColumnAssigned.php | 12 +- app/Action/TaskMoveColumnCategoryChange.php | 15 +- app/Action/TaskMoveColumnUnAssigned.php | 12 +- app/Action/TaskOpen.php | 11 + app/Action/TaskUpdateStartDate.php | 11 + app/Api/Action.php | 28 +- app/Controller/Action.php | 21 +- app/Core/Action/ActionManager.php | 141 +++++ app/Core/Base.php | 3 + app/Core/Event/EventManager.php | 83 +++ app/Core/Mail/Client.php | 20 +- app/Integration/BitbucketWebhook.php | 2 +- app/Integration/GithubWebhook.php | 2 +- app/Integration/GitlabWebhook.php | 2 +- app/Model/Action.php | 301 +-------- app/Model/ActionParameter.php | 122 ++++ app/Model/Comment.php | 1 + app/Model/ProjectUserRole.php | 6 +- app/Schema/Sqlite.php | 25 +- app/ServiceProvider/ActionProvider.php | 78 +++ app/ServiceProvider/ClassProvider.php | 4 + app/ServiceProvider/EventDispatcherProvider.php | 3 - app/Subscriber/BootstrapSubscriber.php | 13 +- app/Template/action/index.php | 30 +- app/common.php | 1 + doc/api-action-procedures.markdown | 42 +- doc/automatic-actions.markdown | 66 +- doc/plugin-registration.markdown | 37 -- tests/functionals/ApiTest.php | 6 +- tests/units/Action/BaseActionTest.php | 144 +++++ .../Action/CommentCreationMoveTaskColumnTest.php | 58 ++ tests/units/Action/CommentCreationTest.php | 165 ++--- tests/units/Action/TaskAssignCategoryColorTest.php | 60 ++ tests/units/Action/TaskAssignCategoryLabelTest.php | 85 +++ tests/units/Action/TaskAssignCategoryLinkTest.php | 32 +- tests/units/Action/TaskAssignColorCategoryTest.php | 90 +-- tests/units/Action/TaskAssignColorColumnTest.php | 55 +- tests/units/Action/TaskAssignColorLinkTest.php | 67 +- tests/units/Action/TaskAssignColorUserTest.php | 78 +-- .../Action/TaskAssignCurrentUserColumnTest.php | 75 +++ tests/units/Action/TaskAssignCurrentUserTest.php | 74 +-- tests/units/Action/TaskAssignSpecificUserTest.php | 72 +-- tests/units/Action/TaskAssignUserTest.php | 62 ++ tests/units/Action/TaskCloseColumnTest.php | 53 ++ tests/units/Action/TaskCloseTest.php | 106 +--- tests/units/Action/TaskCreationTest.php | 49 ++ .../Action/TaskDuplicateAnotherProjectTest.php | 95 +-- tests/units/Action/TaskEmailTest.php | 133 +--- tests/units/Action/TaskMoveAnotherProjectTest.php | 90 +-- tests/units/Action/TaskMoveColumnAssignedTest.php | 56 ++ .../Action/TaskMoveColumnCategoryChangeTest.php | 108 ++-- .../units/Action/TaskMoveColumnUnAssignedTest.php | 74 +++ tests/units/Action/TaskOpenTest.php | 51 ++ tests/units/Action/TaskUpdateStartDateTest.php | 54 +- tests/units/Core/Action/ActionManagerTest.php | 157 +++++ tests/units/Core/Event/EventManagerTest.php | 18 + tests/units/Integration/BitbucketWebhookTest.php | 2 +- tests/units/Integration/GithubWebhookTest.php | 2 +- tests/units/Integration/GitlabWebhookTest.php | 2 +- tests/units/Model/ActionTest.php | 698 ++++++++++++--------- tests/units/Model/ProjectDuplicationTest.php | 6 +- 83 files changed, 3028 insertions(+), 1682 deletions(-) create mode 100644 app/Action/CommentCreationMoveTaskColumn.php create mode 100644 app/Action/TaskAssignCurrentUserColumn.php create mode 100644 app/Action/TaskCloseColumn.php delete mode 100644 app/Action/TaskLogMoveAnotherColumn.php create mode 100644 app/Core/Action/ActionManager.php create mode 100644 app/Core/Event/EventManager.php create mode 100644 app/Model/ActionParameter.php create mode 100644 app/ServiceProvider/ActionProvider.php create mode 100644 tests/units/Action/BaseActionTest.php create mode 100644 tests/units/Action/CommentCreationMoveTaskColumnTest.php create mode 100644 tests/units/Action/TaskAssignCategoryColorTest.php create mode 100644 tests/units/Action/TaskAssignCategoryLabelTest.php create mode 100644 tests/units/Action/TaskAssignCurrentUserColumnTest.php create mode 100644 tests/units/Action/TaskAssignUserTest.php create mode 100644 tests/units/Action/TaskCloseColumnTest.php create mode 100644 tests/units/Action/TaskCreationTest.php create mode 100644 tests/units/Action/TaskMoveColumnAssignedTest.php create mode 100644 tests/units/Action/TaskMoveColumnUnAssignedTest.php create mode 100644 tests/units/Action/TaskOpenTest.php create mode 100644 tests/units/Core/Action/ActionManagerTest.php create mode 100644 tests/units/Core/Event/EventManagerTest.php (limited to 'app/Model/ProjectUserRole.php') diff --git a/ChangeLog b/ChangeLog index 3b261700..54518b34 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,24 +1,31 @@ Version 1.0.23 (unreleased) --------------------------- +Breaking changes: + +* Plugin API changes for Automatic Actions +* Automatic Action to close a task doesn't have the column parameter anymore (use the action "Close a task in a specific column") +* Action name stored in the database is now the absolute class name + New features: -- Added support of user mentions (@username) -- Added report to compare working hours between open and closed tasks -- Added the possiblity to define custom routes from plugins -- Added new method to remove metadata +* Added support of user mentions (@username) +* Added report to compare working hours between open and closed tasks +* Added the possiblity to define custom routes from plugins +* Added new method to remove metadata Improvements: -- Improving performance during task position change (SQL queries are 3 times faster than before) -- Do not show window scrollbars when individual column scrolling is enabled +* Improving performance during task position change (SQL queries are 3 times faster than before) +* Do not show window scrollbars when individual column scrolling is enabled +* Automatic Actions code improvements and unit tests Bug fixes: -- Fix compatiblity issue with FreeBSD for session.hash_function parameter -- Fix wrong constant name that cause a PHP error in project management section -- Fix pagination in group members listing -- Avoid PHP error when enabling LDAP group provider with PHP < 5.5 +* Fix compatiblity issue with FreeBSD for session.hash_function parameter +* Fix wrong constant name that cause a PHP error in project management section +* Fix pagination in group members listing +* Avoid PHP error when enabling LDAP group provider with PHP < 5.5 Version 1.0.22 -------------- diff --git a/app/Action/Base.php b/app/Action/Base.php index 81e2ccc6..febd6cfc 100644 --- a/app/Action/Base.php +++ b/app/Action/Base.php @@ -3,7 +3,6 @@ namespace Kanboard\Action; use Kanboard\Event\GenericEvent; -use Pimple\Container; /** * Base class for automatic actions @@ -13,6 +12,14 @@ use Pimple\Container; */ abstract class Base extends \Kanboard\Core\Base { + /** + * Extended events + * + * @access private + * @var array + */ + private $compatibleEvents = array(); + /** * Flag for called listener * @@ -27,7 +34,7 @@ abstract class Base extends \Kanboard\Core\Base * @access private * @var integer */ - private $project_id = 0; + private $projectId = 0; /** * User parameters @@ -38,20 +45,25 @@ abstract class Base extends \Kanboard\Core\Base private $params = array(); /** - * Attached event name + * Get automatic action name * - * @access protected - * @var string + * @final + * @access public + * @return string */ - protected $event_name = ''; + final public function getName() + { + return '\\'.get_called_class(); + } /** - * Container instance + * Get automatic action description * - * @access protected - * @var \Pimple\Container + * @abstract + * @access public + * @return string */ - protected $container; + abstract public function getDescription(); /** * Execute the action @@ -100,30 +112,26 @@ abstract class Base extends \Kanboard\Core\Base abstract public function hasRequiredCondition(array $data); /** - * Constructor + * Return class information * * @access public - * @param \Pimple\Container $container Container - * @param integer $project_id Project id - * @param string $event_name Attached event name + * @return string */ - public function __construct(Container $container, $project_id, $event_name) + public function __toString() { - $this->container = $container; - $this->project_id = $project_id; - $this->event_name = $event_name; - $this->called = false; + return $this->getName(); } /** - * Return class information + * Set project id * * @access public - * @return string + * @return Base */ - public function __toString() + public function setProjectId($project_id) { - return get_called_class(); + $this->projectId = $project_id; + return $this; } /** @@ -134,7 +142,7 @@ abstract class Base extends \Kanboard\Core\Base */ public function getProjectId() { - return $this->project_id; + return $this->projectId; } /** @@ -143,10 +151,12 @@ abstract class Base extends \Kanboard\Core\Base * @access public * @param string $name Parameter name * @param mixed $value Value + * @param Base */ public function setParam($name, $value) { $this->params[$name] = $value; + return $this; } /** @@ -154,24 +164,25 @@ abstract class Base extends \Kanboard\Core\Base * * @access public * @param string $name Parameter name - * @param mixed $default_value Default value + * @param mixed $default Default value * @return mixed */ - public function getParam($name, $default_value = null) + public function getParam($name, $default = null) { - return isset($this->params[$name]) ? $this->params[$name] : $default_value; + return isset($this->params[$name]) ? $this->params[$name] : $default; } /** * Check if an action is executable (right project and required parameters) * * @access public - * @param array $data Event data dictionary - * @return bool True if the action is executable + * @param array $data + * @param string $eventName + * @return bool */ - public function isExecutable(array $data) + public function isExecutable(array $data, $eventName) { - return $this->hasCompatibleEvent() && + return $this->hasCompatibleEvent($eventName) && $this->hasRequiredProject($data) && $this->hasRequiredParameters($data) && $this->hasRequiredCondition($data); @@ -181,11 +192,12 @@ abstract class Base extends \Kanboard\Core\Base * Check if the event is compatible with the action * * @access public + * @param string $eventName * @return bool */ - public function hasCompatibleEvent() + public function hasCompatibleEvent($eventName) { - return in_array($this->event_name, $this->getCompatibleEvents()); + return in_array($eventName, $this->getEvents()); } /** @@ -197,7 +209,7 @@ abstract class Base extends \Kanboard\Core\Base */ public function hasRequiredProject(array $data) { - return isset($data['project_id']) && $data['project_id'] == $this->project_id; + return isset($data['project_id']) && $data['project_id'] == $this->getProjectId(); } /** @@ -222,10 +234,11 @@ abstract class Base extends \Kanboard\Core\Base * Execute the action * * @access public - * @param \Event\GenericEvent $event Event data dictionary - * @return bool True if the action was executed or false when not executed + * @param \Kanboard\Event\GenericEvent $event + * @param string $eventName + * @return bool */ - public function execute(GenericEvent $event) + public function execute(GenericEvent $event, $eventName) { // Avoid infinite loop, a listener instance can be called only one time if ($this->called) { @@ -235,15 +248,38 @@ abstract class Base extends \Kanboard\Core\Base $data = $event->getAll(); $result = false; - if ($this->isExecutable($data)) { + if ($this->isExecutable($data, $eventName)) { $this->called = true; $result = $this->doAction($data); } - if (DEBUG) { - $this->logger->debug(get_called_class().' => '.($result ? 'true' : 'false')); - } + $this->logger->debug('AutomaticAction '.$this->getName().' => '.($result ? 'true' : 'false')); return $result; } + + /** + * Register a new event for the automatic action + * + * @access public + * @param string $event + * @param string $description + */ + public function addEvent($event, $description) + { + $this->eventManager->register($event, $description); + $this->compatibleEvents[] = $event; + return $this; + } + + /** + * Get all compatible events of an automatic action + * + * @access public + * @return array + */ + public function getEvents() + { + return array_unique(array_merge($this->getCompatibleEvents(), $this->compatibleEvents)); + } } diff --git a/app/Action/CommentCreation.php b/app/Action/CommentCreation.php index 73fedc3b..d6ea2074 100644 --- a/app/Action/CommentCreation.php +++ b/app/Action/CommentCreation.php @@ -14,6 +14,17 @@ use Kanboard\Integration\GitlabWebhook; */ class CommentCreation extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Create a comment from an external provider'); + } + /** * Get the list of compatible events * @@ -67,9 +78,9 @@ class CommentCreation extends Base { return (bool) $this->comment->create(array( 'reference' => isset($data['reference']) ? $data['reference'] : '', - 'comment' => empty($data['comment']) ? $data['commit_comment'] : $data['comment'], + 'comment' => $data['comment'], 'task_id' => $data['task_id'], - 'user_id' => empty($data['user_id']) ? 0 : $data['user_id'], + 'user_id' => isset($data['user_id']) && $this->projectPermission->isAssignable($this->getProjectId(), $data['user_id']) ? $data['user_id'] : 0, )); } @@ -82,6 +93,6 @@ class CommentCreation extends Base */ public function hasRequiredCondition(array $data) { - return ! empty($data['comment']) || ! empty($data['commit_comment']); + return ! empty($data['comment']); } } diff --git a/app/Action/CommentCreationMoveTaskColumn.php b/app/Action/CommentCreationMoveTaskColumn.php new file mode 100644 index 00000000..4473cf91 --- /dev/null +++ b/app/Action/CommentCreationMoveTaskColumn.php @@ -0,0 +1,94 @@ + t('Column')); + } + + /** + * Get the required parameter for the event + * + * @access public + * @return string[] + */ + public function getEventRequiredParameters() + { + return array('task_id', 'column_id'); + } + + /** + * Execute the action (append to the task description). + * + * @access public + * @param array $data Event data dictionary + * @return bool True if the action was executed or false when not executed + */ + public function doAction(array $data) + { + if (! $this->userSession->isLogged()) { + return false; + } + + $column = $this->board->getColumn($data['column_id']); + + return (bool) $this->comment->create(array( + 'comment' => t('Moved to column %s', $column['title']), + 'task_id' => $data['task_id'], + 'user_id' => $this->userSession->getId(), + )); + } + + /** + * Check if the event data meet the action condition + * + * @access public + * @param array $data Event data dictionary + * @return bool + */ + public function hasRequiredCondition(array $data) + { + return $data['column_id'] == $this->getParam('column_id'); + } +} diff --git a/app/Action/TaskAssignCategoryColor.php b/app/Action/TaskAssignCategoryColor.php index ffa1ac2a..f5085cb0 100644 --- a/app/Action/TaskAssignCategoryColor.php +++ b/app/Action/TaskAssignCategoryColor.php @@ -12,6 +12,17 @@ use Kanboard\Model\Task; */ class TaskAssignCategoryColor extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Assign automatically a category based on a color'); + } + /** * Get the list of compatible events * diff --git a/app/Action/TaskAssignCategoryLabel.php b/app/Action/TaskAssignCategoryLabel.php index 0ef474b6..8d291e89 100644 --- a/app/Action/TaskAssignCategoryLabel.php +++ b/app/Action/TaskAssignCategoryLabel.php @@ -12,6 +12,17 @@ use Kanboard\Integration\GithubWebhook; */ class TaskAssignCategoryLabel extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Change the category based on an external label'); + } + /** * Get the list of compatible events * @@ -64,7 +75,7 @@ class TaskAssignCategoryLabel extends Base { $values = array( 'id' => $data['task_id'], - 'category_id' => isset($data['category_id']) ? $data['category_id'] : $this->getParam('category_id'), + 'category_id' => $this->getParam('category_id'), ); return $this->taskModification->update($values); @@ -79,6 +90,6 @@ class TaskAssignCategoryLabel extends Base */ public function hasRequiredCondition(array $data) { - return $data['label'] == $this->getParam('label'); + return $data['label'] == $this->getParam('label') && empty($data['category_id']); } } diff --git a/app/Action/TaskAssignCategoryLink.php b/app/Action/TaskAssignCategoryLink.php index 3d00e8d3..b39e41b4 100644 --- a/app/Action/TaskAssignCategoryLink.php +++ b/app/Action/TaskAssignCategoryLink.php @@ -13,6 +13,17 @@ use Kanboard\Model\TaskLink; */ class TaskAssignCategoryLink extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Assign automatically a category based on a link'); + } + /** * Get the list of compatible events * @@ -65,7 +76,7 @@ class TaskAssignCategoryLink extends Base { $values = array( 'id' => $data['task_id'], - 'category_id' => isset($data['category_id']) ? $data['category_id'] : $this->getParam('category_id'), + 'category_id' => $this->getParam('category_id'), ); return $this->taskModification->update($values); diff --git a/app/Action/TaskAssignColorCategory.php b/app/Action/TaskAssignColorCategory.php index a2332f78..3a15b15f 100644 --- a/app/Action/TaskAssignColorCategory.php +++ b/app/Action/TaskAssignColorCategory.php @@ -12,6 +12,17 @@ use Kanboard\Model\Task; */ class TaskAssignColorCategory extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Assign automatically a color based on a category'); + } + /** * Get the list of compatible events * diff --git a/app/Action/TaskAssignColorColumn.php b/app/Action/TaskAssignColorColumn.php index 53140733..7474045b 100644 --- a/app/Action/TaskAssignColorColumn.php +++ b/app/Action/TaskAssignColorColumn.php @@ -12,6 +12,17 @@ use Kanboard\Model\Task; */ class TaskAssignColorColumn extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Assign a color when the task is moved to a specific column'); + } + /** * Get the list of compatible events * diff --git a/app/Action/TaskAssignColorLink.php b/app/Action/TaskAssignColorLink.php index 67b2ef62..f71df70e 100644 --- a/app/Action/TaskAssignColorLink.php +++ b/app/Action/TaskAssignColorLink.php @@ -12,6 +12,17 @@ use Kanboard\Model\TaskLink; */ class TaskAssignColorLink extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Change task color when using a specific task link'); + } + /** * Get the list of compatible events * diff --git a/app/Action/TaskAssignColorUser.php b/app/Action/TaskAssignColorUser.php index 6bf02c36..6e56bdc5 100644 --- a/app/Action/TaskAssignColorUser.php +++ b/app/Action/TaskAssignColorUser.php @@ -12,6 +12,17 @@ use Kanboard\Model\Task; */ class TaskAssignColorUser extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Assign a color to a specific user'); + } + /** * Get the list of compatible events * diff --git a/app/Action/TaskAssignCurrentUser.php b/app/Action/TaskAssignCurrentUser.php index f34c4f36..192a120c 100644 --- a/app/Action/TaskAssignCurrentUser.php +++ b/app/Action/TaskAssignCurrentUser.php @@ -12,6 +12,17 @@ use Kanboard\Model\Task; */ class TaskAssignCurrentUser extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Assign the task to the person who does the action'); + } + /** * Get the list of compatible events * @@ -22,7 +33,6 @@ class TaskAssignCurrentUser extends Base { return array( Task::EVENT_CREATE, - Task::EVENT_MOVE_COLUMN, ); } @@ -34,9 +44,7 @@ class TaskAssignCurrentUser extends Base */ public function getActionRequiredParameters() { - return array( - 'column_id' => t('Column'), - ); + return array(); } /** @@ -49,7 +57,6 @@ class TaskAssignCurrentUser extends Base { return array( 'task_id', - 'column_id', ); } @@ -83,6 +90,6 @@ class TaskAssignCurrentUser extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return true; } } diff --git a/app/Action/TaskAssignCurrentUserColumn.php b/app/Action/TaskAssignCurrentUserColumn.php new file mode 100644 index 00000000..05d08dd3 --- /dev/null +++ b/app/Action/TaskAssignCurrentUserColumn.php @@ -0,0 +1,98 @@ + t('Column'), + ); + } + + /** + * Get the required parameter for the event + * + * @access public + * @return string[] + */ + public function getEventRequiredParameters() + { + return array( + 'task_id', + 'column_id', + ); + } + + /** + * Execute the action + * + * @access public + * @param array $data Event data dictionary + * @return bool True if the action was executed or false when not executed + */ + public function doAction(array $data) + { + if (! $this->userSession->isLogged()) { + return false; + } + + $values = array( + 'id' => $data['task_id'], + 'owner_id' => $this->userSession->getId(), + ); + + return $this->taskModification->update($values); + } + + /** + * Check if the event data meet the action condition + * + * @access public + * @param array $data Event data dictionary + * @return bool + */ + public function hasRequiredCondition(array $data) + { + return $data['column_id'] == $this->getParam('column_id'); + } +} diff --git a/app/Action/TaskAssignSpecificUser.php b/app/Action/TaskAssignSpecificUser.php index dfcb281b..2dc3e966 100644 --- a/app/Action/TaskAssignSpecificUser.php +++ b/app/Action/TaskAssignSpecificUser.php @@ -12,6 +12,17 @@ use Kanboard\Model\Task; */ class TaskAssignSpecificUser extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Assign the task to a specific user'); + } + /** * Get the list of compatible events * diff --git a/app/Action/TaskAssignUser.php b/app/Action/TaskAssignUser.php index a5821729..bb3a83c2 100644 --- a/app/Action/TaskAssignUser.php +++ b/app/Action/TaskAssignUser.php @@ -13,6 +13,17 @@ use Kanboard\Integration\BitbucketWebhook; */ class TaskAssignUser extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Change the assignee based on an external username'); + } + /** * Get the list of compatible events * @@ -78,6 +89,6 @@ class TaskAssignUser extends Base */ public function hasRequiredCondition(array $data) { - return true; + return $this->projectPermission->isAssignable($this->getProjectId(), $data['owner_id']); } } diff --git a/app/Action/TaskClose.php b/app/Action/TaskClose.php index d80bd023..a4b093a4 100644 --- a/app/Action/TaskClose.php +++ b/app/Action/TaskClose.php @@ -15,6 +15,17 @@ use Kanboard\Model\Task; */ class TaskClose extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Close a task'); + } + /** * Get the list of compatible events * @@ -24,7 +35,6 @@ class TaskClose extends Base public function getCompatibleEvents() { return array( - Task::EVENT_MOVE_COLUMN, GithubWebhook::EVENT_COMMIT, GithubWebhook::EVENT_ISSUE_CLOSED, GitlabWebhook::EVENT_COMMIT, @@ -42,17 +52,7 @@ class TaskClose extends Base */ public function getActionRequiredParameters() { - switch ($this->event_name) { - case GithubWebhook::EVENT_COMMIT: - case GithubWebhook::EVENT_ISSUE_CLOSED: - case GitlabWebhook::EVENT_COMMIT: - case GitlabWebhook::EVENT_ISSUE_CLOSED: - case BitbucketWebhook::EVENT_COMMIT: - case BitbucketWebhook::EVENT_ISSUE_CLOSED: - return array(); - default: - return array('column_id' => t('Column')); - } + return array(); } /** @@ -63,17 +63,7 @@ class TaskClose extends Base */ public function getEventRequiredParameters() { - switch ($this->event_name) { - case GithubWebhook::EVENT_COMMIT: - case GithubWebhook::EVENT_ISSUE_CLOSED: - case GitlabWebhook::EVENT_COMMIT: - case GitlabWebhook::EVENT_ISSUE_CLOSED: - case BitbucketWebhook::EVENT_COMMIT: - case BitbucketWebhook::EVENT_ISSUE_CLOSED: - return array('task_id'); - default: - return array('task_id', 'column_id'); - } + return array('task_id'); } /** @@ -97,16 +87,6 @@ class TaskClose extends Base */ public function hasRequiredCondition(array $data) { - switch ($this->event_name) { - case GithubWebhook::EVENT_COMMIT: - case GithubWebhook::EVENT_ISSUE_CLOSED: - case GitlabWebhook::EVENT_COMMIT: - case GitlabWebhook::EVENT_ISSUE_CLOSED: - case BitbucketWebhook::EVENT_COMMIT: - case BitbucketWebhook::EVENT_ISSUE_CLOSED: - return true; - default: - return $data['column_id'] == $this->getParam('column_id'); - } + return true; } } diff --git a/app/Action/TaskCloseColumn.php b/app/Action/TaskCloseColumn.php new file mode 100644 index 00000000..09af3b96 --- /dev/null +++ b/app/Action/TaskCloseColumn.php @@ -0,0 +1,84 @@ + t('Column')); + } + + /** + * Get the required parameter for the event + * + * @access public + * @return string[] + */ + public function getEventRequiredParameters() + { + return array('task_id', 'column_id'); + } + + /** + * Execute the action (close the task) + * + * @access public + * @param array $data Event data dictionary + * @return bool True if the action was executed or false when not executed + */ + public function doAction(array $data) + { + return $this->taskStatus->close($data['task_id']); + } + + /** + * Check if the event data meet the action condition + * + * @access public + * @param array $data Event data dictionary + * @return bool + */ + public function hasRequiredCondition(array $data) + { + return $data['column_id'] == $this->getParam('column_id'); + } +} diff --git a/app/Action/TaskCreation.php b/app/Action/TaskCreation.php index af1403f0..23ff4592 100644 --- a/app/Action/TaskCreation.php +++ b/app/Action/TaskCreation.php @@ -14,6 +14,17 @@ use Kanboard\Integration\BitbucketWebhook; */ class TaskCreation extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Create a task from an external provider'); + } + /** * Get the list of compatible events * diff --git a/app/Action/TaskDuplicateAnotherProject.php b/app/Action/TaskDuplicateAnotherProject.php index 1f6684dd..5bcdce08 100644 --- a/app/Action/TaskDuplicateAnotherProject.php +++ b/app/Action/TaskDuplicateAnotherProject.php @@ -12,6 +12,17 @@ use Kanboard\Model\Task; */ class TaskDuplicateAnotherProject extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Duplicate the task to another project'); + } + /** * Get the list of compatible events * @@ -51,7 +62,6 @@ class TaskDuplicateAnotherProject extends Base return array( 'task_id', 'column_id', - 'project_id', ); } @@ -65,7 +75,6 @@ class TaskDuplicateAnotherProject extends Base public function doAction(array $data) { $destination_column_id = $this->board->getFirstColumn($this->getParam('project_id')); - return (bool) $this->taskDuplication->duplicateToProject($data['task_id'], $this->getParam('project_id'), null, $destination_column_id); } diff --git a/app/Action/TaskEmail.php b/app/Action/TaskEmail.php index 7fb76c4c..4e0e06a6 100644 --- a/app/Action/TaskEmail.php +++ b/app/Action/TaskEmail.php @@ -12,6 +12,17 @@ use Kanboard\Model\Task; */ class TaskEmail extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Send a task by email to someone'); + } + /** * Get the list of compatible events * diff --git a/app/Action/TaskLogMoveAnotherColumn.php b/app/Action/TaskLogMoveAnotherColumn.php deleted file mode 100644 index a699c4ab..00000000 --- a/app/Action/TaskLogMoveAnotherColumn.php +++ /dev/null @@ -1,83 +0,0 @@ - t('Column')); - } - - /** - * Get the required parameter for the event - * - * @access public - * @return string[] - */ - public function getEventRequiredParameters() - { - return array('task_id', 'column_id'); - } - - /** - * Execute the action (append to the task description). - * - * @access public - * @param array $data Event data dictionary - * @return bool True if the action was executed or false when not executed - */ - public function doAction(array $data) - { - if (! $this->userSession->isLogged()) { - return false; - } - - $column = $this->board->getColumn($data['column_id']); - - return (bool) $this->comment->create(array( - 'comment' => t('Moved to column %s', $column['title']), - 'task_id' => $data['task_id'], - 'user_id' => $this->userSession->getId(), - )); - } - - /** - * Check if the event data meet the action condition - * - * @access public - * @param array $data Event data dictionary - * @return bool - */ - public function hasRequiredCondition(array $data) - { - return $data['column_id'] == $this->getParam('column_id'); - } -} diff --git a/app/Action/TaskMoveAnotherProject.php b/app/Action/TaskMoveAnotherProject.php index 476e2036..fdff0d8c 100644 --- a/app/Action/TaskMoveAnotherProject.php +++ b/app/Action/TaskMoveAnotherProject.php @@ -12,6 +12,17 @@ use Kanboard\Model\Task; */ class TaskMoveAnotherProject extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Move the task to another project'); + } + /** * Get the list of compatible events * diff --git a/app/Action/TaskMoveColumnAssigned.php b/app/Action/TaskMoveColumnAssigned.php index 16622ee4..1b23a591 100644 --- a/app/Action/TaskMoveColumnAssigned.php +++ b/app/Action/TaskMoveColumnAssigned.php @@ -12,6 +12,17 @@ use Kanboard\Model\Task; */ class TaskMoveColumnAssigned extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Move the task to another column when assigned to a user'); + } + /** * Get the list of compatible events * @@ -51,7 +62,6 @@ class TaskMoveColumnAssigned extends Base return array( 'task_id', 'column_id', - 'project_id', 'owner_id' ); } diff --git a/app/Action/TaskMoveColumnCategoryChange.php b/app/Action/TaskMoveColumnCategoryChange.php index 1e12be4a..0f591eda 100644 --- a/app/Action/TaskMoveColumnCategoryChange.php +++ b/app/Action/TaskMoveColumnCategoryChange.php @@ -12,6 +12,17 @@ use Kanboard\Model\Task; */ class TaskMoveColumnCategoryChange extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Move the task to another column when the category is changed'); + } + /** * Get the list of compatible events * @@ -50,7 +61,6 @@ class TaskMoveColumnCategoryChange extends Base return array( 'task_id', 'column_id', - 'project_id', 'category_id', ); } @@ -71,7 +81,8 @@ class TaskMoveColumnCategoryChange extends Base $data['task_id'], $this->getParam('dest_column_id'), $original_task['position'], - $original_task['swimlane_id'] + $original_task['swimlane_id'], + false ); } diff --git a/app/Action/TaskMoveColumnUnAssigned.php b/app/Action/TaskMoveColumnUnAssigned.php index 617c75a8..99ef9351 100644 --- a/app/Action/TaskMoveColumnUnAssigned.php +++ b/app/Action/TaskMoveColumnUnAssigned.php @@ -12,6 +12,17 @@ use Kanboard\Model\Task; */ class TaskMoveColumnUnAssigned extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Move the task to another column when assignee is cleared'); + } + /** * Get the list of compatible events * @@ -51,7 +62,6 @@ class TaskMoveColumnUnAssigned extends Base return array( 'task_id', 'column_id', - 'project_id', 'owner_id' ); } diff --git a/app/Action/TaskOpen.php b/app/Action/TaskOpen.php index 2e84c695..a1ab622c 100644 --- a/app/Action/TaskOpen.php +++ b/app/Action/TaskOpen.php @@ -14,6 +14,17 @@ use Kanboard\Integration\BitbucketWebhook; */ class TaskOpen extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Open a task'); + } + /** * Get the list of compatible events * diff --git a/app/Action/TaskUpdateStartDate.php b/app/Action/TaskUpdateStartDate.php index 4cd548af..011a5baf 100644 --- a/app/Action/TaskUpdateStartDate.php +++ b/app/Action/TaskUpdateStartDate.php @@ -12,6 +12,17 @@ use Kanboard\Model\Task; */ class TaskUpdateStartDate extends Base { + /** + * Get automatic action description + * + * @access public + * @return string + */ + public function getDescription() + { + return t('Automatically update the start date'); + } + /** * Get the list of compatible events * diff --git a/app/Api/Action.php b/app/Api/Action.php index 0ae91f10..bdb5b26e 100644 --- a/app/Api/Action.php +++ b/app/Api/Action.php @@ -12,17 +12,17 @@ class Action extends \Kanboard\Core\Base { public function getAvailableActions() { - return $this->action->getAvailableActions(); + return $this->actionManager->getAvailableActions(); } public function getAvailableActionEvents() { - return $this->action->getAvailableEvents(); + return $this->eventManager->getAll(); } public function getCompatibleActionEvents($action_name) { - return $this->action->getCompatibleEvents($action_name); + return $this->actionManager->getCompatibleEvents($action_name); } public function removeAction($action_id) @@ -32,22 +32,10 @@ class Action extends \Kanboard\Core\Base public function getActions($project_id) { - $actions = $this->action->getAllByProject($project_id); - - foreach ($actions as $index => $action) { - $params = array(); - - foreach ($action['params'] as $param) { - $params[$param['name']] = $param['value']; - } - - $actions[$index]['params'] = $params; - } - - return $actions; + return $this->action->getAllByProject($project_id); } - public function createAction($project_id, $event_name, $action_name, $params) + public function createAction($project_id, $event_name, $action_name, array $params) { $values = array( 'project_id' => $project_id, @@ -63,16 +51,16 @@ class Action extends \Kanboard\Core\Base } // Check if the action exists - $actions = $this->action->getAvailableActions(); + $actions = $this->actionManager->getAvailableActions(); if (! isset($actions[$action_name])) { return false; } // Check the event - $action = $this->action->load($action_name, $project_id, $event_name); + $action = $this->actionManager->getAction($action_name); - if (! in_array($event_name, $action->getCompatibleEvents())) { + if (! in_array($event_name, $action->getEvents())) { return false; } diff --git a/app/Controller/Action.php b/app/Controller/Action.php index 3caea45c..9b803893 100644 --- a/app/Controller/Action.php +++ b/app/Controller/Action.php @@ -18,17 +18,18 @@ class Action extends Base public function index() { $project = $this->getProject(); + $actions = $this->action->getAllByProject($project['id']); $this->response->html($this->projectLayout('action/index', array( 'values' => array('project_id' => $project['id']), 'project' => $project, - 'actions' => $this->action->getAllByProject($project['id']), - 'available_actions' => $this->action->getAvailableActions(), - 'available_events' => $this->action->getAvailableEvents(), - 'available_params' => $this->action->getAllActionParameters(), + 'actions' => $actions, + 'available_actions' => $this->actionManager->getAvailableActions(), + 'available_events' => $this->eventManager->getAll(), + 'available_params' => $this->actionManager->getAvailableParameters($actions), 'columns_list' => $this->board->getColumnsList($project['id']), 'users_list' => $this->projectUserRole->getAssignableUsersList($project['id']), - 'projects_list' => $this->project->getList(false), + 'projects_list' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), 'colors_list' => $this->color->getList(), 'categories_list' => $this->category->getList($project['id']), 'links_list' => $this->link->getList(0, false), @@ -53,7 +54,7 @@ class Action extends Base $this->response->html($this->projectLayout('action/event', array( 'values' => $values, 'project' => $project, - 'events' => $this->action->getCompatibleEvents($values['action_name']), + 'events' => $this->actionManager->getCompatibleEvents($values['action_name']), 'title' => t('Automatic actions') ))); } @@ -72,14 +73,14 @@ class Action extends Base $this->response->redirect($this->helper->url->to('action', 'index', array('project_id' => $project['id']))); } - $action = $this->action->load($values['action_name'], $values['project_id'], $values['event_name']); + $action = $this->actionManager->getAction($values['action_name']); $action_params = $action->getActionRequiredParameters(); if (empty($action_params)) { $this->doCreation($project, $values + array('params' => array())); } - $projects_list = $this->project->getList(false); + $projects_list = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); unset($projects_list[$project['id']]); $this->response->html($this->projectLayout('action/params', array( @@ -139,8 +140,8 @@ class Action extends Base $this->response->html($this->projectLayout('action/remove', array( 'action' => $this->action->getById($this->request->getIntegerParam('action_id')), - 'available_events' => $this->action->getAvailableEvents(), - 'available_actions' => $this->action->getAvailableActions(), + 'available_events' => $this->eventManager->getAll(), + 'available_actions' => $this->actionManager->getAvailableActions(), 'project' => $project, 'title' => t('Remove an action') ))); diff --git a/app/Core/Action/ActionManager.php b/app/Core/Action/ActionManager.php new file mode 100644 index 00000000..921a8b98 --- /dev/null +++ b/app/Core/Action/ActionManager.php @@ -0,0 +1,141 @@ +actions[$action->getName()] = $action; + return $this; + } + + /** + * Get automatic action instance + * + * @access public + * @param string $name Absolute class name with namespace + * @return ActionBase + */ + public function getAction($name) + { + if (isset($this->actions[$name])) { + return $this->actions[$name]; + } + + throw new RuntimeException('Automatic Action Not Found: '.$name); + } + + /** + * Get available automatic actions + * + * @access public + * @return array + */ + public function getAvailableActions() + { + $actions = array(); + + foreach ($this->actions as $action) { + if (count($action->getEvents()) > 0) { + $actions[$action->getName()] = $action->getDescription(); + } + } + + asort($actions); + + return $actions; + } + + /** + * Get all available action parameters + * + * @access public + * @param array $actions + * @return array + */ + public function getAvailableParameters(array $actions) + { + $params = array(); + + foreach ($actions as $action) { + $currentAction = $this->getAction($action['action_name']); + $params[$currentAction->getName()] = $currentAction->getActionRequiredParameters(); + } + + return $params; + } + + /** + * Get list of compatible events for a given action + * + * @access public + * @param string $name + * @return array + */ + public function getCompatibleEvents($name) + { + $events = array(); + $actionEvents = $this->getAction($name)->getEvents(); + + foreach ($this->eventManager->getAll() as $event => $description) { + if (in_array($event, $actionEvents)) { + $events[$event] = $description; + } + } + + return $events; + } + + /** + * Bind automatic actions to events + * + * @access public + * @return ActionManager + */ + public function attachEvents() + { + if ($this->userSession->isLogged()) { + $actions = $this->action->getAllByUser($this->userSession->getId()); + } else { + $actions = $this->action->getAll(); + } + + foreach ($actions as $action) { + $listener = $this->getAction($action['action_name'])->setProjectId($action['project_id']); + + foreach ($action['params'] as $param_name => $param_value) { + $listener->setParam($param_name, $param_value); + } + + $this->dispatcher->addListener($action['event_name'], array($listener, 'execute')); + } + + return $this; + } +} diff --git a/app/Core/Base.php b/app/Core/Base.php index a4cf787a..11a0be68 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -10,7 +10,9 @@ use Pimple\Container; * @package core * @author Frederic Guillot * + * @property \Kanboard\Core\Action\ActionManager $actionManager * @property \Kanboard\Core\Cache\MemoryCache $memoryCache + * @property \Kanboard\Core\Event\EventManager $eventManager * @property \Kanboard\Core\Group\GroupManager $groupManager * @property \Kanboard\Core\Http\Client $httpClient * @property \Kanboard\Core\Http\OAuth2 $oauth @@ -54,6 +56,7 @@ use Pimple\Container; * @property \Kanboard\Formatter\UserFilterAutoCompleteFormatter $userFilterAutoCompleteFormatter * @property \Kanboard\Formatter\GroupAutoCompleteFormatter $groupAutoCompleteFormatter * @property \Kanboard\Model\Action $action + * @property \Kanboard\Model\ActionParameter $actionParameter * @property \Kanboard\Model\Authentication $authentication * @property \Kanboard\Model\Board $board * @property \Kanboard\Model\Category $category diff --git a/app/Core/Event/EventManager.php b/app/Core/Event/EventManager.php new file mode 100644 index 00000000..8e66cc12 --- /dev/null +++ b/app/Core/Event/EventManager.php @@ -0,0 +1,83 @@ +events[$event] = $description; + return $this; + } + + /** + * Get the list of events and description that can be used from the user interface + * + * @access public + * @return array + */ + public function getAll() + { + $events = array( + TaskLink::EVENT_CREATE_UPDATE => t('Task link creation or modification'), + Task::EVENT_MOVE_COLUMN => t('Move a task to another column'), + Task::EVENT_UPDATE => t('Task modification'), + Task::EVENT_CREATE => t('Task creation'), + Task::EVENT_OPEN => t('Reopen a task'), + Task::EVENT_CLOSE => t('Closing a task'), + Task::EVENT_CREATE_UPDATE => t('Task creation or modification'), + Task::EVENT_ASSIGNEE_CHANGE => t('Task assignee change'), + GithubWebhook::EVENT_COMMIT => t('Github commit received'), + GithubWebhook::EVENT_ISSUE_OPENED => t('Github issue opened'), + GithubWebhook::EVENT_ISSUE_CLOSED => t('Github issue closed'), + GithubWebhook::EVENT_ISSUE_REOPENED => t('Github issue reopened'), + GithubWebhook::EVENT_ISSUE_ASSIGNEE_CHANGE => t('Github issue assignee change'), + GithubWebhook::EVENT_ISSUE_LABEL_CHANGE => t('Github issue label change'), + GithubWebhook::EVENT_ISSUE_COMMENT => t('Github issue comment created'), + GitlabWebhook::EVENT_COMMIT => t('Gitlab commit received'), + GitlabWebhook::EVENT_ISSUE_OPENED => t('Gitlab issue opened'), + GitlabWebhook::EVENT_ISSUE_REOPENED => t('Gitlab issue reopened'), + GitlabWebhook::EVENT_ISSUE_CLOSED => t('Gitlab issue closed'), + GitlabWebhook::EVENT_ISSUE_COMMENT => t('Gitlab issue comment created'), + BitbucketWebhook::EVENT_COMMIT => t('Bitbucket commit received'), + BitbucketWebhook::EVENT_ISSUE_OPENED => t('Bitbucket issue opened'), + BitbucketWebhook::EVENT_ISSUE_CLOSED => t('Bitbucket issue closed'), + BitbucketWebhook::EVENT_ISSUE_REOPENED => t('Bitbucket issue reopened'), + BitbucketWebhook::EVENT_ISSUE_ASSIGNEE_CHANGE => t('Bitbucket issue assignee change'), + BitbucketWebhook::EVENT_ISSUE_COMMENT => t('Bitbucket issue comment created'), + ); + + $events = array_merge($events, $this->events); + asort($events); + + return $events; + } +} diff --git a/app/Core/Mail/Client.php b/app/Core/Mail/Client.php index 7b4268bd..e1f31696 100644 --- a/app/Core/Mail/Client.php +++ b/app/Core/Mail/Client.php @@ -45,19 +45,21 @@ class Client extends Base */ public function send($email, $name, $subject, $html) { - $this->container['logger']->debug('Sending email to '.$email.' ('.MAIL_TRANSPORT.')'); + if (! empty($email)) { + $this->logger->debug('Sending email to '.$email.' ('.MAIL_TRANSPORT.')'); - $start_time = microtime(true); - $author = 'Kanboard'; + $start_time = microtime(true); + $author = 'Kanboard'; - if ($this->userSession->isLogged()) { - $author = e('%s via Kanboard', $this->helper->user->getFullname()); - } + if ($this->userSession->isLogged()) { + $author = e('%s via Kanboard', $this->helper->user->getFullname()); + } - $this->getTransport(MAIL_TRANSPORT)->sendEmail($email, $name, $subject, $html, $author); + $this->getTransport(MAIL_TRANSPORT)->sendEmail($email, $name, $subject, $html, $author); - if (DEBUG) { - $this->logger->debug('Email sent in '.round(microtime(true) - $start_time, 6).' seconds'); + if (DEBUG) { + $this->logger->debug('Email sent in '.round(microtime(true) - $start_time, 6).' seconds'); + } } return $this; diff --git a/app/Integration/BitbucketWebhook.php b/app/Integration/BitbucketWebhook.php index 3814e35c..e6ba3f1a 100644 --- a/app/Integration/BitbucketWebhook.php +++ b/app/Integration/BitbucketWebhook.php @@ -303,7 +303,7 @@ class BitbucketWebhook extends \Kanboard\Core\Base 'task_id' => $task_id, 'commit_message' => $commit['message'], 'commit_url' => $commit['links']['html']['href'], - 'commit_comment' => $commit['message']."\n\n[".t('Commit made by @%s on Bitbucket', $actor['display_name']).']('.$commit['links']['html']['href'].')', + 'comment' => $commit['message']."\n\n[".t('Commit made by @%s on Bitbucket', $actor['display_name']).']('.$commit['links']['html']['href'].')', ) + $task) ); diff --git a/app/Integration/GithubWebhook.php b/app/Integration/GithubWebhook.php index 6dd7a8d9..cdd2fc48 100644 --- a/app/Integration/GithubWebhook.php +++ b/app/Integration/GithubWebhook.php @@ -98,7 +98,7 @@ class GithubWebhook extends \Kanboard\Core\Base 'task_id' => $task_id, 'commit_message' => $commit['message'], 'commit_url' => $commit['url'], - 'commit_comment' => $commit['message']."\n\n[".t('Commit made by @%s on Github', $commit['author']['username']).']('.$commit['url'].')' + 'comment' => $commit['message']."\n\n[".t('Commit made by @%s on Github', $commit['author']['username']).']('.$commit['url'].')' ) + $task) ); } diff --git a/app/Integration/GitlabWebhook.php b/app/Integration/GitlabWebhook.php index 7ab4cedf..5e0aa59d 100644 --- a/app/Integration/GitlabWebhook.php +++ b/app/Integration/GitlabWebhook.php @@ -144,7 +144,7 @@ class GitlabWebhook extends \Kanboard\Core\Base 'task_id' => $task_id, 'commit_message' => $commit['message'], 'commit_url' => $commit['url'], - 'commit_comment' => $commit['message']."\n\n[".t('Commit made by @%s on Gitlab', $commit['author']['name']).']('.$commit['url'].')' + 'comment' => $commit['message']."\n\n[".t('Commit made by @%s on Gitlab', $commit['author']['name']).']('.$commit['url'].')' ) + $task) ); diff --git a/app/Model/Action.php b/app/Model/Action.php index d3d18edb..c368b494 100644 --- a/app/Model/Action.php +++ b/app/Model/Action.php @@ -2,14 +2,11 @@ namespace Kanboard\Model; -use Kanboard\Integration\GitlabWebhook; -use Kanboard\Integration\GithubWebhook; -use Kanboard\Integration\BitbucketWebhook; use SimpleValidator\Validator; use SimpleValidator\Validators; /** - * Action model + * Action Model * * @package model * @author Frederic Guillot @@ -24,143 +21,33 @@ class Action extends Base const TABLE = 'actions'; /** - * SQL table name for action parameters - * - * @var string - */ - const TABLE_PARAMS = 'action_has_params'; - - /** - * Extended actions - * - * @access private - * @var array - */ - private $actions = array(); - - /** - * Extend the list of default actions - * - * @access public - * @param string $className - * @param string $description - * @return Action - */ - public function extendActions($className, $description) - { - $this->actions[$className] = $description; - return $this; - } - - /** - * Return the name and description of available actions + * Return actions and parameters for a given user * * @access public + * @param integer $user_id * @return array */ - public function getAvailableActions() + public function getAllByUser($user_id) { - $values = array( - 'TaskClose' => t('Close a task'), - 'TaskOpen' => t('Open a task'), - 'TaskAssignSpecificUser' => t('Assign the task to a specific user'), - 'TaskAssignCurrentUser' => t('Assign the task to the person who does the action'), - 'TaskDuplicateAnotherProject' => t('Duplicate the task to another project'), - 'TaskMoveAnotherProject' => t('Move the task to another project'), - 'TaskMoveColumnAssigned' => t('Move the task to another column when assigned to a user'), - 'TaskMoveColumnUnAssigned' => t('Move the task to another column when assignee is cleared'), - 'TaskAssignColorColumn' => t('Assign a color when the task is moved to a specific column'), - 'TaskAssignColorUser' => t('Assign a color to a specific user'), - 'TaskAssignColorCategory' => t('Assign automatically a color based on a category'), - 'TaskAssignCategoryColor' => t('Assign automatically a category based on a color'), - 'TaskAssignCategoryLink' => t('Assign automatically a category based on a link'), - 'CommentCreation' => t('Create a comment from an external provider'), - 'TaskCreation' => t('Create a task from an external provider'), - 'TaskLogMoveAnotherColumn' => t('Add a comment log when moving the task between columns'), - 'TaskAssignUser' => t('Change the assignee based on an external username'), - 'TaskAssignCategoryLabel' => t('Change the category based on an external label'), - 'TaskUpdateStartDate' => t('Automatically update the start date'), - 'TaskMoveColumnCategoryChange' => t('Move the task to another column when the category is changed'), - 'TaskEmail' => t('Send a task by email to someone'), - 'TaskAssignColorLink' => t('Change task color when using a specific task link'), - ); - - $values = array_merge($values, $this->actions); + $project_ids = $this->projectPermission->getActiveProjectIds($user_id); + $actions = array(); - asort($values); + if (! empty($project_ids)) { + $actions = $this->db->table(self::TABLE)->in('project_id', $project_ids)->findAll(); - return $values; - } - - /** - * Return the name and description of available actions - * - * @access public - * @return array - */ - public function getAvailableEvents() - { - $values = array( - TaskLink::EVENT_CREATE_UPDATE => t('Task link creation or modification'), - Task::EVENT_MOVE_COLUMN => t('Move a task to another column'), - Task::EVENT_UPDATE => t('Task modification'), - Task::EVENT_CREATE => t('Task creation'), - Task::EVENT_OPEN => t('Reopen a task'), - Task::EVENT_CLOSE => t('Closing a task'), - Task::EVENT_CREATE_UPDATE => t('Task creation or modification'), - Task::EVENT_ASSIGNEE_CHANGE => t('Task assignee change'), - GithubWebhook::EVENT_COMMIT => t('Github commit received'), - GithubWebhook::EVENT_ISSUE_OPENED => t('Github issue opened'), - GithubWebhook::EVENT_ISSUE_CLOSED => t('Github issue closed'), - GithubWebhook::EVENT_ISSUE_REOPENED => t('Github issue reopened'), - GithubWebhook::EVENT_ISSUE_ASSIGNEE_CHANGE => t('Github issue assignee change'), - GithubWebhook::EVENT_ISSUE_LABEL_CHANGE => t('Github issue label change'), - GithubWebhook::EVENT_ISSUE_COMMENT => t('Github issue comment created'), - GitlabWebhook::EVENT_COMMIT => t('Gitlab commit received'), - GitlabWebhook::EVENT_ISSUE_OPENED => t('Gitlab issue opened'), - GitlabWebhook::EVENT_ISSUE_REOPENED => t('Gitlab issue reopened'), - GitlabWebhook::EVENT_ISSUE_CLOSED => t('Gitlab issue closed'), - GitlabWebhook::EVENT_ISSUE_COMMENT => t('Gitlab issue comment created'), - BitbucketWebhook::EVENT_COMMIT => t('Bitbucket commit received'), - BitbucketWebhook::EVENT_ISSUE_OPENED => t('Bitbucket issue opened'), - BitbucketWebhook::EVENT_ISSUE_CLOSED => t('Bitbucket issue closed'), - BitbucketWebhook::EVENT_ISSUE_REOPENED => t('Bitbucket issue reopened'), - BitbucketWebhook::EVENT_ISSUE_ASSIGNEE_CHANGE => t('Bitbucket issue assignee change'), - BitbucketWebhook::EVENT_ISSUE_COMMENT => t('Bitbucket issue comment created'), - ); - - asort($values); - - return $values; - } - - /** - * Return the name and description of compatible actions - * - * @access public - * @param string $action_name Action name - * @return array - */ - public function getCompatibleEvents($action_name) - { - $action = $this->load($action_name, 0, ''); - $compatible_events = $action->getCompatibleEvents(); - $events = array(); - - foreach ($this->getAvailableEvents() as $event_name => $event_description) { - if (in_array($event_name, $compatible_events)) { - $events[$event_name] = $event_description; + foreach ($actions as &$action) { + $action['params'] = $this->actionParameter->getAll($action['id']); } } - return $events; + return $actions; } /** * Return actions and parameters for a given project * * @access public - * @param $project_id + * @param integer $project_id * @return array */ public function getAllByProject($project_id) @@ -168,7 +55,7 @@ class Action extends Base $actions = $this->db->table(self::TABLE)->eq('project_id', $project_id)->findAll(); foreach ($actions as &$action) { - $action['params'] = $this->db->table(self::TABLE_PARAMS)->eq('action_id', $action['id'])->findAll(); + $action['params'] = $this->actionParameter->getAll($action['id']); } return $actions; @@ -183,52 +70,27 @@ class Action extends Base public function getAll() { $actions = $this->db->table(self::TABLE)->findAll(); - $params = $this->db->table(self::TABLE_PARAMS)->findAll(); foreach ($actions as &$action) { - $action['params'] = array(); - - foreach ($params as $param) { - if ($param['action_id'] === $action['id']) { - $action['params'][] = $param; - } - } + $action['params'] = $this->actionParameter->getAll($action['id']); } return $actions; } - /** - * Get all required action parameters for all registered actions - * - * @access public - * @return array All required parameters for all actions - */ - public function getAllActionParameters() - { - $params = array(); - - foreach ($this->getAll() as $action) { - $action = $this->load($action['action_name'], $action['project_id'], $action['event_name']); - $params += $action->getActionRequiredParameters(); - } - - return $params; - } - /** * Fetch an action * * @access public - * @param integer $action_id Action id - * @return array Action data + * @param integer $action_id + * @return array */ public function getById($action_id) { $action = $this->db->table(self::TABLE)->eq('id', $action_id)->findOne(); if (! empty($action)) { - $action['params'] = $this->db->table(self::TABLE_PARAMS)->eq('action_id', $action_id)->findAll(); + $action['params'] = $this->actionParameter->getAll($action_id); } return $action; @@ -238,8 +100,8 @@ class Action extends Base * Remove an action * * @access public - * @param integer $action_id Action id - * @return bool Success or not + * @param integer $action_id + * @return bool */ public function remove($action_id) { @@ -263,24 +125,16 @@ class Action extends Base 'action_name' => $values['action_name'], ); - if (! $this->db->table(self::TABLE)->save($action)) { + if (! $this->db->table(self::TABLE)->insert($action)) { $this->db->cancelTransaction(); return false; } $action_id = $this->db->getLastId(); - foreach ($values['params'] as $param_name => $param_value) { - $action_param = array( - 'action_id' => $action_id, - 'name' => $param_name, - 'value' => $param_value, - ); - - if (! $this->db->table(self::TABLE_PARAMS)->save($action_param)) { - $this->db->cancelTransaction(); - return false; - } + if (! $this->actionParameter->create($action_id, $values)) { + $this->db->cancelTransaction(); + return false; } $this->db->closeTransaction(); @@ -288,42 +142,6 @@ class Action extends Base return $action_id; } - /** - * Load all actions and attach events - * - * @access public - */ - public function attachEvents() - { - $actions = $this->getAll(); - - foreach ($actions as $action) { - $listener = $this->load($action['action_name'], $action['project_id'], $action['event_name']); - - foreach ($action['params'] as $param) { - $listener->setParam($param['name'], $param['value']); - } - - $this->container['dispatcher']->addListener($action['event_name'], array($listener, 'execute')); - } - } - - /** - * Load an action - * - * @access public - * @param string $name Action class name - * @param integer $project_id Project id - * @param string $event Event name - * @return \Action\Base - */ - public function load($name, $project_id, $event) - { - $className = $name{0} - !== '\\' ? '\Kanboard\Action\\'.$name : $name; - return new $className($this->container, $project_id, $event); - } - /** * Copy actions from a project to another one (skip actions that cannot resolve parameters) * @@ -346,15 +164,14 @@ class Action extends Base ); if (! $this->db->table(self::TABLE)->insert($values)) { - $this->container['logger']->debug('Action::duplicate => unable to create '.$action['action_name']); $this->db->cancelTransaction(); continue; } $action_id = $this->db->getLastId(); - if (! $this->duplicateParameters($dst_project_id, $action_id, $action['params'])) { - $this->container['logger']->debug('Action::duplicate => unable to copy parameters for '.$action['action_name']); + if (! $this->actionParameter->duplicateParameters($dst_project_id, $action_id, $action['params'])) { + $this->logger->error('Action::duplicate => skip action '.$action['action_name'].' '.$action['id']); $this->db->cancelTransaction(); continue; } @@ -365,74 +182,6 @@ class Action extends Base return true; } - /** - * Duplicate action parameters - * - * @access public - * @param integer $project_id - * @param integer $action_id - * @param array $params - * @return boolean - */ - public function duplicateParameters($project_id, $action_id, array $params) - { - foreach ($params as $param) { - $value = $this->resolveParameters($param, $project_id); - - if ($value === false) { - $this->container['logger']->debug('Action::duplicateParameters => unable to resolve '.$param['name'].'='.$param['value']); - return false; - } - - $values = array( - 'action_id' => $action_id, - 'name' => $param['name'], - 'value' => $value, - ); - - if (! $this->db->table(self::TABLE_PARAMS)->insert($values)) { - return false; - } - } - - return true; - } - - /** - * Resolve action parameter values according to another project - * - * @author Antonio Rabelo - * @access public - * @param array $param Action parameter - * @param integer $project_id Project to find the corresponding values - * @return mixed - */ - public function resolveParameters(array $param, $project_id) - { - switch ($param['name']) { - case 'project_id': - return $project_id; - case 'category_id': - return $this->category->getIdByName($project_id, $this->category->getNameById($param['value'])) ?: false; - case 'src_column_id': - case 'dest_column_id': - case 'dst_column_id': - case 'column_id': - $column = $this->board->getColumn($param['value']); - - if (empty($column)) { - return false; - } - - return $this->board->getColumnIdByTitle($project_id, $column['title']) ?: false; - case 'user_id': - case 'owner_id': - return $this->projectPermission->isAssignable($project_id, $param['value']) ? $param['value'] : false; - default: - return $param['value']; - } - } - /** * Validate action creation * diff --git a/app/Model/ActionParameter.php b/app/Model/ActionParameter.php new file mode 100644 index 00000000..f170ef66 --- /dev/null +++ b/app/Model/ActionParameter.php @@ -0,0 +1,122 @@ +db->hashtable(self::TABLE)->eq('action_id', $action_id)->getAll('name', 'value'); + } + + /** + * Insert new parameters for an action + * + * @access public + * @param integer $action_id + * @param array $values + * @return boolean + */ + public function create($action_id, array $values) + { + foreach ($values['params'] as $name => $value) { + $param = array( + 'action_id' => $action_id, + 'name' => $name, + 'value' => $value, + ); + + if (! $this->db->table(self::TABLE)->save($param)) { + return false; + } + } + + return true; + } + + /** + * Duplicate action parameters + * + * @access public + * @param integer $project_id + * @param integer $action_id + * @param array $params + * @return boolean + */ + public function duplicateParameters($project_id, $action_id, array $params) + { + foreach ($params as $name => $value) { + $value = $this->resolveParameter($project_id, $name, $value); + + if ($value === false) { + $this->logger->error('ActionParameter::duplicateParameters => unable to resolve '.$name.'='.$value); + return false; + } + + $values = array( + 'action_id' => $action_id, + 'name' => $name, + 'value' => $value, + ); + + if (! $this->db->table(self::TABLE)->insert($values)) { + return false; + } + } + + return true; + } + + /** + * Resolve action parameter values according to another project + * + * @access private + * @param integer $project_id + * @param string $name + * @param string $value + * @return mixed + */ + private function resolveParameter($project_id, $name, $value) + { + switch ($name) { + case 'project_id': + return $value != $project_id ? $value : false; + case 'category_id': + return $this->category->getIdByName($project_id, $this->category->getNameById($value)) ?: false; + case 'src_column_id': + case 'dest_column_id': + case 'dst_column_id': + case 'column_id': + $column = $this->board->getColumn($value); + return empty($column) ? false : $this->board->getColumnIdByTitle($project_id, $column['title']) ?: false; + case 'user_id': + case 'owner_id': + return $this->projectPermission->isAssignable($project_id, $value) ? $value : false; + default: + return $value; + } + } +} diff --git a/app/Model/Comment.php b/app/Model/Comment.php index 71e964dc..eb83f8d6 100644 --- a/app/Model/Comment.php +++ b/app/Model/Comment.php @@ -75,6 +75,7 @@ class Comment extends Base self::TABLE.'.user_id', self::TABLE.'.date_creation', self::TABLE.'.comment', + self::TABLE.'.reference', User::TABLE.'.username', User::TABLE.'.name' ) diff --git a/app/Model/ProjectUserRole.php b/app/Model/ProjectUserRole.php index b2c38622..6b9c23b0 100644 --- a/app/Model/ProjectUserRole.php +++ b/app/Model/ProjectUserRole.php @@ -52,11 +52,11 @@ class ProjectUserRole extends Base ->getAll(Project::TABLE.'.id', Project::TABLE.'.name'); $groupProjects = $this->projectGroupRole->getProjectsByUser($user_id, $status); - $groups = $userProjects + $groupProjects; + $projects = $userProjects + $groupProjects; - asort($groups); + asort($projects); - return $groups; + return $projects; } /** diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php index 534c3f3a..f430c00b 100644 --- a/app/Schema/Sqlite.php +++ b/app/Schema/Sqlite.php @@ -6,7 +6,30 @@ use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; use PDO; -const VERSION = 91; +const VERSION = 92; + +function version_92(PDO $pdo) +{ + $rq = $pdo->prepare('SELECT * FROM actions'); + $rq->execute(); + $rows = $rq->fetchAll(PDO::FETCH_ASSOC) ?: array(); + + $rq = $pdo->prepare('UPDATE actions SET action_name=? WHERE id=?'); + + foreach ($rows as $row) { + if ($row['action_name'] === 'TaskAssignCurrentUser' && $row['event_name'] === 'task.move.column') { + $row['action_name'] = '\Kanboard\Action\TaskAssignCurrentUserColumn'; + } elseif ($row['action_name'] === 'TaskClose' && $row['event_name'] === 'task.move.column') { + $row['action_name'] = '\Kanboard\Action\TaskCloseColumn'; + } elseif ($row['action_name'] === 'TaskLogMoveAnotherColumn') { + $row['action_name'] = '\Kanboard\Action\CommentCreationMoveTaskColumn'; + } elseif ($row['action_name']{0} !== '\\') { + $row['action_name'] = '\Kanboard\Action\\'.$row['action_name']; + } + + $rq->execute(array($row['action_name'], $row['id'])); + } +} function version_91(PDO $pdo) { diff --git a/app/ServiceProvider/ActionProvider.php b/app/ServiceProvider/ActionProvider.php new file mode 100644 index 00000000..0aba29f1 --- /dev/null +++ b/app/ServiceProvider/ActionProvider.php @@ -0,0 +1,78 @@ +register(new CommentCreation($container)); + $container['actionManager']->register(new CommentCreationMoveTaskColumn($container)); + $container['actionManager']->register(new TaskAssignCategoryColor($container)); + $container['actionManager']->register(new TaskAssignCategoryLabel($container)); + $container['actionManager']->register(new TaskAssignCategoryLink($container)); + $container['actionManager']->register(new TaskAssignColorCategory($container)); + $container['actionManager']->register(new TaskAssignColorColumn($container)); + $container['actionManager']->register(new TaskAssignColorLink($container)); + $container['actionManager']->register(new TaskAssignColorUser($container)); + $container['actionManager']->register(new TaskAssignCurrentUser($container)); + $container['actionManager']->register(new TaskAssignCurrentUserColumn($container)); + $container['actionManager']->register(new TaskAssignSpecificUser($container)); + $container['actionManager']->register(new TaskAssignUser($container)); + $container['actionManager']->register(new TaskClose($container)); + $container['actionManager']->register(new TaskCloseColumn($container)); + $container['actionManager']->register(new TaskCreation($container)); + $container['actionManager']->register(new TaskDuplicateAnotherProject($container)); + $container['actionManager']->register(new TaskEmail($container)); + $container['actionManager']->register(new TaskMoveAnotherProject($container)); + $container['actionManager']->register(new TaskMoveColumnAssigned($container)); + $container['actionManager']->register(new TaskMoveColumnCategoryChange($container)); + $container['actionManager']->register(new TaskMoveColumnUnAssigned($container)); + $container['actionManager']->register(new TaskOpen($container)); + $container['actionManager']->register(new TaskUpdateStartDate($container)); + + return $container; + } +} diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 559a78c1..57e63746 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -17,6 +17,7 @@ class ClassProvider implements ServiceProviderInterface private $classes = array( 'Model' => array( 'Action', + 'ActionParameter', 'Authentication', 'Board', 'Category', @@ -90,6 +91,9 @@ class ClassProvider implements ServiceProviderInterface 'Lexer', 'Template', ), + 'Core\Event' => array( + 'EventManager', + ), 'Core\Http' => array( 'Request', 'Response', diff --git a/app/ServiceProvider/EventDispatcherProvider.php b/app/ServiceProvider/EventDispatcherProvider.php index 17141fd4..6cb302e6 100644 --- a/app/ServiceProvider/EventDispatcherProvider.php +++ b/app/ServiceProvider/EventDispatcherProvider.php @@ -30,9 +30,6 @@ class EventDispatcherProvider implements ServiceProviderInterface $container['dispatcher']->addSubscriber(new TransitionSubscriber($container)); $container['dispatcher']->addSubscriber(new RecurringTaskSubscriber($container)); - // Automatic actions - $container['action']->attachEvents(); - return $container; } } diff --git a/app/Subscriber/BootstrapSubscriber.php b/app/Subscriber/BootstrapSubscriber.php index e399f688..d114bf86 100644 --- a/app/Subscriber/BootstrapSubscriber.php +++ b/app/Subscriber/BootstrapSubscriber.php @@ -3,21 +3,26 @@ namespace Kanboard\Subscriber; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Kanboard\Core\Base; -class BootstrapSubscriber extends \Kanboard\Core\Base implements EventSubscriberInterface +class BootstrapSubscriber extends Base implements EventSubscriberInterface { public static function getSubscribedEvents() { return array( - 'app.bootstrap' => array('setup', 0), + 'app.bootstrap' => 'execute', ); } - public function setup() + public function execute() { $this->config->setupTranslations(); $this->config->setupTimezone(); - $this->sessionStorage->hasSubtaskInProgress = $this->subtask->hasSubtaskInProgress($this->userSession->getId()); + $this->actionManager->attachEvents(); + + if ($this->userSession->isLogged()) { + $this->sessionStorage->hasSubtaskInProgress = $this->subtask->hasSubtaskInProgress($this->userSession->getId()); + } } public function __destruct() diff --git a/app/Template/action/index.php b/app/Template/action/index.php index bf2f7475..8275f080 100644 --- a/app/Template/action/index.php +++ b/app/Template/action/index.php @@ -28,24 +28,24 @@
    - + $param_value): ?>
  • - text->in($param['name'], $available_params) ?> = + text->in($param_name, $available_params[$action['action_name']]) ?> = - text->contains($param['name'], 'column_id')): ?> - text->in($param['value'], $columns_list) ?> - text->contains($param['name'], 'user_id')): ?> - text->in($param['value'], $users_list) ?> - text->contains($param['name'], 'project_id')): ?> - text->in($param['value'], $projects_list) ?> - text->contains($param['name'], 'color_id')): ?> - text->in($param['value'], $colors_list) ?> - text->contains($param['name'], 'category_id')): ?> - text->in($param['value'], $categories_list) ?> - text->contains($param['name'], 'link_id')): ?> - text->in($param['value'], $links_list) ?> + text->contains($param_name, 'column_id')): ?> + text->in($param_value, $columns_list) ?> + text->contains($param_name, 'user_id')): ?> + text->in($param_value, $users_list) ?> + text->contains($param_name, 'project_id')): ?> + text->in($param_value, $projects_list) ?> + text->contains($param_name, 'color_id')): ?> + text->in($param_value, $colors_list) ?> + text->contains($param_name, 'category_id')): ?> + text->in($param_value, $categories_list) ?> + text->contains($param_name, 'link_id')): ?> + text->in($param_value, $links_list) ?> - e($param['value']) ?> + e($param_value) ?>
  • diff --git a/app/common.php b/app/common.php index 91e24c65..fe287811 100644 --- a/app/common.php +++ b/app/common.php @@ -33,4 +33,5 @@ $container->register(new Kanboard\ServiceProvider\ClassProvider); $container->register(new Kanboard\ServiceProvider\EventDispatcherProvider); $container->register(new Kanboard\ServiceProvider\GroupProvider); $container->register(new Kanboard\ServiceProvider\RouteProvider); +$container->register(new Kanboard\ServiceProvider\ActionProvider); $container->register(new Kanboard\ServiceProvider\PluginProvider); diff --git a/doc/api-action-procedures.markdown b/doc/api-action-procedures.markdown index 5dd88f4a..67bd85de 100644 --- a/doc/api-action-procedures.markdown +++ b/doc/api-action-procedures.markdown @@ -25,24 +25,24 @@ Response example: "jsonrpc": "2.0", "id": 1217735483, "result": { - "TaskLogMoveAnotherColumn": "Add a comment logging moving the task between columns", - "TaskAssignColorUser": "Assign a color to a specific user", - "TaskAssignColorColumn": "Assign a color when the task is moved to a specific column", - "TaskAssignCategoryColor": "Assign automatically a category based on a color", - "TaskAssignColorCategory": "Assign automatically a color based on a category", - "TaskAssignSpecificUser": "Assign the task to a specific user", - "TaskAssignCurrentUser": "Assign the task to the person who does the action", - "TaskUpdateStartDate": "Automatically update the start date", - "TaskAssignUser": "Change the assignee based on an external username", - "TaskAssignCategoryLabel": "Change the category based on an external label", - "TaskClose": "Close a task", - "CommentCreation": "Create a comment from an external provider", - "TaskCreation": "Create a task from an external provider", - "TaskDuplicateAnotherProject": "Duplicate the task to another project", - "TaskMoveColumnAssigned": "Move the task to another column when assigned to a user", - "TaskMoveColumnUnAssigned": "Move the task to another column when assignee is cleared", - "TaskMoveAnotherProject": "Move the task to another project", - "TaskOpen": "Open a task" + "\Kanboard\Action\TaskLogMoveAnotherColumn": "Add a comment logging moving the task between columns", + "\Kanboard\Action\TaskAssignColorUser": "Assign a color to a specific user", + "\Kanboard\Action\TaskAssignColorColumn": "Assign a color when the task is moved to a specific column", + "\Kanboard\Action\TaskAssignCategoryColor": "Assign automatically a category based on a color", + "\Kanboard\Action\TaskAssignColorCategory": "Assign automatically a color based on a category", + "\Kanboard\Action\TaskAssignSpecificUser": "Assign the task to a specific user", + "\Kanboard\Action\TaskAssignCurrentUser": "Assign the task to the person who does the action", + "\Kanboard\Action\TaskUpdateStartDate": "Automatically update the start date", + "\Kanboard\Action\TaskAssignUser": "Change the assignee based on an external username", + "\Kanboard\Action\TaskAssignCategoryLabel": "Change the category based on an external label", + "\Kanboard\Action\TaskClose": "Close a task", + "\Kanboard\Action\CommentCreation": "Create a comment from an external provider", + "\Kanboard\Action\TaskCreation": "Create a task from an external provider", + "\Kanboard\Action\TaskDuplicateAnotherProject": "Duplicate the task to another project", + "\Kanboard\Action\TaskMoveColumnAssigned": "Move the task to another column when assigned to a user", + "\Kanboard\Action\TaskMoveColumnUnAssigned": "Move the task to another column when assignee is cleared", + "\Kanboard\Action\TaskMoveAnotherProject": "Move the task to another project", + "\Kanboard\Action\TaskOpen": "Open a task" } } ``` @@ -109,7 +109,7 @@ Request example: "method": "getCompatibleActionEvents", "id": 899370297, "params": [ - "TaskClose" + "\Kanboard\Action\TaskClose" ] } ``` @@ -163,7 +163,7 @@ Response example: "id" : "13", "project_id" : "2", "event_name" : "task.move.column", - "action_name" : "TaskAssignSpecificUser", + "action_name" : "\Kanboard\Action\TaskAssignSpecificUser", "params" : { "column_id" : "5", "user_id" : "1" @@ -194,7 +194,7 @@ Request example: "params": { "project_id" : "2", "event_name" : "task.move.column", - "action_name" : "TaskAssignSpecificUser", + "action_name" : "\Kanboard\Action\TaskAssignSpecificUser", "params" : { "column_id" : "3", "user_id" : "2" diff --git a/doc/automatic-actions.markdown b/doc/automatic-actions.markdown index 69352d12..db56ccc0 100644 --- a/doc/automatic-actions.markdown +++ b/doc/automatic-actions.markdown @@ -26,59 +26,33 @@ Add a new action ![Define parameters](http://kanboard.net/screenshots/documentation/project-automatic-action-step3.png) -List of available events ------------------------- - -- Move a task to another column -- Move a task to another position in the same column -- Task modification -- Task creation -- Reopen a task -- Closing a task -- Task creation or modification -- Task assignee change -- Task link created or updated -- Github commit received -- Github issue opened -- Github issue closed -- Github issue reopened -- Github issue assignee change -- Github issue label change -- Github issue comment created -- Gitlab issue opened -- Gitlab issue closed -- Gitlab commit received -- Bitbucket commit received -- Bitbucket issue opened -- Bitbucket issue closed -- Bitbucket issue reopened -- Bitbucket issue assignee change -- Bitbucket issue comment created - List of available actions ------------------------- -- Close the task -- Open a task -- Assign the task to a specific user +- Create a comment from an external provider +- Add a comment log when moving the task between columns +- Assign automatically a category based on a color +- Change the category based on an external label +- Assign automatically a category based on a link +- Assign automatically a color based on a category +- Assign a color when the task is moved to a specific column +- Change task color when using a specific task link +- Assign a color to a specific user - Assign the task to the person who does the action +- Assign the task to the person who does the action when the column is changed +- Assign the task to a specific user +- Change the assignee based on an external username +- Close the task +- Close a task in a specific column +- Create a task from an external provider - Duplicate the task to another project +- Send a task by email to someone - Move the task to another project - Move the task to another column when assigned to a user +- Move the task to another column when the category is changed - Move the task to another column when assignee is cleared -- Assign color when the task is moved to a specific column -- Assign color to a specific user -- Assign automatically a color based on a category -- Assign automatically a category based on a color -- Create a comment from an external provider -- Create a task from an external provider -- Add a comment log when moving the task between columns -- Change the assignee based on an external username -- Change the category based on an external label +- Open a task - Automatically update the start date -- Move the task to another column when the category is changed -- Send a task by email to someone -- Change task color when using a specific task link Examples -------- @@ -87,7 +61,7 @@ Here are some examples used in real life: ### When I move a task to the column "Done", automatically close this task -- Choose action: **Close the task** +- Choose action: **Close a task in a specific column** - Choose the event: **Move a task to another column** - Define action parameter: **Column = Done** (this is the destination column) @@ -99,7 +73,7 @@ Here are some examples used in real life: ### When I move a task to the column "Work in progress", assign this task to the current user -- Choose action: **Assign the task to the person who does the action** +- Choose action: **Assign the task to the person who does the action when the column is changed** - Choose the event: **Move a task to another column** - Define action parameter: **Column = Work in progress** diff --git a/doc/plugin-registration.markdown b/doc/plugin-registration.markdown index 746fa200..37e71f9a 100644 --- a/doc/plugin-registration.markdown +++ b/doc/plugin-registration.markdown @@ -138,40 +138,3 @@ $this->on('app.bootstrap', function($container) { - The first argument is the event name - The second argument is a PHP callable function (closure or class method) - -Extend Automatic Actions ------------------------- - -To define a new automatic action with a plugin, you just need to call the method `extendActions()` from the class `Kanboard\Model\Action`, here an example: - -```php -action->extendActions( - '\Kanboard\Plugin\AutomaticAction\Action\DoSomething', // Use absolute namespace - t('Do something when the task color change') - ); - } -} -``` - -- The first argument of the method `extendActions()` is the action class with the complete namespace path. **The namespace path must starts with a backslash** otherwise Kanboard will not be able to load your class. -- The second argument is the description of your automatic action. - -The automatic action class must inherit from the class `Kanboard\Action\Base` and implements all abstract methods: - -- `getCompatibleEvents()` -- `getActionRequiredParameters()` -- `getEventRequiredParameters()` -- `doAction(array $data)` -- `hasRequiredCondition(array $data)` - -For more details you should take a look to existing automatic actions or this [plugin example](https://github.com/kanboard/plugin-example-automatic-action). diff --git a/tests/functionals/ApiTest.php b/tests/functionals/ApiTest.php index fbb703c9..79d87bd6 100644 --- a/tests/functionals/ApiTest.php +++ b/tests/functionals/ApiTest.php @@ -875,7 +875,7 @@ class Api extends PHPUnit_Framework_TestCase $actions = $this->client->getAvailableActions(); $this->assertNotEmpty($actions); $this->assertInternalType('array', $actions); - $this->assertArrayHasKey('TaskLogMoveAnotherColumn', $actions); + $this->assertArrayHasKey('\Kanboard\Action\TaskClose', $actions); } public function testGetAvailableActionEvents() @@ -888,7 +888,7 @@ class Api extends PHPUnit_Framework_TestCase public function testGetCompatibleActionEvents() { - $events = $this->client->getCompatibleActionEvents('TaskClose'); + $events = $this->client->getCompatibleActionEvents('\Kanboard\Action\TaskCloseColumn'); $this->assertNotEmpty($events); $this->assertInternalType('array', $events); $this->assertArrayHasKey('task.move.column', $events); @@ -896,7 +896,7 @@ class Api extends PHPUnit_Framework_TestCase public function testCreateAction() { - $action_id = $this->client->createAction(1, 'task.move.column', 'TaskClose', array('column_id' => 1)); + $action_id = $this->client->createAction(1, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1)); $this->assertNotFalse($action_id); $this->assertEquals(1, $action_id); } diff --git a/tests/units/Action/BaseActionTest.php b/tests/units/Action/BaseActionTest.php new file mode 100644 index 00000000..1d50c70e --- /dev/null +++ b/tests/units/Action/BaseActionTest.php @@ -0,0 +1,144 @@ + 'Param 1'); + } + + public function getEventRequiredParameters() + { + return array('p1', 'p2'); + } + + public function doAction(array $data) + { + return true; + } + + public function hasRequiredCondition(array $data) + { + return $data['p1'] == $this->getParam('p1'); + } +} + +class BaseActionTest extends Base +{ + public function testGetName() + { + $dummyAction = new DummyAction($this->container); + $this->assertEquals('\\DummyAction', $dummyAction->getName()); + } + + public function testGetDescription() + { + $dummyAction = new DummyAction($this->container); + $this->assertEquals('Dummy Action', $dummyAction->getDescription()); + } + + public function testGetActionRequiredParameters() + { + $dummyAction = new DummyAction($this->container); + $this->assertEquals(array('p1' => 'Param 1'), $dummyAction->getActionRequiredParameters()); + } + + public function testGetEventRequiredParameters() + { + $dummyAction = new DummyAction($this->container); + $this->assertEquals(array('p1', 'p2'), $dummyAction->getEventRequiredParameters()); + } + + public function testGetCompatibleEvents() + { + $dummyAction = new DummyAction($this->container); + $this->assertEquals(array('my.event'), $dummyAction->getCompatibleEvents()); + } + + public function testHasRequiredCondition() + { + $dummyAction = new DummyAction($this->container); + $dummyAction->setParam('p1', 123); + $this->assertTrue($dummyAction->hasRequiredCondition(array('p1' => 123))); + $this->assertFalse($dummyAction->hasRequiredCondition(array('p1' => 456))); + } + + public function testProjectId() + { + $dummyAction = new DummyAction($this->container); + $this->assertInstanceOf('DummyAction', $dummyAction->setProjectId(123)); + $this->assertEquals(123, $dummyAction->getProjectId()); + } + + public function testParam() + { + $dummyAction = new DummyAction($this->container); + $this->assertInstanceOf('DummyAction', $dummyAction->setParam('p1', 123)); + $this->assertEquals(123, $dummyAction->getParam('p1')); + } + + public function testHasCompatibleEvents() + { + $dummyAction = new DummyAction($this->container); + $this->assertTrue($dummyAction->hasCompatibleEvent('my.event')); + $this->assertFalse($dummyAction->hasCompatibleEvent('foobar')); + } + + public function testHasRequiredProject() + { + $dummyAction = new DummyAction($this->container); + $dummyAction->setProjectId(1234); + + $this->assertTrue($dummyAction->hasRequiredProject(array('project_id' => 1234))); + $this->assertFalse($dummyAction->hasRequiredProject(array('project_id' => 1))); + $this->assertFalse($dummyAction->hasRequiredProject(array())); + } + + public function testHasRequiredParameters() + { + $dummyAction = new DummyAction($this->container); + $dummyAction->setProjectId(1234); + + $this->assertTrue($dummyAction->hasRequiredParameters(array('p1' => 12, 'p2' => 34))); + $this->assertFalse($dummyAction->hasRequiredParameters(array('p1' => 12))); + $this->assertFalse($dummyAction->hasRequiredParameters(array())); + } + + public function testAddEvent() + { + $dummyAction = new DummyAction($this->container); + $dummyAction->addEvent('foobar', 'FooBar'); + $dummyAction->addEvent('my.event', 'My Event Overrided'); + + $events = $dummyAction->getEvents(); + $this->assertcount(2, $events); + $this->assertEquals(array('my.event', 'foobar'), $events); + } + + public function testExecuteOnlyOnce() + { + $dummyAction = new DummyAction($this->container); + $dummyAction->setProjectId(1234); + $dummyAction->setParam('p1', 'something'); + $dummyAction->addEvent('foobar', 'FooBar'); + + $event = new GenericEvent(array('project_id' => 1234, 'p1' => 'something', 'p2' => 'abc')); + + $this->assertTrue($dummyAction->execute($event, 'foobar')); + $this->assertFalse($dummyAction->execute($event, 'foobar')); + } +} diff --git a/tests/units/Action/CommentCreationMoveTaskColumnTest.php b/tests/units/Action/CommentCreationMoveTaskColumnTest.php new file mode 100644 index 00000000..87ee86ea --- /dev/null +++ b/tests/units/Action/CommentCreationMoveTaskColumnTest.php @@ -0,0 +1,58 @@ +container['sessionStorage']->user = array('id' => 1); + + $projectModel = new Project($this->container); + $commentModel = new Comment($this->container); + $taskCreationModel = new TaskCreation($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + + $action = new CommentCreationMoveTaskColumn($this->container); + $action->setProjectId(1); + $action->setParam('column_id', 2); + + $this->assertTrue($action->execute($event, Task::EVENT_MOVE_COLUMN)); + + $comment = $commentModel->getById(1); + $this->assertNotEmpty($comment); + $this->assertEquals(1, $comment['task_id']); + $this->assertEquals(1, $comment['user_id']); + $this->assertEquals('Moved to column Ready', $comment['comment']); + } + + public function testWithUserNotLogged() + { + $projectModel = new Project($this->container); + $commentModel = new Comment($this->container); + $taskCreationModel = new TaskCreation($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + + $action = new CommentCreationMoveTaskColumn($this->container); + $action->setProjectId(1); + $action->setParam('column_id', 2); + + $this->assertFalse($action->execute($event, Task::EVENT_MOVE_COLUMN)); + } +} diff --git a/tests/units/Action/CommentCreationTest.php b/tests/units/Action/CommentCreationTest.php index 8a689309..8460a350 100644 --- a/tests/units/Action/CommentCreationTest.php +++ b/tests/units/Action/CommentCreationTest.php @@ -7,119 +7,88 @@ use Kanboard\Model\Task; use Kanboard\Model\TaskCreation; use Kanboard\Model\Comment; use Kanboard\Model\Project; -use Kanboard\Integration\GithubWebhook; +use Kanboard\Model\ProjectUserRole; +use Kanboard\Model\User; use Kanboard\Action\CommentCreation; +use Kanboard\Core\Security\Role; class CommentCreationTest extends Base { - public function testWithoutRequiredParams() + public function testSuccess() { - $action = new CommentCreation($this->container, 1, GithubWebhook::EVENT_ISSUE_COMMENT); - - // We create a task in the first column - $tc = new TaskCreation($this->container); - $p = new Project($this->container); - $c = new Comment($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); - - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'user_id' => 1, - ); - - // Our event should be executed - $this->assertFalse($action->execute(new GenericEvent($event))); - - $comment = $c->getById(1); - $this->assertEmpty($comment); - } + $userModel = new User($this->container); + $projectModel = new Project($this->container); + $projectUserRoleModel = new ProjectUserRole($this->container); + $commentModel = new Comment($this->container); + $taskCreationModel = new TaskCreation($this->container); - public function testWithCommitMessage() - { - $action = new CommentCreation($this->container, 1, GithubWebhook::EVENT_ISSUE_COMMENT); - - // We create a task in the first column - $tc = new TaskCreation($this->container); - $p = new Project($this->container); - $c = new Comment($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); - - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'commit_comment' => 'plop', - ); - - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); - - $comment = $c->getById(1); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(2, $userModel->create(array('username' => 'user1'))); + $this->assertTrue($projectUserRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'comment' => 'test123', 'reference' => 'ref123', 'user_id' => 2)); + + $action = new CommentCreation($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); + + $this->assertTrue($action->execute($event, 'test.event')); + + $comment = $commentModel->getById(1); $this->assertNotEmpty($comment); $this->assertEquals(1, $comment['task_id']); - $this->assertEquals(0, $comment['user_id']); - $this->assertEquals('plop', $comment['comment']); + $this->assertEquals('test123', $comment['comment']); + $this->assertEquals('ref123', $comment['reference']); + $this->assertEquals(2, $comment['user_id']); } - public function testWithUser() + public function testWithUserNotAssignable() { - $action = new CommentCreation($this->container, 1, GithubWebhook::EVENT_ISSUE_COMMENT); - - // We create a task in the first column - $tc = new TaskCreation($this->container); - $p = new Project($this->container); - $c = new Comment($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); - - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'user_id' => 1, - 'comment' => 'youpi', - ); - - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); - - $comment = $c->getById(1); + $userModel = new User($this->container); + $projectModel = new Project($this->container); + $projectUserRoleModel = new ProjectUserRole($this->container); + $commentModel = new Comment($this->container); + $taskCreationModel = new TaskCreation($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(2, $userModel->create(array('username' => 'user1'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'comment' => 'test123', 'user_id' => 2)); + + $action = new CommentCreation($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); + + $this->assertTrue($action->execute($event, 'test.event')); + + $comment = $commentModel->getById(1); $this->assertNotEmpty($comment); $this->assertEquals(1, $comment['task_id']); - $this->assertEquals(1, $comment['user_id']); - $this->assertEquals('youpi', $comment['comment']); + $this->assertEquals('test123', $comment['comment']); + $this->assertEquals('', $comment['reference']); + $this->assertEquals(0, $comment['user_id']); } - public function testWithNoUser() + public function testWithNoComment() { - $action = new CommentCreation($this->container, 1, GithubWebhook::EVENT_ISSUE_COMMENT); - - // We create a task in the first column - $tc = new TaskCreation($this->container); - $p = new Project($this->container); - $c = new Comment($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); - - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'user_id' => 0, - 'comment' => 'youpi', - ); - - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); - - $comment = $c->getById(1); - $this->assertNotEmpty($comment); - $this->assertEquals(1, $comment['task_id']); - $this->assertEquals(0, $comment['user_id']); - $this->assertEquals('youpi', $comment['comment']); + $userModel = new User($this->container); + $projectModel = new Project($this->container); + $projectUserRoleModel = new ProjectUserRole($this->container); + $commentModel = new Comment($this->container); + $taskCreationModel = new TaskCreation($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(2, $userModel->create(array('username' => 'user1'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1)); + + $action = new CommentCreation($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); + + $this->assertFalse($action->execute($event, 'test.event')); } } diff --git a/tests/units/Action/TaskAssignCategoryColorTest.php b/tests/units/Action/TaskAssignCategoryColorTest.php new file mode 100644 index 00000000..bd8181e8 --- /dev/null +++ b/tests/units/Action/TaskAssignCategoryColorTest.php @@ -0,0 +1,60 @@ +container); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'color_id' => 'red')); + + $action = new TaskAssignCategoryColor($this->container); + $action->setProjectId(1); + $action->setParam('color_id', 'red'); + $action->setParam('category_id', 1); + + $this->assertTrue($action->execute($event, Task::EVENT_CREATE_UPDATE)); + + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(1, $task['category_id']); + } + + public function testWithWrongColor() + { + $categoryModel = new Category($this->container); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'color_id' => 'blue')); + + $action = new TaskAssignCategoryColor($this->container); + $action->setProjectId(1); + $action->setParam('color_id', 'red'); + $action->setParam('category_id', 1); + + $this->assertFalse($action->execute($event, Task::EVENT_CREATE_UPDATE)); + } +} diff --git a/tests/units/Action/TaskAssignCategoryLabelTest.php b/tests/units/Action/TaskAssignCategoryLabelTest.php new file mode 100644 index 00000000..bf8bdb5b --- /dev/null +++ b/tests/units/Action/TaskAssignCategoryLabelTest.php @@ -0,0 +1,85 @@ +container); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'label' => 'foobar')); + + $action = new TaskAssignCategoryLabel($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); + $action->setParam('label', 'foobar'); + $action->setParam('category_id', 1); + + $this->assertTrue($action->execute($event, 'test.event')); + + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(1, $task['category_id']); + } + + public function testWithWrongLabel() + { + $categoryModel = new Category($this->container); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'label' => 'something')); + + $action = new TaskAssignCategoryLabel($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); + $action->setParam('label', 'foobar'); + $action->setParam('category_id', 1); + + $this->assertFalse($action->execute($event, 'test.event')); + } + + public function testWithExistingCategory() + { + $categoryModel = new Category($this->container); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); + $this->assertEquals(2, $categoryModel->create(array('name' => 'c2', 'project_id' => 1))); + + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test', 'category_id' => 2))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'label' => 'foobar', 'category_id' => 2)); + + $action = new TaskAssignCategoryLabel($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); + $action->setParam('label', 'foobar'); + $action->setParam('category_id', 1); + + $this->assertFalse($action->execute($event, 'test.event')); + } +} diff --git a/tests/units/Action/TaskAssignCategoryLinkTest.php b/tests/units/Action/TaskAssignCategoryLinkTest.php index 4f2d757e..f638e017 100644 --- a/tests/units/Action/TaskAssignCategoryLinkTest.php +++ b/tests/units/Action/TaskAssignCategoryLinkTest.php @@ -20,7 +20,8 @@ class TaskAssignCategoryLinkTest extends Base $p = new Project($this->container); $c = new Category($this->container); - $action = new TaskAssignCategoryLink($this->container, 1, TaskLink::EVENT_CREATE_UPDATE); + $action = new TaskAssignCategoryLink($this->container); + $action->setProjectId(1); $action->setParam('category_id', 1); $action->setParam('link_id', 2); @@ -28,30 +29,28 @@ class TaskAssignCategoryLinkTest extends Base $this->assertEquals(1, $c->create(array('name' => 'C1', 'project_id' => 1))); $this->assertEquals(1, $tc->create(array('title' => 'T1', 'project_id' => 1))); - $task = $tf->getById(1); - $this->assertEquals(0, $task['category_id']); - - $event = array( + $event = new TaskLinkEvent(array( 'project_id' => 1, 'task_id' => 1, 'opposite_task_id' => 2, 'link_id' => 2, - ); + )); - $this->assertTrue($action->execute(new TaskLinkEvent($event))); + $this->assertTrue($action->execute($event, TaskLink::EVENT_CREATE_UPDATE)); $task = $tf->getById(1); $this->assertEquals(1, $task['category_id']); } - public function testThatLinkDontMatch() + public function testWhenLinkDontMatch() { $tc = new TaskCreation($this->container); $tf = new TaskFinder($this->container); $p = new Project($this->container); $c = new Category($this->container); - $action = new TaskAssignCategoryLink($this->container, 1, TaskLink::EVENT_CREATE_UPDATE); + $action = new TaskAssignCategoryLink($this->container); + $action->setProjectId(1); $action->setParam('category_id', 1); $action->setParam('link_id', 1); @@ -59,14 +58,14 @@ class TaskAssignCategoryLinkTest extends Base $this->assertEquals(1, $c->create(array('name' => 'C1', 'project_id' => 1))); $this->assertEquals(1, $tc->create(array('title' => 'T1', 'project_id' => 1))); - $event = array( + $event = new TaskLinkEvent(array( 'project_id' => 1, 'task_id' => 1, 'opposite_task_id' => 2, 'link_id' => 2, - ); + )); - $this->assertFalse($action->execute(new TaskLinkEvent($event))); + $this->assertFalse($action->execute($event, TaskLink::EVENT_CREATE_UPDATE)); } public function testThatExistingCategoryWillNotChange() @@ -76,7 +75,8 @@ class TaskAssignCategoryLinkTest extends Base $p = new Project($this->container); $c = new Category($this->container); - $action = new TaskAssignCategoryLink($this->container, 1, TaskLink::EVENT_CREATE_UPDATE); + $action = new TaskAssignCategoryLink($this->container); + $action->setProjectId(1); $action->setParam('category_id', 2); $action->setParam('link_id', 2); @@ -85,13 +85,13 @@ class TaskAssignCategoryLinkTest extends Base $this->assertEquals(2, $c->create(array('name' => 'C2', 'project_id' => 1))); $this->assertEquals(1, $tc->create(array('title' => 'T1', 'project_id' => 1, 'category_id' => 1))); - $event = array( + $event = new TaskLinkEvent(array( 'project_id' => 1, 'task_id' => 1, 'opposite_task_id' => 2, 'link_id' => 2, - ); + )); - $this->assertFalse($action->execute(new TaskLinkEvent($event))); + $this->assertFalse($action->execute($event, TaskLink::EVENT_CREATE_UPDATE)); } } diff --git a/tests/units/Action/TaskAssignColorCategoryTest.php b/tests/units/Action/TaskAssignColorCategoryTest.php index 1bd3493b..9f188645 100644 --- a/tests/units/Action/TaskAssignColorCategoryTest.php +++ b/tests/units/Action/TaskAssignColorCategoryTest.php @@ -2,80 +2,58 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Model\Task; +use Kanboard\Event\GenericEvent; +use Kanboard\Model\Category; use Kanboard\Model\TaskCreation; use Kanboard\Model\TaskFinder; use Kanboard\Model\Project; -use Kanboard\Model\Category; -use Kanboard\Event\GenericEvent; +use Kanboard\Model\Task; use Kanboard\Action\TaskAssignColorCategory; class TaskAssignColorCategoryTest extends Base { - public function testBadProject() + public function testChangeColor() { - $action = new TaskAssignColorCategory($this->container, 3, Task::EVENT_CREATE_UPDATE); + $categoryModel = new Category($this->container); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); - $event = array( - 'project_id' => 2, - 'task_id' => 3, - 'column_id' => 5, - ); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); - $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute(new GenericEvent($event))); - } + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'category_id' => 1)); - public function testExecute() - { - $action = new TaskAssignColorCategory($this->container, 1, Task::EVENT_CREATE_UPDATE); + $action = new TaskAssignColorCategory($this->container); + $action->setProjectId(1); + $action->setParam('color_id', 'red'); $action->setParam('category_id', 1); - $action->setParam('color_id', 'blue'); - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($this->container); - $c = new Category($this->container); + $this->assertTrue($action->execute($event, Task::EVENT_CREATE_UPDATE)); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $c->create(array('name' => 'c1', 'project_id' => 1))); - $this->assertEquals(2, $c->create(array('name' => 'c2', 'project_id' => 1))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1, 'color_id' => 'green', 'category_id' => 2))); + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals('red', $task['color_id']); + } - // We create an event but we don't do anything - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 1, - 'category_id' => 2, - 'position' => 2, - ); + public function testWithWrongCategory() + { + $categoryModel = new Category($this->container); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); - // Our event should NOT be executed - $this->assertFalse($action->execute(new GenericEvent($event))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - // Our task should be assigned to the ategory_id=1 and have the green color - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(2, $task['category_id']); - $this->assertEquals('green', $task['color_id']); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'category_id' => 2)); - // We create an event to move the task - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 1, - 'position' => 5, - 'category_id' => 1, - ); - - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); + $action = new TaskAssignColorCategory($this->container); + $action->setProjectId(1); + $action->setParam('color_id', 'red'); + $action->setParam('category_id', 1); - // Our task should have the blue color - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals('blue', $task['color_id']); + $this->assertFalse($action->execute($event, Task::EVENT_CREATE_UPDATE)); } } diff --git a/tests/units/Action/TaskAssignColorColumnTest.php b/tests/units/Action/TaskAssignColorColumnTest.php index c09dc96e..e5858b19 100644 --- a/tests/units/Action/TaskAssignColorColumnTest.php +++ b/tests/units/Action/TaskAssignColorColumnTest.php @@ -3,40 +3,53 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; -use Kanboard\Model\Task; use Kanboard\Model\TaskCreation; use Kanboard\Model\TaskFinder; use Kanboard\Model\Project; +use Kanboard\Model\Task; use Kanboard\Action\TaskAssignColorColumn; class TaskAssignColorColumnTest extends Base { - public function testColorChange() + public function testChangeColumn() { - $action = new TaskAssignColorColumn($this->container, 1, Task::EVENT_MOVE_COLUMN); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + + $action = new TaskAssignColorColumn($this->container); + $action->setProjectId(1); + $action->setParam('color_id', 'red'); $action->setParam('column_id', 2); - $action->setParam('color_id', 'green'); - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($this->container); + $this->assertTrue($action->execute($event, Task::EVENT_MOVE_COLUMN)); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1, 'color_id' => 'yellow'))); + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals('red', $task['color_id']); + } + + public function testWithWrongCategory() + { + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 2, - 'color_id' => 'green', - ); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + + $action = new TaskAssignColorColumn($this->container); + $action->setProjectId(1); + $action->setParam('color_id', 'red'); + $action->setParam('column_id', 2); - // Our task should have color green - $task = $tf->getById(1); - $this->assertEquals('green', $task['color_id']); + $this->assertFalse($action->execute($event, Task::EVENT_MOVE_COLUMN)); } } diff --git a/tests/units/Action/TaskAssignColorLinkTest.php b/tests/units/Action/TaskAssignColorLinkTest.php index 36a831dd..d89c8b06 100644 --- a/tests/units/Action/TaskAssignColorLinkTest.php +++ b/tests/units/Action/TaskAssignColorLinkTest.php @@ -2,47 +2,54 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\TaskLinkEvent; -use Kanboard\Model\Task; +use Kanboard\Event\GenericEvent; use Kanboard\Model\TaskCreation; use Kanboard\Model\TaskFinder; -use Kanboard\Model\TaskLink; use Kanboard\Model\Project; +use Kanboard\Model\TaskLink; use Kanboard\Action\TaskAssignColorLink; class TaskAssignColorLinkTest extends Base { - public function testExecute() + public function testChangeColor() { - $action = new TaskAssignColorLink($this->container, 1, TaskLink::EVENT_CREATE_UPDATE); - $action->setParam('link_id', 2); - $action->setParam('color_id', 'green'); - - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $tl = new TaskLink($this->container); - $p = new Project($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - - // The color should be yellow - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals('yellow', $task['color_id']); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'link_id' => 2, - ); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - // Our event should be executed - $this->assertTrue($action->execute(new TaskLinkEvent($event))); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'link_id' => 1)); - // The color should be green - $task = $tf->getById(1); + $action = new TaskAssignColorLink($this->container); + $action->setProjectId(1); + $action->setParam('color_id', 'red'); + $action->setParam('link_id', 1); + + $this->assertTrue($action->execute($event, TaskLink::EVENT_CREATE_UPDATE)); + + $task = $taskFinderModel->getById(1); $this->assertNotEmpty($task); - $this->assertEquals('green', $task['color_id']); + $this->assertEquals('red', $task['color_id']); + } + + public function testWithWrongLink() + { + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'link_id' => 2)); + + $action = new TaskAssignColorLink($this->container); + $action->setProjectId(1); + $action->setParam('color_id', 'red'); + $action->setParam('link_id', 1); + + $this->assertFalse($action->execute($event, TaskLink::EVENT_CREATE_UPDATE)); } } diff --git a/tests/units/Action/TaskAssignColorUserTest.php b/tests/units/Action/TaskAssignColorUserTest.php index ea2a8f38..e2656cc0 100644 --- a/tests/units/Action/TaskAssignColorUserTest.php +++ b/tests/units/Action/TaskAssignColorUserTest.php @@ -2,72 +2,54 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Model\Task; +use Kanboard\Event\GenericEvent; use Kanboard\Model\TaskCreation; use Kanboard\Model\TaskFinder; use Kanboard\Model\Project; -use Kanboard\Event\GenericEvent; +use Kanboard\Model\Task; use Kanboard\Action\TaskAssignColorUser; class TaskAssignColorUserTest extends Base { - public function testBadProject() + public function testChangeColor() { - $action = new TaskAssignColorUser($this->container, 3, Task::EVENT_CREATE); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); - $event = array( - 'project_id' => 2, - 'task_id' => 3, - 'column_id' => 5, - ); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute(new GenericEvent($event))); - } + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'owner_id' => 1)); - public function testExecute() - { - $action = new TaskAssignColorUser($this->container, 1, Task::EVENT_ASSIGNEE_CHANGE); + $action = new TaskAssignColorUser($this->container); + $action->setProjectId(1); + $action->setParam('color_id', 'red'); $action->setParam('user_id', 1); - $action->setParam('color_id', 'blue'); - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1, 'color_id' => 'green'))); + $this->assertTrue($action->execute($event, Task::EVENT_ASSIGNEE_CHANGE)); - // We change the assignee - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'owner_id' => 5, - ); + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals('red', $task['color_id']); + } - // Our event should NOT be executed - $this->assertFalse($action->execute(new GenericEvent($event))); + public function testWithWrongUser() + { + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); - // Our task should be assigned to nobody and have the green color - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['owner_id']); - $this->assertEquals('green', $task['color_id']); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - // We change the assignee - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'owner_id' => 1, - ); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'owner_id' => 2)); - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); + $action = new TaskAssignColorUser($this->container); + $action->setProjectId(1); + $action->setParam('color_id', 'red'); + $action->setParam('user_id', 1); - // Our task should be assigned to nobody and have the blue color - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['owner_id']); - $this->assertEquals('blue', $task['color_id']); + $this->assertFalse($action->execute($event, Task::EVENT_ASSIGNEE_CHANGE)); } } diff --git a/tests/units/Action/TaskAssignCurrentUserColumnTest.php b/tests/units/Action/TaskAssignCurrentUserColumnTest.php new file mode 100644 index 00000000..41576ee4 --- /dev/null +++ b/tests/units/Action/TaskAssignCurrentUserColumnTest.php @@ -0,0 +1,75 @@ +container['sessionStorage']->user = array('id' => 1); + + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + + $action = new TaskAssignCurrentUserColumn($this->container); + $action->setProjectId(1); + $action->setParam('column_id', 2); + + $this->assertTrue($action->execute($event, Task::EVENT_MOVE_COLUMN)); + + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(1, $task['owner_id']); + } + + public function testWithWrongColumn() + { + $this->container['sessionStorage']->user = array('id' => 1); + + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + + $action = new TaskAssignCurrentUserColumn($this->container); + $action->setProjectId(1); + $action->setParam('column_id', 2); + + $this->assertFalse($action->execute($event, Task::EVENT_MOVE_COLUMN)); + } + + public function testWithNoUserSession() + { + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + + $action = new TaskAssignCurrentUserColumn($this->container); + $action->setProjectId(1); + $action->setParam('column_id', 2); + + $this->assertFalse($action->execute($event, Task::EVENT_MOVE_COLUMN)); + } +} diff --git a/tests/units/Action/TaskAssignCurrentUserTest.php b/tests/units/Action/TaskAssignCurrentUserTest.php index e2d1c11a..2fe84a5d 100644 --- a/tests/units/Action/TaskAssignCurrentUserTest.php +++ b/tests/units/Action/TaskAssignCurrentUserTest.php @@ -3,73 +3,51 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; -use Kanboard\Model\Task; use Kanboard\Model\TaskCreation; use Kanboard\Model\TaskFinder; use Kanboard\Model\Project; -use Kanboard\Core\User\UserSession; +use Kanboard\Model\Task; use Kanboard\Action\TaskAssignCurrentUser; class TaskAssignCurrentUserTest extends Base { - public function testBadProject() + public function testChangeUser() { - $action = new TaskAssignCurrentUser($this->container, 3, Task::EVENT_CREATE); - $action->setParam('column_id', 5); + $this->container['sessionStorage']->user = array('id' => 1); - $event = array( - 'project_id' => 2, - 'task_id' => 3, - 'column_id' => 5, - ); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); - $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute(new GenericEvent($event))); - } + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - public function testBadColumn() - { - $action = new TaskAssignCurrentUser($this->container, 3, Task::EVENT_CREATE); - $action->setParam('column_id', 5); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1)); + + $action = new TaskAssignCurrentUser($this->container); + $action->setProjectId(1); - $event = array( - 'project_id' => 3, - 'task_id' => 3, - 'column_id' => 3, - ); + $this->assertTrue($action->execute($event, Task::EVENT_CREATE)); - $this->assertFalse($action->execute(new GenericEvent($event))); + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(1, $task['owner_id']); } - public function testExecute() + public function testWithNoUserSession() { - $this->container['sessionStorage']->user = array('id' => 5); - - $action = new TaskAssignCurrentUser($this->container, 1, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 2); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($this->container); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1)); - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 2, - ); + $action = new TaskAssignCurrentUser($this->container); + $action->setProjectId(1); - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); - - // Our task should be assigned to the user 5 (from the session) - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(1, $task['id']); - $this->assertEquals(5, $task['owner_id']); + $this->assertFalse($action->execute($event, Task::EVENT_CREATE)); } } diff --git a/tests/units/Action/TaskAssignSpecificUserTest.php b/tests/units/Action/TaskAssignSpecificUserTest.php index a67335e8..67b2c397 100644 --- a/tests/units/Action/TaskAssignSpecificUserTest.php +++ b/tests/units/Action/TaskAssignSpecificUserTest.php @@ -3,69 +3,53 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; -use Kanboard\Model\Task; use Kanboard\Model\TaskCreation; use Kanboard\Model\TaskFinder; use Kanboard\Model\Project; +use Kanboard\Model\Task; use Kanboard\Action\TaskAssignSpecificUser; class TaskAssignSpecificUserTest extends Base { - public function testBadProject() + public function testChangeUser() { - $action = new TaskAssignSpecificUser($this->container, 3, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 5); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); - $event = array( - 'project_id' => 2, - 'task_id' => 3, - 'column_id' => 5, - ); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test', 'owner_id' => 0))); - $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute(new GenericEvent($event))); - } + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); - public function testBadColumn() - { - $action = new TaskAssignSpecificUser($this->container, 3, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 5); + $action = new TaskAssignSpecificUser($this->container); + $action->setProjectId(1); + $action->setParam('column_id', 2); + $action->setParam('user_id', 1); - $event = array( - 'project_id' => 3, - 'task_id' => 3, - 'column_id' => 3, - ); + $this->assertTrue($action->execute($event, Task::EVENT_MOVE_COLUMN)); - $this->assertFalse($action->execute(new GenericEvent($event))); + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(1, $task['owner_id']); } - public function testExecute() + public function testWithWrongColumn() { - $action = new TaskAssignSpecificUser($this->container, 1, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 2); - $action->setParam('user_id', 1); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 2, - ); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); + $action = new TaskAssignSpecificUser($this->container); + $action->setProjectId(1); + $action->setParam('column_id', 2); + $action->setParam('user_id', 1); - // Our task should be assigned to the user 1 - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(1, $task['owner_id']); + $this->assertFalse($action->execute($event, Task::EVENT_MOVE_COLUMN)); } } diff --git a/tests/units/Action/TaskAssignUserTest.php b/tests/units/Action/TaskAssignUserTest.php new file mode 100644 index 00000000..d1cb72b9 --- /dev/null +++ b/tests/units/Action/TaskAssignUserTest.php @@ -0,0 +1,62 @@ +container); + $projectModel = new Project($this->container); + $projectUserRoleModel = new ProjectUserRole($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test', 'owner_id' => 0))); + $this->assertEquals(2, $userModel->create(array('username' => 'user1'))); + $this->assertTrue($projectUserRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'owner_id' => 2)); + + $action = new TaskAssignUser($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); + + $this->assertTrue($action->execute($event, 'test.event')); + + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(2, $task['owner_id']); + } + + public function testWithNotAssignableUser() + { + $userModel = new User($this->container); + $projectModel = new Project($this->container); + $projectUserRoleModel = new ProjectUserRole($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'owner_id' => 1)); + + $action = new TaskAssignUser($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); + + $this->assertFalse($action->execute($event, 'test.event')); + } +} diff --git a/tests/units/Action/TaskCloseColumnTest.php b/tests/units/Action/TaskCloseColumnTest.php new file mode 100644 index 00000000..ce41bb41 --- /dev/null +++ b/tests/units/Action/TaskCloseColumnTest.php @@ -0,0 +1,53 @@ +container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + + $action = new TaskCloseColumn($this->container); + $action->setProjectId(1); + $action->setParam('column_id', 2); + + $this->assertTrue($action->execute($event, Task::EVENT_MOVE_COLUMN)); + + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['is_active']); + } + + public function testWithWrongColumn() + { + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + + $action = new TaskCloseColumn($this->container); + $action->setProjectId(1); + $action->setParam('column_id', 2); + + $this->assertFalse($action->execute($event, Task::EVENT_MOVE_COLUMN)); + } +} diff --git a/tests/units/Action/TaskCloseTest.php b/tests/units/Action/TaskCloseTest.php index b2d83194..536d79ca 100644 --- a/tests/units/Action/TaskCloseTest.php +++ b/tests/units/Action/TaskCloseTest.php @@ -3,107 +3,49 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; -use Kanboard\Model\Task; use Kanboard\Model\TaskCreation; use Kanboard\Model\TaskFinder; use Kanboard\Model\Project; -use Kanboard\Integration\GithubWebhook; use Kanboard\Action\TaskClose; class TaskCloseTest extends Base { - public function testExecutable() + public function testClose() { - $action = new TaskClose($this->container, 3, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 5); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); - $event = array( - 'project_id' => 3, - 'task_id' => 3, - 'column_id' => 5, - ); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $this->assertTrue($action->isExecutable($event)); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1)); - $action = new TaskClose($this->container, 3, GithubWebhook::EVENT_COMMIT); + $action = new TaskClose($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); - $event = array( - 'project_id' => 3, - 'task_id' => 3, - ); + $this->assertTrue($action->execute($event, 'test.event')); - $this->assertTrue($action->isExecutable($event)); - } - - public function testBadEvent() - { - $action = new TaskClose($this->container, 3, Task::EVENT_UPDATE); - $action->setParam('column_id', 5); - - $event = array( - 'project_id' => 3, - 'task_id' => 3, - 'column_id' => 5, - ); - - $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute(new GenericEvent($event))); - } - - public function testBadProject() - { - $action = new TaskClose($this->container, 3, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 5); - - $event = array( - 'project_id' => 2, - 'task_id' => 3, - 'column_id' => 5, - ); - - $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute(new GenericEvent($event))); - } - - public function testBadColumn() - { - $action = new TaskClose($this->container, 3, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 5); - - $event = array( - 'project_id' => 3, - 'task_id' => 3, - 'column_id' => 3, - ); - - $this->assertFalse($action->execute(new GenericEvent($event))); + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['is_active']); } - public function testExecute() + public function testWithNoTaskId() { - $action = new TaskClose($this->container, 1, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 2); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 2, - ); + $event = new GenericEvent(array('project_id' => 1)); - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); + $action = new TaskClose($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); - // Our task should be closed - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['is_active']); + $this->assertFalse($action->execute($event, 'test.event')); } } diff --git a/tests/units/Action/TaskCreationTest.php b/tests/units/Action/TaskCreationTest.php new file mode 100644 index 00000000..57c2995d --- /dev/null +++ b/tests/units/Action/TaskCreationTest.php @@ -0,0 +1,49 @@ +container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'title' => 'test123', 'reference' => 'ref123', 'description' => 'test')); + + $action = new TaskCreationAction($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); + + $this->assertTrue($action->execute($event, 'test.event')); + + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals('test123', $task['title']); + $this->assertEquals('ref123', $task['reference']); + $this->assertEquals('test', $task['description']); + } + + public function testWithNoTitle() + { + $projectModel = new Project($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'reference' => 'ref123', 'description' => 'test')); + + $action = new TaskCreationAction($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); + + $this->assertFalse($action->execute($event, 'test.event')); + } +} diff --git a/tests/units/Action/TaskDuplicateAnotherProjectTest.php b/tests/units/Action/TaskDuplicateAnotherProjectTest.php index 50cbad01..d9491dd9 100644 --- a/tests/units/Action/TaskDuplicateAnotherProjectTest.php +++ b/tests/units/Action/TaskDuplicateAnotherProjectTest.php @@ -4,92 +4,53 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; use Kanboard\Model\Task; -use Kanboard\Model\TaskCreation; use Kanboard\Model\TaskFinder; +use Kanboard\Model\TaskCreation; use Kanboard\Model\Project; use Kanboard\Action\TaskDuplicateAnotherProject; class TaskDuplicateAnotherProjectTest extends Base { - public function testBadProject() + public function testSuccess() { - $action = new TaskDuplicateAnotherProject($this->container, 3, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 5); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); - $event = array( - 'project_id' => 2, - 'task_id' => 3, - 'column_id' => 5, - ); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute(new GenericEvent($event))); - } + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); - public function testBadColumn() - { - $action = new TaskDuplicateAnotherProject($this->container, 3, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 5); + $action = new TaskDuplicateAnotherProject($this->container); + $action->setProjectId(1); + $action->setParam('project_id', 2); + $action->setParam('column_id', 2); - $event = array( - 'project_id' => 3, - 'task_id' => 3, - 'column_id' => 3, - ); + $this->assertTrue($action->execute($event, Task::EVENT_CLOSE)); - $this->assertFalse($action->execute(new GenericEvent($event))); + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals('test', $task['title']); + $this->assertEquals(2, $task['project_id']); } - public function testExecute() + public function testWithWrongColumn() { - $action = new TaskDuplicateAnotherProject($this->container, 1, Task::EVENT_MOVE_COLUMN); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($this->container); - $this->assertEquals(1, $p->create(array('name' => 'project 1'))); - $this->assertEquals(2, $p->create(array('name' => 'project 2'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 2, - ); - - // Our event should NOT be executed because we define the same project - $action->setParam('column_id', 2); - $action->setParam('project_id', 1); - $this->assertFalse($action->execute(new GenericEvent($event))); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); - // Our task should be assigned to the project 1 - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(1, $task['project_id']); - - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 2, - ); - - // Our event should be executed because we define a different project - $action->setParam('column_id', 2); + $action = new TaskDuplicateAnotherProject($this->container); + $action->setProjectId(1); $action->setParam('project_id', 2); - $this->assertTrue($action->hasRequiredCondition($event)); - $this->assertTrue($action->execute(new GenericEvent($event))); - - // Our task should be assigned to the project 1 - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(1, $task['project_id']); + $action->setParam('column_id', 2); - // We should have another task assigned to the project 2 - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(2, $task['project_id']); + $this->assertFalse($action->execute($event, Task::EVENT_CLOSE)); } } diff --git a/tests/units/Action/TaskEmailTest.php b/tests/units/Action/TaskEmailTest.php index 404865f4..ef32a296 100644 --- a/tests/units/Action/TaskEmailTest.php +++ b/tests/units/Action/TaskEmailTest.php @@ -5,98 +5,30 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; use Kanboard\Model\Task; use Kanboard\Model\TaskCreation; -use Kanboard\Model\TaskFinder; use Kanboard\Model\Project; use Kanboard\Model\User; use Kanboard\Action\TaskEmail; class TaskEmailTest extends Base { - public function testNoEmail() + public function testSuccess() { - $action = new TaskEmail($this->container, 1, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 2); - $action->setParam('user_id', 1); - $action->setParam('subject', 'My email subject'); - - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($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, 'column_id' => 1))); + $userModel = new User($this->container); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 2, - ); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertTrue($userModel->update(array('id' => 1, 'email' => 'admin@localhost'))); - // Email should be not be sent - $this->container['emailClient']->expects($this->never())->method('send'); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); - // Our event should be executed - $this->assertFalse($action->execute(new GenericEvent($event))); - } - - public function testWrongColumn() - { - $action = new TaskEmail($this->container, 1, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 2); - $action->setParam('user_id', 1); - $action->setParam('subject', 'My email subject'); - - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($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, 'column_id' => 1))); - - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 3, - ); - - // Email should be not be sent - $this->container['emailClient']->expects($this->never())->method('send'); - - // Our event should be executed - $this->assertFalse($action->execute(new GenericEvent($event))); - } - - public function testMoveColumn() - { - $action = new TaskEmail($this->container, 1, Task::EVENT_MOVE_COLUMN); + $action = new TaskEmail($this->container); + $action->setProjectId(1); $action->setParam('column_id', 2); $action->setParam('user_id', 1); $action->setParam('subject', 'My email subject'); - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($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, 'column_id' => 1))); - $this->assertTrue($u->update(array('id' => 1, 'email' => 'admin@localhost'))); - - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 2, - ); - - // Email should be sent $this->container['emailClient']->expects($this->once()) ->method('send') ->with( @@ -106,45 +38,24 @@ class TaskEmailTest extends Base $this->stringContains('test') ); - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); + $this->assertTrue($action->execute($event, Task::EVENT_CLOSE)); } - public function testTaskClose() + public function testWithWrongColumn() { - $action = new TaskEmail($this->container, 1, Task::EVENT_CLOSE); - $action->setParam('column_id', 2); - $action->setParam('user_id', 1); - $action->setParam('subject', 'My email subject'); - - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($this->container); - $u = new User($this->container); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); - $this->assertTrue($u->update(array('id' => 1, 'email' => 'admin@localhost'))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - // We create an event - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 2, - ); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); - // Email should be sent - $this->container['emailClient']->expects($this->once()) - ->method('send') - ->with( - $this->equalTo('admin@localhost'), - $this->equalTo('admin'), - $this->equalTo('My email subject'), - $this->stringContains('test') - ); + $action = new TaskEmail($this->container); + $action->setProjectId(1); + $action->setParam('column_id', 2); + $action->setParam('user_id', 1); + $action->setParam('subject', 'My email subject'); - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); + $this->assertFalse($action->execute($event, Task::EVENT_CLOSE)); } } diff --git a/tests/units/Action/TaskMoveAnotherProjectTest.php b/tests/units/Action/TaskMoveAnotherProjectTest.php index 93ee3b94..dfabe5f8 100644 --- a/tests/units/Action/TaskMoveAnotherProjectTest.php +++ b/tests/units/Action/TaskMoveAnotherProjectTest.php @@ -4,86 +4,54 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; use Kanboard\Model\Task; -use Kanboard\Model\TaskCreation; use Kanboard\Model\TaskFinder; +use Kanboard\Model\TaskCreation; use Kanboard\Model\Project; use Kanboard\Action\TaskMoveAnotherProject; class TaskMoveAnotherProjectTest extends Base { - public function testBadProject() + public function testSuccess() { - $action = new TaskMoveAnotherProject($this->container, 3, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 5); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); - $event = array( - 'project_id' => 2, - 'task_id' => 3, - 'column_id' => 5, - ); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $this->assertFalse($action->isExecutable($event)); - $this->assertFalse($action->execute(new GenericEvent($event))); - } + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); - public function testBadColumn() - { - $action = new TaskMoveAnotherProject($this->container, 3, Task::EVENT_MOVE_COLUMN); - $action->setParam('column_id', 5); + $action = new TaskMoveAnotherProject($this->container); + $action->setProjectId(1); + $action->setParam('project_id', 2); + $action->setParam('column_id', 2); - $event = array( - 'project_id' => 3, - 'task_id' => 3, - 'column_id' => 3, - ); + $this->assertTrue($action->execute($event, Task::EVENT_CLOSE)); - $this->assertFalse($action->execute(new GenericEvent($event))); + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals('test', $task['title']); + $this->assertEquals(2, $task['project_id']); + $this->assertEquals(5, $task['column_id']); } - public function testExecute() + public function testWithWrongColumn() { - $action = new TaskMoveAnotherProject($this->container, 1, Task::EVENT_MOVE_COLUMN); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($this->container); - $this->assertEquals(1, $p->create(array('name' => 'project 1'))); - $this->assertEquals(2, $p->create(array('name' => 'project 2'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 2, - ); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); - // Our event should NOT be executed because we define the same project - $action->setParam('column_id', 2); - $action->setParam('project_id', 1); - $this->assertFalse($action->execute(new GenericEvent($event))); - - // Our task should be assigned to the project 1 - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(1, $task['project_id']); - - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 2, - ); - - // Our event should be executed because we define a different project - $action->setParam('column_id', 2); + $action = new TaskMoveAnotherProject($this->container); + $action->setProjectId(1); $action->setParam('project_id', 2); - $this->assertTrue($action->execute(new GenericEvent($event))); + $action->setParam('column_id', 2); - // Our task should be assigned to the project 2 - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(2, $task['project_id']); + $this->assertFalse($action->execute($event, Task::EVENT_CLOSE)); } } diff --git a/tests/units/Action/TaskMoveColumnAssignedTest.php b/tests/units/Action/TaskMoveColumnAssignedTest.php new file mode 100644 index 00000000..f0eec894 --- /dev/null +++ b/tests/units/Action/TaskMoveColumnAssignedTest.php @@ -0,0 +1,56 @@ +container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 1, 'owner_id' => 1)); + + $action = new TaskMoveColumnAssigned($this->container); + $action->setProjectId(1); + $action->setParam('src_column_id', 1); + $action->setParam('dest_column_id', 2); + + $this->assertTrue($action->execute($event, Task::EVENT_ASSIGNEE_CHANGE)); + + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals('test', $task['title']); + $this->assertEquals(2, $task['column_id']); + } + + public function testWithWrongColumn() + { + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3, 'owner_id' => 1)); + + $action = new TaskMoveColumnAssigned($this->container); + $action->setProjectId(1); + $action->setParam('src_column_id', 1); + $action->setParam('dest_column_id', 2); + + $this->assertFalse($action->execute($event, Task::EVENT_ASSIGNEE_CHANGE)); + } +} diff --git a/tests/units/Action/TaskMoveColumnCategoryChangeTest.php b/tests/units/Action/TaskMoveColumnCategoryChangeTest.php index 03423776..1f0768c1 100644 --- a/tests/units/Action/TaskMoveColumnCategoryChangeTest.php +++ b/tests/units/Action/TaskMoveColumnCategoryChangeTest.php @@ -3,60 +3,84 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; +use Kanboard\Model\Category; use Kanboard\Model\Task; -use Kanboard\Model\TaskCreation; use Kanboard\Model\TaskFinder; +use Kanboard\Model\TaskCreation; use Kanboard\Model\Project; -use Kanboard\Model\Category; -use Kanboard\Integration\GithubWebhook; use Kanboard\Action\TaskMoveColumnCategoryChange; class TaskMoveColumnCategoryChangeTest extends Base { - public function testExecute() + public function testSuccess() { - $action = new TaskMoveColumnCategoryChange($this->container, 1, Task::EVENT_UPDATE); - $action->setParam('dest_column_id', 3); - $action->setParam('category_id', 1); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + $categoryModel = new Category($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $this->assertEquals(3, $action->getParam('dest_column_id')); - $this->assertEquals(1, $action->getParam('category_id')); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 1, 'category_id' => 1)); - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($this->container); - $c = new Category($this->container); + $action = new TaskMoveColumnCategoryChange($this->container); + $action->setProjectId(1); + $action->setParam('category_id', 1); + $action->setParam('dest_column_id', 2); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $c->create(array('name' => 'bug', 'project_id' => 1))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); + $this->assertTrue($action->execute($event, Task::EVENT_UPDATE)); - // No category should be assigned + column_id=1 - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEmpty($task['category_id']); - $this->assertEquals(1, $task['column_id']); - - // We create an event to move the task to the 2nd column - $event = array( - 'task_id' => 1, - 'column_id' => 1, - 'project_id' => 1, - 'category_id' => 1, - ); - - // Our event should be executed - $this->assertTrue($action->hasCompatibleEvent()); - $this->assertTrue($action->hasRequiredProject($event)); - $this->assertTrue($action->hasRequiredParameters($event)); - $this->assertTrue($action->hasRequiredCondition($event)); - $this->assertTrue($action->isExecutable($event)); - $this->assertTrue($action->execute(new GenericEvent($event))); - - // Our task should be moved to the other column - $task = $tf->getById(1); + $task = $taskFinderModel->getById(1); $this->assertNotEmpty($task); - $this->assertEquals(3, $task['column_id']); + $this->assertEquals('test', $task['title']); + $this->assertEquals(2, $task['column_id']); + } + + public function testWithWrongColumn() + { + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + $categoryModel = new Category($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2, 'category_id' => 1)); + + $action = new TaskMoveColumnCategoryChange($this->container); + $action->setProjectId(1); + $action->setParam('category_id', 1); + $action->setParam('dest_column_id', 2); + + $this->assertFalse($action->execute($event, Task::EVENT_UPDATE)); + } + + public function testWithWrongCategory() + { + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + $categoryModel = new Category($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); + $this->assertEquals(2, $categoryModel->create(array('name' => 'c2', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 1, 'category_id' => 2)); + + $action = new TaskMoveColumnCategoryChange($this->container); + $action->setProjectId(1); + $action->setParam('category_id', 1); + $action->setParam('dest_column_id', 2); + + $this->assertFalse($action->execute($event, Task::EVENT_UPDATE)); } } diff --git a/tests/units/Action/TaskMoveColumnUnAssignedTest.php b/tests/units/Action/TaskMoveColumnUnAssignedTest.php new file mode 100644 index 00000000..0b54b781 --- /dev/null +++ b/tests/units/Action/TaskMoveColumnUnAssignedTest.php @@ -0,0 +1,74 @@ +container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 1, 'owner_id' => 0)); + + $action = new TaskMoveColumnUnAssigned($this->container); + $action->setProjectId(1); + $action->setParam('src_column_id', 1); + $action->setParam('dest_column_id', 2); + + $this->assertTrue($action->execute($event, Task::EVENT_ASSIGNEE_CHANGE)); + + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals('test', $task['title']); + $this->assertEquals(2, $task['column_id']); + } + + public function testWithWrongColumn() + { + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2, 'owner_id' => 0)); + + $action = new TaskMoveColumnUnAssigned($this->container); + $action->setProjectId(1); + $action->setParam('src_column_id', 1); + $action->setParam('dest_column_id', 2); + + $this->assertFalse($action->execute($event, Task::EVENT_ASSIGNEE_CHANGE)); + } + + public function testWithWrongUser() + { + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 1, 'owner_id' => 1)); + + $action = new TaskMoveColumnUnAssigned($this->container); + $action->setProjectId(1); + $action->setParam('src_column_id', 1); + $action->setParam('dest_column_id', 2); + + $this->assertFalse($action->execute($event, Task::EVENT_ASSIGNEE_CHANGE)); + } +} diff --git a/tests/units/Action/TaskOpenTest.php b/tests/units/Action/TaskOpenTest.php new file mode 100644 index 00000000..01290a64 --- /dev/null +++ b/tests/units/Action/TaskOpenTest.php @@ -0,0 +1,51 @@ +container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test', 'is_active' => 0))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1)); + + $action = new TaskOpen($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); + + $this->assertTrue($action->execute($event, 'test.event')); + + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(1, $task['is_active']); + } + + public function testWithNoTaskId() + { + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1)); + + $action = new TaskOpen($this->container); + $action->setProjectId(1); + $action->addEvent('test.event', 'Test Event'); + + $this->assertFalse($action->execute($event, 'test.event')); + } +} diff --git a/tests/units/Action/TaskUpdateStartDateTest.php b/tests/units/Action/TaskUpdateStartDateTest.php index 7d558e28..adf5bd9d 100644 --- a/tests/units/Action/TaskUpdateStartDateTest.php +++ b/tests/units/Action/TaskUpdateStartDateTest.php @@ -3,44 +3,50 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; -use Kanboard\Model\Task; use Kanboard\Model\TaskCreation; use Kanboard\Model\TaskFinder; use Kanboard\Model\Project; +use Kanboard\Model\Task; use Kanboard\Action\TaskUpdateStartDate; class TaskUpdateStartDateTest extends Base { - public function testExecute() + public function testClose() { - $action = new TaskUpdateStartDate($this->container, 1, Task::EVENT_MOVE_COLUMN); + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); + $taskFinderModel = new TaskFinder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + + $action = new TaskUpdateStartDate($this->container); + $action->setProjectId(1); $action->setParam('column_id', 2); - // We create a task in the first column - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $p = new Project($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); + $this->assertTrue($action->execute($event, Task::EVENT_MOVE_COLUMN)); - // The start date must be empty - $task = $tf->getById(1); + $task = $taskFinderModel->getById(1); $this->assertNotEmpty($task); - $this->assertEmpty($task['date_started']); + $this->assertEquals(time(), $task['date_started'], 'Date started delta', 2); + } - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'column_id' => 2, - ); + public function testWithWrongColumn() + { + $projectModel = new Project($this->container); + $taskCreationModel = new TaskCreation($this->container); - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - // Our task should be updated - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(time(), $task['date_started'], '', 2); + $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + + $action = new TaskUpdateStartDate($this->container); + $action->setProjectId(1); + $action->setParam('column_id', 2); + + $this->assertFalse($action->execute($event, Task::EVENT_MOVE_COLUMN)); } } diff --git a/tests/units/Core/Action/ActionManagerTest.php b/tests/units/Core/Action/ActionManagerTest.php new file mode 100644 index 00000000..3714583b --- /dev/null +++ b/tests/units/Core/Action/ActionManagerTest.php @@ -0,0 +1,157 @@ +container); + $actionTaskClose = new TaskClose($this->container); + + $actionManager->register($actionTaskClose); + $this->assertInstanceOf(get_class($actionTaskClose), $actionManager->getAction($actionTaskClose->getName())); + } + + public function testGetActionNotFound() + { + $this->setExpectedException('RuntimeException', 'Automatic Action Not Found: foobar'); + $actionManager = new ActionManager($this->container); + $actionManager->getAction('foobar'); + } + + public function testGetAvailableActions() + { + $actionManager = new ActionManager($this->container); + $actionTaskClose1 = new TaskClose($this->container); + $actionTaskClose2 = new TaskClose($this->container); + $actionTaskUpdateStartDate = new TaskUpdateStartDate($this->container); + + $actionManager + ->register($actionTaskClose1) + ->register($actionTaskClose2) + ->register($actionTaskUpdateStartDate); + + $actions = $actionManager->getAvailableActions(); + $this->assertCount(2, $actions); + $this->assertArrayHasKey($actionTaskClose1->getName(), $actions); + $this->assertArrayHasKey($actionTaskUpdateStartDate->getName(), $actions); + $this->assertNotEmpty($actions[$actionTaskClose1->getName()]); + $this->assertNotEmpty($actions[$actionTaskUpdateStartDate->getName()]); + } + + public function testGetAvailableParameters() + { + $actionManager = new ActionManager($this->container); + + $actionManager + ->register(new TaskCloseColumn($this->container)) + ->register(new TaskUpdateStartDate($this->container)); + + $params = $actionManager->getAvailableParameters(array( + array('action_name' => '\Kanboard\Action\TaskCloseColumn'), + array('action_name' => '\Kanboard\Action\TaskUpdateStartDate'), + )); + + $this->assertCount(2, $params); + $this->assertArrayHasKey('column_id', $params['\Kanboard\Action\TaskCloseColumn']); + $this->assertArrayHasKey('column_id', $params['\Kanboard\Action\TaskUpdateStartDate']); + $this->assertNotEmpty($params['\Kanboard\Action\TaskCloseColumn']['column_id']); + $this->assertNotEmpty($params['\Kanboard\Action\TaskUpdateStartDate']['column_id']); + } + + public function testGetCompatibleEvents() + { + $actionTaskAssignColorColumn = new TaskAssignColorColumn($this->container); + $actionManager = new ActionManager($this->container); + $actionManager->register($actionTaskAssignColorColumn); + + $events = $actionManager->getCompatibleEvents('\\'.get_class($actionTaskAssignColorColumn)); + $this->assertCount(2, $events); + $this->assertArrayHasKey(Task::EVENT_CREATE, $events); + $this->assertArrayHasKey(Task::EVENT_MOVE_COLUMN, $events); + $this->assertNotEmpty($events[Task::EVENT_CREATE]); + $this->assertNotEmpty($events[Task::EVENT_MOVE_COLUMN]); + } + + public function testAttachEventsWithoutUserSession() + { + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + $actionTaskAssignColorColumn = new TaskAssignColorColumn($this->container); + $actionManager = new ActionManager($this->container); + $actionManager->register($actionTaskAssignColorColumn); + + $actions = $actionManager->getAvailableActions(); + + $actionManager->attachEvents(); + $this->assertEmpty($this->container['dispatcher']->getListeners()); + + $this->assertEquals(1, $projectModel->create(array('name' =>'test'))); + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => Task::EVENT_CREATE, + 'action_name' => key($actions), + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); + + $actionManager->attachEvents(); + $listeners = $this->container['dispatcher']->getListeners(Task::EVENT_CREATE); + $this->assertCount(1, $listeners); + $this->assertInstanceOf(get_class($actionTaskAssignColorColumn), $listeners[0][0]); + + $this->assertEquals(1, $listeners[0][0]->getProjectId()); + } + + public function testAttachEventsWithLoggedUser() + { + $this->container['sessionStorage']->user = array('id' => 1); + + $projectModel = new Project($this->container); + $projectUserRoleModel = new ProjectUserRole($this->container); + $actionModel = new Action($this->container); + $actionTaskAssignColorColumn = new TaskAssignColorColumn($this->container); + $actionManager = new ActionManager($this->container); + $actionManager->register($actionTaskAssignColorColumn); + + $actions = $actionManager->getAvailableActions(); + + $this->assertEquals(1, $projectModel->create(array('name' =>'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' =>'test2'))); + + $this->assertTrue($projectUserRoleModel->addUser(2, 1, Role::PROJECT_MEMBER)); + + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => Task::EVENT_CREATE, + 'action_name' => key($actions), + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); + + $this->assertEquals(2, $actionModel->create(array( + 'project_id' => 2, + 'event_name' => Task::EVENT_MOVE_COLUMN, + 'action_name' => key($actions), + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); + + $actionManager->attachEvents(); + + $listeners = $this->container['dispatcher']->getListeners(Task::EVENT_MOVE_COLUMN); + $this->assertCount(1, $listeners); + $this->assertInstanceOf(get_class($actionTaskAssignColorColumn), $listeners[0][0]); + + $this->assertEquals(2, $listeners[0][0]->getProjectId()); + } +} diff --git a/tests/units/Core/Event/EventManagerTest.php b/tests/units/Core/Event/EventManagerTest.php new file mode 100644 index 00000000..974fde62 --- /dev/null +++ b/tests/units/Core/Event/EventManagerTest.php @@ -0,0 +1,18 @@ +register('my.event', 'My Event'); + + $events = $eventManager->getAll(); + $this->assertArrayHasKey('my.event', $events); + $this->assertEquals('My Event', $events['my.event']); + } +} diff --git a/tests/units/Integration/BitbucketWebhookTest.php b/tests/units/Integration/BitbucketWebhookTest.php index 40dbde2e..bb6755c2 100644 --- a/tests/units/Integration/BitbucketWebhookTest.php +++ b/tests/units/Integration/BitbucketWebhookTest.php @@ -319,7 +319,7 @@ class BitbucketWebhookTest extends Base $this->assertEquals(1, $data['project_id']); $this->assertEquals(2, $data['task_id']); $this->assertEquals('test2', $data['title']); - $this->assertEquals("Test another commit #2\n\n\n[Commit made by @Frederic Guillot on Bitbucket](https://bitbucket.org/minicoders/test-webhook/commits/824059cce7667d3f8d8780cc707391be821e0ea6)", $data['commit_comment']); + $this->assertEquals("Test another commit #2\n\n\n[Commit made by @Frederic Guillot on Bitbucket](https://bitbucket.org/minicoders/test-webhook/commits/824059cce7667d3f8d8780cc707391be821e0ea6)", $data['comment']); $this->assertEquals("Test another commit #2\n", $data['commit_message']); $this->assertEquals('https://bitbucket.org/minicoders/test-webhook/commits/824059cce7667d3f8d8780cc707391be821e0ea6', $data['commit_url']); } diff --git a/tests/units/Integration/GithubWebhookTest.php b/tests/units/Integration/GithubWebhookTest.php index f00e5dde..6b5e19a5 100644 --- a/tests/units/Integration/GithubWebhookTest.php +++ b/tests/units/Integration/GithubWebhookTest.php @@ -453,7 +453,7 @@ class GithubWebhookTest extends Base $this->assertEquals(1, $data['project_id']); $this->assertEquals(1, $data['task_id']); $this->assertEquals('boo', $data['title']); - $this->assertEquals("Update README to fix #1\n\n[Commit made by @fguillot on Github](https://github.com/kanboardapp/webhook/commit/98dee3e49ee7aa66ffec1f761af93da5ffd711f6)", $data['commit_comment']); + $this->assertEquals("Update README to fix #1\n\n[Commit made by @fguillot on Github](https://github.com/kanboardapp/webhook/commit/98dee3e49ee7aa66ffec1f761af93da5ffd711f6)", $data['comment']); $this->assertEquals('Update README to fix #1', $data['commit_message']); $this->assertEquals('https://github.com/kanboardapp/webhook/commit/98dee3e49ee7aa66ffec1f761af93da5ffd711f6', $data['commit_url']); } diff --git a/tests/units/Integration/GitlabWebhookTest.php b/tests/units/Integration/GitlabWebhookTest.php index 3e0e6d2c..afd9f7f1 100644 --- a/tests/units/Integration/GitlabWebhookTest.php +++ b/tests/units/Integration/GitlabWebhookTest.php @@ -221,7 +221,7 @@ class GitlabWebhookTest extends Base $this->assertEquals(1, $data['project_id']); $this->assertEquals(2, $data['task_id']); $this->assertEquals('test2', $data['title']); - $this->assertEquals("Fix bug #2\n\n[Commit made by @Fred on Gitlab](https://gitlab.com/minicoders/test-webhook/commit/48aafa75eef9ad253aa254b0c82c987a52ebea78)", $data['commit_comment']); + $this->assertEquals("Fix bug #2\n\n[Commit made by @Fred on Gitlab](https://gitlab.com/minicoders/test-webhook/commit/48aafa75eef9ad253aa254b0c82c987a52ebea78)", $data['comment']); $this->assertEquals("Fix bug #2", $data['commit_message']); $this->assertEquals('https://gitlab.com/minicoders/test-webhook/commit/48aafa75eef9ad253aa254b0c82c987a52ebea78', $data['commit_url']); } diff --git a/tests/units/Model/ActionTest.php b/tests/units/Model/ActionTest.php index 4a338707..8d574115 100644 --- a/tests/units/Model/ActionTest.php +++ b/tests/units/Model/ActionTest.php @@ -4,388 +4,506 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Model\Action; use Kanboard\Model\Project; -use Kanboard\Model\Board; use Kanboard\Model\Task; -use Kanboard\Model\TaskPosition; -use Kanboard\Model\TaskCreation; -use Kanboard\Model\TaskFinder; -use Kanboard\Model\Category; use Kanboard\Model\User; +use Kanboard\Model\Board; +use Kanboard\Model\Category; use Kanboard\Model\ProjectUserRole; -use Kanboard\Integration\GithubWebhook; -use Kanboard\Integration\BitbucketWebhook; use Kanboard\Core\Security\Role; class ActionTest extends Base { - public function testGetActions() + public function testCreate() { - $a = new Action($this->container); + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $actions = $a->getAvailableActions(); - $this->assertNotEmpty($actions); - $this->assertEquals('Add a comment log when moving the task between columns', current($actions)); - $this->assertEquals('TaskLogMoveAnotherColumn', key($actions)); + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => Task::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); } - public function testExtendActions() + public function testRemove() { - $a = new Action($this->container); - $a->extendActions('MyClass', 'Description'); + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => Task::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); - $actions = $a->getAvailableActions(); - $this->assertNotEmpty($actions); - $this->assertContains('Description', $actions); - $this->assertArrayHasKey('MyClass', $actions); + $this->assertNotEmpty($actionModel->getById(1)); + $this->assertTrue($actionModel->remove(1)); + $this->assertEmpty($actionModel->getById(1)); } - public function testGetEvents() + public function testGetById() { - $a = new Action($this->container); + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $events = $a->getAvailableEvents(); - $this->assertNotEmpty($events); - $this->assertEquals('Bitbucket commit received', current($events)); - $this->assertEquals(BitbucketWebhook::EVENT_COMMIT, key($events)); + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => Task::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); + + $action = $actionModel->getById(1); + $this->assertNotEmpty($action); + $this->assertEquals(1, $action['project_id']); + $this->assertEquals('\Kanboard\Action\TaskAssignColorColumn', $action['action_name']); + $this->assertEquals(Task::EVENT_CREATE, $action['event_name']); + $this->assertEquals(array('column_id' => 1, 'color_id' => 'red'), $action['params']); } - public function testGetCompatibleEvents() + public function testGetAll() { - $a = new Action($this->container); - $events = $a->getCompatibleEvents('TaskAssignSpecificUser'); + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - $this->assertNotEmpty($events); - $this->assertCount(2, $events); - $this->assertArrayHasKey(Task::EVENT_CREATE_UPDATE, $events); - $this->assertArrayHasKey(Task::EVENT_MOVE_COLUMN, $events); + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => Task::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); + + $this->assertEquals(2, $actionModel->create(array( + 'project_id' => 2, + 'event_name' => Task::EVENT_MOVE_COLUMN, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 6, 'color_id' => 'blue'), + ))); + + $actions = $actionModel->getAll(); + $this->assertCount(2, $actions); + + $this->assertEquals(1, $actions[0]['project_id']); + $this->assertEquals('\Kanboard\Action\TaskAssignColorColumn', $actions[0]['action_name']); + $this->assertEquals(Task::EVENT_CREATE, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 1, 'color_id' => 'red'), $actions[0]['params']); + + $this->assertEquals(2, $actions[1]['project_id']); + $this->assertEquals('\Kanboard\Action\TaskAssignColorColumn', $actions[1]['action_name']); + $this->assertEquals(Task::EVENT_MOVE_COLUMN, $actions[1]['event_name']); + $this->assertEquals(array('column_id' => 6, 'color_id' => 'blue'), $actions[1]['params']); } - public function testResolveDuplicatedParameters() + public function testGetAllByProject() { - $p = new Project($this->container); - $pp = new ProjectUserRole($this->container); - $a = new Action($this->container); - $c = new Category($this->container); - $u = new User($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'P1'))); - $this->assertEquals(2, $p->create(array('name' => 'P2'))); - - $this->assertEquals(1, $c->create(array('name' => 'C1', 'project_id' => 1))); - - $this->assertEquals(2, $c->create(array('name' => 'C2', 'project_id' => 2))); - $this->assertEquals(3, $c->create(array('name' => 'C1', 'project_id' => 2))); - - $this->assertEquals(2, $u->create(array('username' => 'unittest1'))); - $this->assertEquals(3, $u->create(array('username' => 'unittest2'))); - - $this->assertTrue($pp->addUser(1, 2, Role::PROJECT_MEMBER)); - $this->assertTrue($pp->addUser(1, 3, Role::PROJECT_MEMBER)); - $this->assertTrue($pp->addUser(2, 3, Role::PROJECT_MEMBER)); - - // anything - $this->assertEquals('blah', $a->resolveParameters(array('name' => 'foobar', 'value' => 'blah'), 2)); - - // project_id - $this->assertEquals(2, $a->resolveParameters(array('name' => 'project_id', 'value' => 'blah'), 2)); - - // category_id - $this->assertEquals(3, $a->resolveParameters(array('name' => 'category_id', 'value' => 1), 2)); - $this->assertFalse($a->resolveParameters(array('name' => 'category_id', 'value' => 0), 2)); - $this->assertFalse($a->resolveParameters(array('name' => 'category_id', 'value' => 5), 2)); - - // column_id - $this->assertFalse($a->resolveParameters(array('name' => 'column_id', 'value' => 10), 2)); - $this->assertFalse($a->resolveParameters(array('name' => 'column_id', 'value' => 0), 2)); - $this->assertEquals(5, $a->resolveParameters(array('name' => 'column_id', 'value' => 1), 2)); - $this->assertEquals(6, $a->resolveParameters(array('name' => 'dest_column_id', 'value' => 2), 2)); - $this->assertEquals(7, $a->resolveParameters(array('name' => 'dst_column_id', 'value' => 3), 2)); - $this->assertEquals(8, $a->resolveParameters(array('name' => 'src_column_id', 'value' => 4), 2)); - - // user_id - $this->assertFalse($a->resolveParameters(array('name' => 'user_id', 'value' => 10), 2)); - $this->assertFalse($a->resolveParameters(array('name' => 'user_id', 'value' => 0), 2)); - $this->assertFalse($a->resolveParameters(array('name' => 'user_id', 'value' => 2), 2)); - $this->assertFalse($a->resolveParameters(array('name' => 'owner_id', 'value' => 2), 2)); - $this->assertEquals(3, $a->resolveParameters(array('name' => 'user_id', 'value' => 3), 2)); - $this->assertEquals(3, $a->resolveParameters(array('name' => 'owner_id', 'value' => 3), 2)); + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => Task::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); + + $this->assertEquals(2, $actionModel->create(array( + 'project_id' => 2, + 'event_name' => Task::EVENT_MOVE_COLUMN, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 6, 'color_id' => 'blue'), + ))); + + $actions = $actionModel->getAllByProject(1); + $this->assertCount(1, $actions); + + $this->assertEquals(1, $actions[0]['project_id']); + $this->assertEquals('\Kanboard\Action\TaskAssignColorColumn', $actions[0]['action_name']); + $this->assertEquals(Task::EVENT_CREATE, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 1, 'color_id' => 'red'), $actions[0]['params']); + + + $actions = $actionModel->getAllByProject(2); + $this->assertCount(1, $actions); + + $this->assertEquals(2, $actions[0]['project_id']); + $this->assertEquals('\Kanboard\Action\TaskAssignColorColumn', $actions[0]['action_name']); + $this->assertEquals(Task::EVENT_MOVE_COLUMN, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 6, 'color_id' => 'blue'), $actions[0]['params']); } - public function testDuplicateSuccess() + public function testGetAllByUser() { - $p = new Project($this->container); - $pp = new ProjectUserRole($this->container); - $a = new Action($this->container); - $u = new User($this->container); + $projectModel = new Project($this->container); + $projectUserRoleModel = new ProjectUserRole($this->container); + $userModel = new User($this->container); + $actionModel = new Action($this->container); - $this->assertEquals(1, $p->create(array('name' => 'P1'))); - $this->assertEquals(2, $p->create(array('name' => 'P2'))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + $this->assertEquals(3, $projectModel->create(array('name' => 'test4', 'is_active' => 0))); - $this->assertEquals(2, $u->create(array('username' => 'unittest1'))); - $this->assertEquals(3, $u->create(array('username' => 'unittest2'))); + $this->assertEquals(2, $userModel->create(array('username' => 'user1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user2'))); - $this->assertTrue($pp->addUser(1, 2, Role::PROJECT_MEMBER)); - $this->assertTrue($pp->addUser(1, 3, Role::PROJECT_MEMBER)); - $this->assertTrue($pp->addUser(2, 3, Role::PROJECT_MEMBER)); + $this->assertTrue($projectUserRoleModel->addUser(1, 2, Role::PROJECT_VIEWER)); + $this->assertTrue($projectUserRoleModel->addUser(2, 3, Role::PROJECT_MANAGER)); + $this->assertTrue($projectUserRoleModel->addUser(3, 3, Role::PROJECT_MANAGER)); - $this->assertEquals(1, $a->create(array( + $this->assertEquals(1, $actionModel->create(array( 'project_id' => 1, - 'event_name' => Task::EVENT_CREATE_UPDATE, - 'action_name' => 'TaskAssignSpecificUser', - 'params' => array( - 'column_id' => 1, - 'user_id' => 3, - ) + 'event_name' => Task::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 1, 'color_id' => 'red'), ))); - $action = $a->getById(1); - $this->assertNotEmpty($action); - $this->assertNotEmpty($action['params']); - $this->assertEquals(1, $action['project_id']); + $this->assertEquals(2, $actionModel->create(array( + 'project_id' => 2, + 'event_name' => Task::EVENT_MOVE_COLUMN, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 6, 'color_id' => 'blue'), + ))); - $this->assertTrue($a->duplicate(1, 2)); + $this->assertEquals(3, $actionModel->create(array( + 'project_id' => 3, + 'event_name' => Task::EVENT_MOVE_COLUMN, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 10, 'color_id' => 'green'), + ))); - $action = $a->getById(2); - $this->assertNotEmpty($action); - $this->assertNotEmpty($action['params']); - $this->assertEquals(2, $action['project_id']); - $this->assertEquals(Task::EVENT_CREATE_UPDATE, $action['event_name']); - $this->assertEquals('TaskAssignSpecificUser', $action['action_name']); - $this->assertEquals('column_id', $action['params'][0]['name']); - $this->assertEquals(5, $action['params'][0]['value']); - $this->assertEquals('user_id', $action['params'][1]['name']); - $this->assertEquals(3, $action['params'][1]['value']); + $actions = $actionModel->getAllByUser(1); + $this->assertCount(0, $actions); + + $actions = $actionModel->getAllByUser(2); + $this->assertCount(1, $actions); + + $this->assertEquals(1, $actions[0]['project_id']); + $this->assertEquals('\Kanboard\Action\TaskAssignColorColumn', $actions[0]['action_name']); + $this->assertEquals(Task::EVENT_CREATE, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 1, 'color_id' => 'red'), $actions[0]['params']); + + $actions = $actionModel->getAllByUser(3); + $this->assertCount(1, $actions); + + $this->assertEquals(2, $actions[0]['project_id']); + $this->assertEquals('\Kanboard\Action\TaskAssignColorColumn', $actions[0]['action_name']); + $this->assertEquals(Task::EVENT_MOVE_COLUMN, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 6, 'color_id' => 'blue'), $actions[0]['params']); } - public function testDuplicateUnableToResolveParams() + public function testDuplicateWithColumnAndColorParameter() { - $p = new Project($this->container); - $pp = new ProjectUserRole($this->container); - $a = new Action($this->container); - $u = new User($this->container); + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); - $this->assertEquals(1, $p->create(array('name' => 'P1'))); - $this->assertEquals(2, $p->create(array('name' => 'P2'))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - $this->assertEquals(2, $u->create(array('username' => 'unittest1'))); + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => Task::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); - $this->assertTrue($pp->addUser(1, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($actionModel->duplicate(1, 2)); - $this->assertEquals(1, $a->create(array( + $actions = $actionModel->getAllByProject(2); + $this->assertCount(1, $actions); + + $this->assertEquals(2, $actions[0]['project_id']); + $this->assertEquals('\Kanboard\Action\TaskAssignColorColumn', $actions[0]['action_name']); + $this->assertEquals(Task::EVENT_CREATE, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 5, 'color_id' => 'red'), $actions[0]['params']); + } + + public function testDuplicateWithColumnsParameter() + { + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertEquals(1, $actionModel->create(array( 'project_id' => 1, - 'event_name' => Task::EVENT_CREATE_UPDATE, - 'action_name' => 'TaskAssignSpecificUser', - 'params' => array( - 'column_id' => 1, - 'user_id' => 2, - ) + 'event_name' => Task::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('src_column_id' => 1, 'dst_column_id' => 2, 'dest_column_id' => 3), ))); - $action = $a->getById(1); - $this->assertNotEmpty($action); - $this->assertNotEmpty($action['params']); - $this->assertEquals(1, $action['project_id']); - $this->assertEquals('user_id', $action['params'][1]['name']); - $this->assertEquals(2, $action['params'][1]['value']); + $this->assertTrue($actionModel->duplicate(1, 2)); - $this->assertTrue($a->duplicate(1, 2)); + $actions = $actionModel->getAllByProject(2); + $this->assertCount(1, $actions); - $action = $a->getById(2); - $this->assertEmpty($action); + $this->assertEquals(2, $actions[0]['project_id']); + $this->assertEquals('\Kanboard\Action\TaskAssignColorColumn', $actions[0]['action_name']); + $this->assertEquals(Task::EVENT_CREATE, $actions[0]['event_name']); + $this->assertEquals(array('src_column_id' => 5, 'dst_column_id' => 6, 'dest_column_id' => 7), $actions[0]['params']); } - public function testDuplicateMixedResults() + public function testDuplicateWithColumnParameterNotfound() { - $p = new Project($this->container); - $pp = new ProjectUserRole($this->container); - $a = new Action($this->container); - $u = new User($this->container); - $c = new Category($this->container); + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + $boardModel = new Board($this->container); - $this->assertEquals(1, $p->create(array('name' => 'P1'))); - $this->assertEquals(2, $p->create(array('name' => 'P2'))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - $this->assertEquals(1, $c->create(array('name' => 'C1', 'project_id' => 1))); - $this->assertEquals(2, $c->create(array('name' => 'C2', 'project_id' => 2))); - $this->assertEquals(3, $c->create(array('name' => 'C1', 'project_id' => 2))); + $this->assertTrue($boardModel->updateColumn(2, 'My unique column')); - $this->assertEquals(2, $u->create(array('username' => 'unittest1'))); - - $this->assertTrue($pp->addUser(1, 2, Role::PROJECT_MEMBER)); + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => Task::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); - $this->assertEquals(1, $a->create(array( + $this->assertEquals(2, $actionModel->create(array( 'project_id' => 1, - 'event_name' => Task::EVENT_CREATE_UPDATE, - 'action_name' => 'TaskAssignSpecificUser', - 'params' => array( - 'column_id' => 1, - 'user_id' => 2, - ) + 'event_name' => Task::EVENT_MOVE_COLUMN, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 2, 'color_id' => 'green'), ))); - $action = $a->getById(1); - $this->assertNotEmpty($action); - $this->assertNotEmpty($action['params']); + $this->assertTrue($actionModel->duplicate(1, 2)); + + $actions = $actionModel->getAllByProject(2); + $this->assertCount(1, $actions); + + $this->assertEquals(2, $actions[0]['project_id']); + $this->assertEquals('\Kanboard\Action\TaskAssignColorColumn', $actions[0]['action_name']); + $this->assertEquals(Task::EVENT_CREATE, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 5, 'color_id' => 'red'), $actions[0]['params']); + } + + public function testDuplicateWithProjectParameter() + { + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + $this->assertEquals(3, $projectModel->create(array('name' => 'test2'))); - $this->assertEquals(2, $a->create(array( + $this->assertEquals(1, $actionModel->create(array( 'project_id' => 1, - 'event_name' => Task::EVENT_CREATE_UPDATE, - 'action_name' => 'TaskAssignCategoryColor', - 'params' => array( - 'color_id' => 'blue', - 'category_id' => 1, - ) + 'event_name' => Task::EVENT_CLOSE, + 'action_name' => '\Kanboard\Action\TaskDuplicateAnotherProject', + 'params' => array('column_id' => 1, 'project_id' => 3), ))); - $action = $a->getById(2); - $this->assertNotEmpty($action); - $this->assertNotEmpty($action['params']); - $this->assertEquals('category_id', $action['params'][1]['name']); - $this->assertEquals(1, $action['params'][1]['value']); + $this->assertTrue($actionModel->duplicate(1, 2)); - $actions = $a->getAllByProject(1); - $this->assertNotEmpty($actions); - $this->assertCount(2, $actions); + $actions = $actionModel->getAllByProject(2); + $this->assertCount(1, $actions); - $this->assertTrue($a->duplicate(1, 2)); + $this->assertEquals(2, $actions[0]['project_id']); + $this->assertEquals('\Kanboard\Action\TaskDuplicateAnotherProject', $actions[0]['action_name']); + $this->assertEquals(Task::EVENT_CLOSE, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 5, 'project_id' => 3), $actions[0]['params']); + } - $actions = $a->getAllByProject(2); - $this->assertNotEmpty($actions); - $this->assertCount(1, $actions); + public function testDuplicateWithProjectParameterIdenticalToDestination() + { + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); - $actions = $a->getAll(); - $this->assertNotEmpty($actions); - $this->assertCount(3, $actions); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - $action = $a->getById($actions[2]['id']); - $this->assertNotEmpty($action); - $this->assertNotEmpty($action['params']); - $this->assertEquals('color_id', $action['params'][0]['name']); - $this->assertEquals('blue', $action['params'][0]['value']); - $this->assertEquals('category_id', $action['params'][1]['name']); - $this->assertEquals(3, $action['params'][1]['value']); + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => Task::EVENT_CLOSE, + 'action_name' => '\Kanboard\Action\TaskDuplicateAnotherProject', + 'params' => array('column_id' => 1, 'project_id' => 2), + ))); + + $this->assertTrue($actionModel->duplicate(1, 2)); + + $actions = $actionModel->getAllByProject(2); + $this->assertCount(0, $actions); } - public function testSingleAction() + public function testDuplicateWithUserParameter() { - $tp = new TaskPosition($this->container); - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $board = new Board($this->container); - $project = new Project($this->container); - $action = new Action($this->container); - - // We create a project - $this->assertEquals(1, $project->create(array('name' => 'unit_test'))); - - // We create a new action - $this->assertEquals(1, $action->create(array( + $projectUserRoleModel = new ProjectUserRole($this->container); + $userModel = new User($this->container); + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertEquals(2, $userModel->create(array('username' => 'user1'))); + + $this->assertTrue($projectUserRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($projectUserRoleModel->addUser(2, 2, Role::PROJECT_MEMBER)); + + $this->assertEquals(1, $actionModel->create(array( 'project_id' => 1, 'event_name' => Task::EVENT_MOVE_COLUMN, - 'action_name' => 'TaskClose', - 'params' => array( - 'column_id' => 4, - ) + 'action_name' => '\Kanboard\Action\TaskAssignSpecificUser', + 'params' => array('column_id' => 1, 'user_id' => 2), ))); - // We create a task - $this->assertEquals(1, $tc->create(array( - 'title' => 'unit_test', + $this->assertTrue($actionModel->duplicate(1, 2)); + + $actions = $actionModel->getAllByProject(2); + $this->assertCount(1, $actions); + + $this->assertEquals(2, $actions[0]['project_id']); + $this->assertEquals('\Kanboard\Action\TaskAssignSpecificUser', $actions[0]['action_name']); + $this->assertEquals(Task::EVENT_MOVE_COLUMN, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 5, 'user_id' => 2), $actions[0]['params']); + } + + public function testDuplicateWithUserParameterButNotAssignable() + { + $projectUserRoleModel = new ProjectUserRole($this->container); + $userModel = new User($this->container); + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertEquals(2, $userModel->create(array('username' => 'user1'))); + + $this->assertTrue($projectUserRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($projectUserRoleModel->addUser(2, 2, Role::PROJECT_VIEWER)); + + $this->assertEquals(1, $actionModel->create(array( 'project_id' => 1, - 'owner_id' => 1, - 'color_id' => 'red', - 'column_id' => 1, + 'event_name' => Task::EVENT_MOVE_COLUMN, + 'action_name' => '\Kanboard\Action\TaskAssignSpecificUser', + 'params' => array('column_id' => 1, 'user_id' => 2), ))); - // We attach events - $action->attachEvents(); + $this->assertTrue($actionModel->duplicate(1, 2)); + + $actions = $actionModel->getAllByProject(2); + $this->assertCount(0, $actions); + } + + public function testDuplicateWithUserParameterButNotAvailable() + { + $projectUserRoleModel = new ProjectUserRole($this->container); + $userModel = new User($this->container); + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertEquals(2, $userModel->create(array('username' => 'user1'))); - // Our task should be open - $t1 = $tf->getById(1); - $this->assertEquals(1, $t1['is_active']); - $this->assertEquals(1, $t1['column_id']); + $this->assertTrue($projectUserRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); - // We move our task - $tp->movePosition(1, 1, 4, 1); + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => Task::EVENT_MOVE_COLUMN, + 'action_name' => '\Kanboard\Action\TaskAssignSpecificUser', + 'params' => array('column_id' => 1, 'owner_id' => 2), + ))); - // Our task should be closed - $t1 = $tf->getById(1); - $this->assertEquals(4, $t1['column_id']); - $this->assertEquals(0, $t1['is_active']); + $this->assertTrue($actionModel->duplicate(1, 2)); + + $actions = $actionModel->getAllByProject(2); + $this->assertCount(0, $actions); } - public function testMultipleActions() + public function testDuplicateWithCategoryParameter() { - $tp = new TaskPosition($this->container); - $tc = new TaskCreation($this->container); - $tf = new TaskFinder($this->container); - $b = new Board($this->container); - $p = new Project($this->container); - $a = new Action($this->container); - $g = new GithubWebhook($this->container); - - // We create a project - $this->assertEquals(1, $p->create(array('name' => 'unit_test'))); - - // We create a new action - $this->assertEquals(1, $a->create(array( + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + $categoryModel = new Category($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); + $this->assertEquals(2, $categoryModel->create(array('name' => 'c1', 'project_id' => 2))); + + $this->assertEquals(1, $actionModel->create(array( 'project_id' => 1, - 'event_name' => GithubWebhook::EVENT_ISSUE_OPENED, - 'action_name' => 'TaskCreation', - 'params' => array() + 'event_name' => Task::EVENT_CREATE_UPDATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorCategory', + 'params' => array('column_id' => 1, 'category_id' => 1), ))); - $this->assertEquals(2, $a->create(array( + $this->assertTrue($actionModel->duplicate(1, 2)); + + $actions = $actionModel->getAllByProject(2); + $this->assertCount(1, $actions); + + $this->assertEquals(2, $actions[0]['project_id']); + $this->assertEquals('\Kanboard\Action\TaskAssignColorCategory', $actions[0]['action_name']); + $this->assertEquals(Task::EVENT_CREATE_UPDATE, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 5, 'category_id' => 2), $actions[0]['params']); + } + + public function testDuplicateWithCategoryParameterButDifferentName() + { + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + $categoryModel = new Category($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); + $this->assertEquals(2, $categoryModel->create(array('name' => 'c2', 'project_id' => 2))); + + $this->assertEquals(1, $actionModel->create(array( 'project_id' => 1, - 'event_name' => GithubWebhook::EVENT_ISSUE_LABEL_CHANGE, - 'action_name' => 'TaskAssignCategoryLabel', - 'params' => array( - 'label' => 'bug', - 'category_id' => 1, - ) + 'event_name' => Task::EVENT_CREATE_UPDATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorCategory', + 'params' => array('column_id' => 1, 'category_id' => 1), ))); - $this->assertEquals(3, $a->create(array( + $this->assertTrue($actionModel->duplicate(1, 2)); + + $actions = $actionModel->getAllByProject(2); + $this->assertCount(0, $actions); + } + + public function testDuplicateWithCategoryParameterButNotFound() + { + $projectModel = new Project($this->container); + $actionModel = new Action($this->container); + $categoryModel = new Category($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertEquals(1, $categoryModel->create(array('name' => 'c1', 'project_id' => 1))); + + $this->assertEquals(1, $actionModel->create(array( 'project_id' => 1, 'event_name' => Task::EVENT_CREATE_UPDATE, - 'action_name' => 'TaskAssignColorCategory', - 'params' => array( - 'color_id' => 'red', - 'category_id' => 1, - ) + 'action_name' => '\Kanboard\Action\TaskAssignColorCategory', + 'params' => array('column_id' => 1, 'category_id' => 1), ))); - // We attach events - $a->attachEvents(); - $g->setProjectId(1); - - // We create a Github issue - $issue = array( - 'number' => 123, - 'title' => 'Bugs everywhere', - 'body' => 'There is a bug!', - 'html_url' => 'http://localhost/', - ); - - $this->assertTrue($g->handleIssueOpened($issue)); - - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(1, $task['is_active']); - $this->assertEquals(0, $task['category_id']); - $this->assertEquals('yellow', $task['color_id']); - - // We assign a label to our issue - $label = array( - 'name' => 'bug', - ); - - $this->assertTrue($g->handleIssueLabeled($issue, $label)); - - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(1, $task['is_active']); - $this->assertEquals(1, $task['category_id']); - $this->assertEquals('red', $task['color_id']); + $this->assertTrue($actionModel->duplicate(1, 2)); + + $actions = $actionModel->getAllByProject(2); + $this->assertCount(0, $actions); } } diff --git a/tests/units/Model/ProjectDuplicationTest.php b/tests/units/Model/ProjectDuplicationTest.php index 8b74675b..db5da525 100644 --- a/tests/units/Model/ProjectDuplicationTest.php +++ b/tests/units/Model/ProjectDuplicationTest.php @@ -165,7 +165,7 @@ class ProjectDuplicationTest extends Base $this->assertNotEmpty($actions); $this->assertEquals('TaskAssignCurrentUser', $actions[0]['action_name']); $this->assertNotEmpty($actions[0]['params']); - $this->assertEquals(6, $actions[0]['params'][0]['value']); + $this->assertEquals(6, $actions[0]['params']['column_id']); } public function testCloneProjectWithActionTaskAssignColorCategory() @@ -195,8 +195,8 @@ class ProjectDuplicationTest extends Base $this->assertNotEmpty($actions); $this->assertEquals('TaskAssignColorCategory', $actions[0]['action_name']); $this->assertNotEmpty($actions[0]['params']); - $this->assertEquals('blue', $actions[0]['params'][0]['value']); - $this->assertEquals(5, $actions[0]['params'][1]['value']); + $this->assertEquals('blue', $actions[0]['params']['color_id']); + $this->assertEquals(5, $actions[0]['params']['category_id']); } public function testCloneProjectWithSwimlanesAndTasks() -- cgit v1.2.3 From 27b9b7a727de7a9608d85bce6ca94e81bbdf7ffb Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 16 Jan 2016 22:29:29 -0500 Subject: Minor code improvements --- app/Action/TaskClose.php | 2 -- app/Core/Http/Route.php | 1 - app/Core/Ldap/User.php | 2 +- app/Model/Config.php | 1 - app/Model/Group.php | 3 --- app/Model/ProjectUserRole.php | 2 +- app/ServiceProvider/EventDispatcherProvider.php | 1 - app/Validator/AuthValidator.php | 29 ++++++++----------------- 8 files changed, 11 insertions(+), 30 deletions(-) (limited to 'app/Model/ProjectUserRole.php') diff --git a/app/Action/TaskClose.php b/app/Action/TaskClose.php index b8c5e175..cf91e83e 100644 --- a/app/Action/TaskClose.php +++ b/app/Action/TaskClose.php @@ -2,8 +2,6 @@ namespace Kanboard\Action; -use Kanboard\Model\Task; - /** * Close automatically a task * diff --git a/app/Core/Http/Route.php b/app/Core/Http/Route.php index ed831467..7836146d 100644 --- a/app/Core/Http/Route.php +++ b/app/Core/Http/Route.php @@ -2,7 +2,6 @@ namespace Kanboard\Core\Http; -use RuntimeException; use Kanboard\Core\Base; /** diff --git a/app/Core/Ldap/User.php b/app/Core/Ldap/User.php index 04c4cc7e..d36d6f34 100644 --- a/app/Core/Ldap/User.php +++ b/app/Core/Ldap/User.php @@ -40,7 +40,7 @@ class User * @access public * @param Client $client * @param string $username - * @return array + * @return LdapUserProvider */ public static function getUser(Client $client, $username) { diff --git a/app/Model/Config.php b/app/Model/Config.php index d815246f..55999310 100644 --- a/app/Model/Config.php +++ b/app/Model/Config.php @@ -4,7 +4,6 @@ namespace Kanboard\Model; use Kanboard\Core\Translator; use Kanboard\Core\Security\Token; -use Kanboard\Core\Session\SessionManager; /** * Config model diff --git a/app/Model/Group.php b/app/Model/Group.php index ce8c0284..67899503 100644 --- a/app/Model/Group.php +++ b/app/Model/Group.php @@ -2,9 +2,6 @@ namespace Kanboard\Model; -use SimpleValidator\Validator; -use SimpleValidator\Validators; - /** * Group Model * diff --git a/app/Model/ProjectUserRole.php b/app/Model/ProjectUserRole.php index 6b9c23b0..8149a253 100644 --- a/app/Model/ProjectUserRole.php +++ b/app/Model/ProjectUserRole.php @@ -28,7 +28,7 @@ class ProjectUserRole extends Base */ public function getActiveProjectsByUser($user_id) { - return $this->getProjectsByUser($user_id, $status = array(Project::ACTIVE)); + return $this->getProjectsByUser($user_id, array(Project::ACTIVE)); } /** diff --git a/app/ServiceProvider/EventDispatcherProvider.php b/app/ServiceProvider/EventDispatcherProvider.php index 8280a138..880caa41 100644 --- a/app/ServiceProvider/EventDispatcherProvider.php +++ b/app/ServiceProvider/EventDispatcherProvider.php @@ -11,7 +11,6 @@ use Kanboard\Subscriber\NotificationSubscriber; use Kanboard\Subscriber\ProjectDailySummarySubscriber; use Kanboard\Subscriber\ProjectModificationDateSubscriber; use Kanboard\Subscriber\SubtaskTimeTrackingSubscriber; -use Kanboard\Subscriber\TaskMovedDateSubscriber; use Kanboard\Subscriber\TransitionSubscriber; use Kanboard\Subscriber\RecurringTaskSubscriber; diff --git a/app/Validator/AuthValidator.php b/app/Validator/AuthValidator.php index e77a88c8..36ccdff0 100644 --- a/app/Validator/AuthValidator.php +++ b/app/Validator/AuthValidator.php @@ -23,28 +23,17 @@ class AuthValidator extends Base */ public function validateForm(array $values) { - $result = false; - $errors = array(); - - foreach (array('validateFields', 'validateLocking', 'validateCaptcha', 'validateCredentials') as $method) { - list($result, $errors) = $this->$method($values); - - if (! $result) { - break; - } - } - - return array($result, $errors); + return $this->executeValidators(array('validateFields', 'validateLocking', 'validateCaptcha', 'validateCredentials'), $values); } /** * Validate credentials syntax * - * @access private + * @access protected * @param array $values Form values * @return array $valid, $errors [0] = Success or not, [1] = List of errors */ - private function validateFields(array $values) + protected function validateFields(array $values) { $v = new Validator($values, array( new Validators\Required('username', t('The username is required')), @@ -61,11 +50,11 @@ class AuthValidator extends Base /** * Validate user locking * - * @access private + * @access protected * @param array $values Form values * @return array $valid, $errors [0] = Success or not, [1] = List of errors */ - private function validateLocking(array $values) + protected function validateLocking(array $values) { $result = true; $errors = array(); @@ -82,11 +71,11 @@ class AuthValidator extends Base /** * Validate password syntax * - * @access private + * @access protected * @param array $values Form values * @return array $valid, $errors [0] = Success or not, [1] = List of errors */ - private function validateCredentials(array $values) + protected function validateCredentials(array $values) { $result = true; $errors = array(); @@ -102,11 +91,11 @@ class AuthValidator extends Base /** * Validate captcha * - * @access private + * @access protected * @param array $values Form values * @return boolean */ - private function validateCaptcha(array $values) + protected function validateCaptcha(array $values) { $result = true; $errors = array(); -- cgit v1.2.3 From 6161eaef9e107ddbfc104753eb5d48434de3b824 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 13 Feb 2016 15:38:35 -0500 Subject: Enable/Disable users --- ChangeLog | 1 + app/Api/User.php | 15 ++++ app/Auth/DatabaseAuth.php | 3 +- app/Controller/Projectuser.php | 6 +- app/Controller/User.php | 29 +------ app/Controller/UserStatus.php | 111 +++++++++++++++++++++++++ app/Core/User/UserProfile.php | 2 +- app/Model/ProjectGroupRole.php | 1 + app/Model/ProjectPermission.php | 3 +- app/Model/ProjectUserRole.php | 5 +- app/Model/User.php | 40 ++++++++- app/Schema/Mysql.php | 7 +- app/Schema/Postgres.php | 7 +- app/Schema/Sqlite.php | 7 +- app/ServiceProvider/AuthenticationProvider.php | 3 +- app/ServiceProvider/RouteProvider.php | 1 - app/Template/user/dropdown.php | 27 ++++++ app/Template/user/index.php | 33 ++++---- app/Template/user/remove.php | 13 --- app/Template/user/show.php | 1 + app/Template/user/sidebar.php | 6 -- app/Template/user_status/disable.php | 13 +++ app/Template/user_status/enable.php | 13 +++ app/Template/user_status/remove.php | 13 +++ doc/api-user-procedures.markdown | 93 +++++++++++++++++++++ tests/integration/Base.php | 2 +- tests/integration/UserTest.php | 18 ++++ tests/units/Auth/DatabaseAuthTest.php | 12 ++- tests/units/Model/ProjectGroupRoleTest.php | 38 +++++++++ tests/units/Model/ProjectPermissionTest.php | 22 +++++ tests/units/Model/ProjectUserRoleTest.php | 61 ++++++++++++++ tests/units/Model/UserTest.php | 27 +++++- 32 files changed, 551 insertions(+), 82 deletions(-) create mode 100644 app/Controller/UserStatus.php create mode 100644 app/Template/user/dropdown.php delete mode 100644 app/Template/user/remove.php create mode 100644 app/Template/user_status/disable.php create mode 100644 app/Template/user_status/enable.php create mode 100644 app/Template/user_status/remove.php create mode 100644 tests/integration/UserTest.php (limited to 'app/Model/ProjectUserRole.php') diff --git a/ChangeLog b/ChangeLog index 4f8f3211..830eff80 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ Version 1.0.26 (unreleased) New features: +* Enable/Disable users * Add setting option to disable private projects * Add new config option to disable logout diff --git a/app/Api/User.php b/app/Api/User.php index 9f26615d..48337ac6 100644 --- a/app/Api/User.php +++ b/app/Api/User.php @@ -36,6 +36,21 @@ class User extends \Kanboard\Core\Base return $this->user->remove($user_id); } + public function disableUser($user_id) + { + return $this->user->disable($user_id); + } + + public function enableUser($user_id) + { + return $this->user->enable($user_id); + } + + public function isActiveUser($user_id) + { + return $this->user->isActive($user_id); + } + public function createUser($username, $password, $name = '', $email = '', $role = Role::APP_USER) { $values = array( diff --git a/app/Auth/DatabaseAuth.php b/app/Auth/DatabaseAuth.php index 5a8ee64d..c13af687 100644 --- a/app/Auth/DatabaseAuth.php +++ b/app/Auth/DatabaseAuth.php @@ -65,6 +65,7 @@ class DatabaseAuth extends Base implements PasswordAuthenticationProviderInterfa ->eq('username', $this->username) ->eq('disable_login_form', 0) ->eq('is_ldap_user', 0) + ->eq('is_active', 1) ->findOne(); if (! empty($user) && password_verify($this->password, $user['password'])) { @@ -83,7 +84,7 @@ class DatabaseAuth extends Base implements PasswordAuthenticationProviderInterfa */ public function isValidSession() { - return $this->user->exists($this->userSession->getId()); + return $this->user->isActive($this->userSession->getId()); } /** diff --git a/app/Controller/Projectuser.php b/app/Controller/Projectuser.php index 9cd21021..a6d4fe4e 100644 --- a/app/Controller/Projectuser.php +++ b/app/Controller/Projectuser.php @@ -24,7 +24,7 @@ class Projectuser extends Base $project_ids = $this->projectPermission->getActiveProjectIds($this->userSession->getId()); } - return array($user_id, $project_ids, $this->user->getList(true)); + return array($user_id, $project_ids, $this->user->getActiveUsersList(true)); } private function role($role, $action, $title, $title_user) @@ -33,7 +33,7 @@ class Projectuser extends Base $query = $this->projectPermission->getQueryByRole($project_ids, $role)->callback(array($this->project, 'applyColumnStats')); - if ($user_id !== UserModel::EVERYBODY_ID) { + if ($user_id !== UserModel::EVERYBODY_ID && isset($users[$user_id])) { $query->eq(UserModel::TABLE.'.id', $user_id); $title = t($title_user, $users[$user_id]); } @@ -59,7 +59,7 @@ class Projectuser extends Base $query = $this->taskFinder->getProjectUserOverviewQuery($project_ids, $is_active); - if ($user_id !== UserModel::EVERYBODY_ID) { + if ($user_id !== UserModel::EVERYBODY_ID && isset($users[$user_id])) { $query->eq(TaskModel::TABLE.'.owner_id', $user_id); $title = t($title_user, $users[$user_id]); } diff --git a/app/Controller/User.php b/app/Controller/User.php index 881266d4..f7d7d2e0 100644 --- a/app/Controller/User.php +++ b/app/Controller/User.php @@ -32,7 +32,8 @@ class User extends Base $this->helper->layout->app('user/index', array( 'title' => t('Users').' ('.$paginator->getTotal().')', 'paginator' => $paginator, - ))); + ) + )); } /** @@ -404,30 +405,4 @@ class User extends Base 'user' => $user, ))); } - - /** - * Remove a user - * - * @access public - */ - public function remove() - { - $user = $this->getUser(); - - if ($this->request->getStringParam('confirmation') === 'yes') { - $this->checkCSRFParam(); - - if ($this->user->remove($user['id'])) { - $this->flash->success(t('User removed successfully.')); - } else { - $this->flash->failure(t('Unable to remove this user.')); - } - - $this->response->redirect($this->helper->url->to('user', 'index')); - } - - $this->response->html($this->helper->layout->user('user/remove', array( - 'user' => $user, - ))); - } } diff --git a/app/Controller/UserStatus.php b/app/Controller/UserStatus.php new file mode 100644 index 00000000..b8ee5c91 --- /dev/null +++ b/app/Controller/UserStatus.php @@ -0,0 +1,111 @@ +getUser(); + + $this->response->html($this->helper->layout->user('user_status/remove', array( + 'user' => $user, + ))); + } + + /** + * Remove a user + * + * @access public + */ + public function remove() + { + $user = $this->getUser(); + $this->checkCSRFParam(); + + if ($this->user->remove($user['id'])) { + $this->flash->success(t('User removed successfully.')); + } else { + $this->flash->failure(t('Unable to remove this user.')); + } + + $this->response->redirect($this->helper->url->to('user', 'index')); + } + + /** + * Confirm enable a user + * + * @access public + */ + public function confirmEnable() + { + $user = $this->getUser(); + + $this->response->html($this->helper->layout->user('user_status/enable', array( + 'user' => $user, + ))); + } + + /** + * Enable a user + * + * @access public + */ + public function enable() + { + $user = $this->getUser(); + $this->checkCSRFParam(); + + if ($this->user->enable($user['id'])) { + $this->flash->success(t('User activated successfully.')); + } else { + $this->flash->failure(t('Unable to enable this user.')); + } + + $this->response->redirect($this->helper->url->to('user', 'index')); + } + + /** + * Confirm disable a user + * + * @access public + */ + public function confirmDisable() + { + $user = $this->getUser(); + + $this->response->html($this->helper->layout->user('user_status/disable', array( + 'user' => $user, + ))); + } + + /** + * Disable a user + * + * @access public + */ + public function disable() + { + $user = $this->getUser(); + $this->checkCSRFParam(); + + if ($this->user->disable($user['id'])) { + $this->flash->success(t('User disabled successfully.')); + } else { + $this->flash->failure(t('Unable to disable this user.')); + } + + $this->response->redirect($this->helper->url->to('user', 'index')); + } +} diff --git a/app/Core/User/UserProfile.php b/app/Core/User/UserProfile.php index ccbc7f06..ef325801 100644 --- a/app/Core/User/UserProfile.php +++ b/app/Core/User/UserProfile.php @@ -52,7 +52,7 @@ class UserProfile extends Base $this->groupSync->synchronize($profile['id'], $user->getExternalGroupIds()); } - if (! empty($profile)) { + if (! empty($profile) && $profile['is_active'] == 1) { $this->userSession->initialize($profile); return true; } diff --git a/app/Model/ProjectGroupRole.php b/app/Model/ProjectGroupRole.php index 591b28c6..750ba7fb 100644 --- a/app/Model/ProjectGroupRole.php +++ b/app/Model/ProjectGroupRole.php @@ -106,6 +106,7 @@ class ProjectGroupRole extends Base ->join(GroupMember::TABLE, 'user_id', 'id', User::TABLE) ->join(self::TABLE, 'group_id', 'group_id', GroupMember::TABLE) ->eq(self::TABLE.'.project_id', $project_id) + ->eq(User::TABLE.'.is_active', 1) ->in(self::TABLE.'.role', array(Role::PROJECT_MANAGER, Role::PROJECT_MEMBER)) ->asc(User::TABLE.'.username') ->findAll(); diff --git a/app/Model/ProjectPermission.php b/app/Model/ProjectPermission.php index cea62e13..db1573ae 100644 --- a/app/Model/ProjectPermission.php +++ b/app/Model/ProjectPermission.php @@ -107,7 +107,8 @@ class ProjectPermission extends Base */ public function isAssignable($project_id, $user_id) { - return in_array($this->projectUserRole->getUserRole($project_id, $user_id), array(Role::PROJECT_MEMBER, Role::PROJECT_MANAGER)); + return $this->user->isActive($user_id) && + in_array($this->projectUserRole->getUserRole($project_id, $user_id), array(Role::PROJECT_MEMBER, Role::PROJECT_MANAGER)); } /** diff --git a/app/Model/ProjectUserRole.php b/app/Model/ProjectUserRole.php index 8149a253..56da679c 100644 --- a/app/Model/ProjectUserRole.php +++ b/app/Model/ProjectUserRole.php @@ -152,13 +152,14 @@ class ProjectUserRole extends Base public function getAssignableUsers($project_id) { if ($this->projectPermission->isEverybodyAllowed($project_id)) { - return $this->user->getList(); + return $this->user->getActiveUsersList(); } $userMembers = $this->db->table(self::TABLE) ->columns(User::TABLE.'.id', User::TABLE.'.username', User::TABLE.'.name') ->join(User::TABLE, 'id', 'user_id') - ->eq('project_id', $project_id) + ->eq(User::TABLE.'.is_active', 1) + ->eq(self::TABLE.'.project_id', $project_id) ->in(self::TABLE.'.role', array(Role::PROJECT_MANAGER, Role::PROJECT_MEMBER)) ->findAll(); diff --git a/app/Model/User.php b/app/Model/User.php index dd622207..e2494c4c 100644 --- a/app/Model/User.php +++ b/app/Model/User.php @@ -40,6 +40,18 @@ class User extends Base return $this->db->table(self::TABLE)->eq('id', $user_id)->exists(); } + /** + * Return true if the user is active + * + * @access public + * @param integer $user_id User id + * @return boolean + */ + public function isActive($user_id) + { + return $this->db->table(self::TABLE)->eq('id', $user_id)->eq('is_active', 1)->exists(); + } + /** * Get query to fetch all users * @@ -193,9 +205,9 @@ class User extends Base * @param boolean $prepend Prepend "All users" * @return array */ - public function getList($prepend = false) + public function getActiveUsersList($prepend = false) { - $users = $this->db->table(self::TABLE)->columns('id', 'username', 'name')->findAll(); + $users = $this->db->table(self::TABLE)->eq('is_active', 1)->columns('id', 'username', 'name')->findAll(); $listing = $this->prepareList($users); if ($prepend) { @@ -280,6 +292,30 @@ class User extends Base return $result; } + /** + * Disable a specific user + * + * @access public + * @param integer $user_id + * @return boolean + */ + public function disable($user_id) + { + return $this->db->table(self::TABLE)->eq('id', $user_id)->update(array('is_active' => 0)); + } + + /** + * Enable a specific user + * + * @access public + * @param integer $user_id + * @return boolean + */ + public function enable($user_id) + { + return $this->db->table(self::TABLE)->eq('id', $user_id)->update(array('is_active' => 1)); + } + /** * Remove a specific user * diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php index 036958b6..1cebbd22 100644 --- a/app/Schema/Mysql.php +++ b/app/Schema/Mysql.php @@ -6,7 +6,12 @@ use PDO; use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; -const VERSION = 104; +const VERSION = 105; + +function version_105(PDO $pdo) +{ + $pdo->exec("ALTER TABLE users ADD COLUMN is_active TINYINT(1) DEFAULT 1"); +} function version_104(PDO $pdo) { diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php index 363b633b..b0b89a7c 100644 --- a/app/Schema/Postgres.php +++ b/app/Schema/Postgres.php @@ -6,7 +6,12 @@ use PDO; use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; -const VERSION = 84; +const VERSION = 85; + +function version_85(PDO $pdo) +{ + $pdo->exec("ALTER TABLE users ADD COLUMN is_active BOOLEAN DEFAULT '1'"); +} function version_84(PDO $pdo) { diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php index bc701341..aa10e58b 100644 --- a/app/Schema/Sqlite.php +++ b/app/Schema/Sqlite.php @@ -6,7 +6,12 @@ use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; use PDO; -const VERSION = 96; +const VERSION = 97; + +function version_97(PDO $pdo) +{ + $pdo->exec("ALTER TABLE users ADD COLUMN is_active INTEGER DEFAULT 1"); +} function version_96(PDO $pdo) { diff --git a/app/ServiceProvider/AuthenticationProvider.php b/app/ServiceProvider/AuthenticationProvider.php index 9b5cdbe9..c2f7a5c4 100644 --- a/app/ServiceProvider/AuthenticationProvider.php +++ b/app/ServiceProvider/AuthenticationProvider.php @@ -134,7 +134,8 @@ class AuthenticationProvider implements ServiceProviderInterface $acl->add('Projectuser', '*', Role::APP_MANAGER); $acl->add('Twofactor', 'disable', Role::APP_ADMIN); $acl->add('UserImport', '*', Role::APP_ADMIN); - $acl->add('User', array('index', 'create', 'save', 'authentication', 'remove'), Role::APP_ADMIN); + $acl->add('User', array('index', 'create', 'save', 'authentication'), Role::APP_ADMIN); + $acl->add('UserStatus', '*', Role::APP_ADMIN); return $acl; } diff --git a/app/ServiceProvider/RouteProvider.php b/app/ServiceProvider/RouteProvider.php index 683ea1c1..5003eb88 100644 --- a/app/ServiceProvider/RouteProvider.php +++ b/app/ServiceProvider/RouteProvider.php @@ -157,7 +157,6 @@ class RouteProvider implements ServiceProviderInterface $container['route']->addRoute('user/:user_id/accounts', 'user', 'external'); $container['route']->addRoute('user/:user_id/integrations', 'user', 'integrations'); $container['route']->addRoute('user/:user_id/authentication', 'user', 'authentication'); - $container['route']->addRoute('user/:user_id/remove', 'user', 'remove'); $container['route']->addRoute('user/:user_id/2fa', 'twofactor', 'index'); // Groups diff --git a/app/Template/user/dropdown.php b/app/Template/user/dropdown.php new file mode 100644 index 00000000..b74ed6e0 --- /dev/null +++ b/app/Template/user/dropdown.php @@ -0,0 +1,27 @@ + \ No newline at end of file diff --git a/app/Template/user/index.php b/app/Template/user/index.php index cb7416d6..494c1465 100644 --- a/app/Template/user/index.php +++ b/app/Template/user/index.php @@ -12,23 +12,21 @@ isEmpty()): ?>

    - +
    - - - - - - - - + + + + + + + + getCollection() as $user): ?> - + diff --git a/app/Template/user/remove.php b/app/Template/user/remove.php deleted file mode 100644 index 810a3a3f..00000000 --- a/app/Template/user/remove.php +++ /dev/null @@ -1,13 +0,0 @@ - - -
    -

    - -
    - url->link(t('Yes'), 'user', 'remove', array('user_id' => $user['id'], 'confirmation' => 'yes'), true, 'btn btn-red') ?> - - url->link(t('cancel'), 'user', 'show', array('user_id' => $user['id'])) ?> -
    -
    \ No newline at end of file diff --git a/app/Template/user/show.php b/app/Template/user/show.php index 89c6b36b..9da56666 100644 --- a/app/Template/user/show.php +++ b/app/Template/user/show.php @@ -5,6 +5,7 @@
  • e($user['username']) ?>
  • e($user['name']) ?: t('None') ?>
  • e($user['email']) ?: t('None') ?>
  • +
  • \ No newline at end of file diff --git a/app/Template/user_status/disable.php b/app/Template/user_status/disable.php new file mode 100644 index 00000000..90d8c757 --- /dev/null +++ b/app/Template/user_status/disable.php @@ -0,0 +1,13 @@ + + +
    +

    + +
    + url->link(t('Yes'), 'UserStatus', 'disable', array('user_id' => $user['id']), true, 'btn btn-red') ?> + + url->link(t('cancel'), 'user', 'index', array(), false, 'close-popover') ?> +
    +
    diff --git a/app/Template/user_status/enable.php b/app/Template/user_status/enable.php new file mode 100644 index 00000000..cd3d4947 --- /dev/null +++ b/app/Template/user_status/enable.php @@ -0,0 +1,13 @@ + + +
    +

    + +
    + url->link(t('Yes'), 'UserStatus', 'enable', array('user_id' => $user['id']), true, 'btn btn-red') ?> + + url->link(t('cancel'), 'user', 'index', array(), false, 'close-popover') ?> +
    +
    diff --git a/app/Template/user_status/remove.php b/app/Template/user_status/remove.php new file mode 100644 index 00000000..cd5c09a6 --- /dev/null +++ b/app/Template/user_status/remove.php @@ -0,0 +1,13 @@ + + +
    +

    + +
    + url->link(t('Yes'), 'UserStatus', 'remove', array('user_id' => $user['id']), true, 'btn btn-red') ?> + + url->link(t('cancel'), 'user', 'index', array(), false, 'close-popover') ?> +
    +
    diff --git a/doc/api-user-procedures.markdown b/doc/api-user-procedures.markdown index 9b43e1e1..6c09355d 100644 --- a/doc/api-user-procedures.markdown +++ b/doc/api-user-procedures.markdown @@ -262,3 +262,96 @@ Response example: "result": true } ``` + +## disableUser + +- Purpose: **Disable a user** +- Parameters: + - **user_id** (integer, required) +- Result on success: **true** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "disableUser", + "id": 2094191872, + "params": { + "user_id": 1 + } +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 2094191872, + "result": true +} +``` + +## enableUser + +- Purpose: **Enable a user** +- Parameters: + - **user_id** (integer, required) +- Result on success: **true** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "enableUser", + "id": 2094191872, + "params": { + "user_id": 1 + } +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 2094191872, + "result": true +} +``` + +## isActiveUser + +- Purpose: **Check if a user is active** +- Parameters: + - **user_id** (integer, required) +- Result on success: **true** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "isActiveUser", + "id": 2094191872, + "params": { + "user_id": 1 + } +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 2094191872, + "result": true +} +``` diff --git a/tests/integration/Base.php b/tests/integration/Base.php index 6facd9ce..983d0ed9 100644 --- a/tests/integration/Base.php +++ b/tests/integration/Base.php @@ -35,7 +35,7 @@ abstract class Base extends PHPUnit_Framework_TestCase { $this->app = new JsonRPC\Client(API_URL); $this->app->authentication('jsonrpc', API_KEY); - $this->app->debug = true; + // $this->app->debug = true; $this->admin = new JsonRPC\Client(API_URL); $this->admin->authentication('admin', 'admin'); diff --git a/tests/integration/UserTest.php b/tests/integration/UserTest.php new file mode 100644 index 00000000..10da051c --- /dev/null +++ b/tests/integration/UserTest.php @@ -0,0 +1,18 @@ +assertEquals(2, $this->app->createUser(array('username' => 'someone', 'password' => 'test123'))); + $this->assertTrue($this->app->isActiveUser(2)); + + $this->assertTrue($this->app->disableUser(2)); + $this->assertFalse($this->app->isActiveUser(2)); + + $this->assertTrue($this->app->enableUser(2)); + $this->assertTrue($this->app->isActiveUser(2)); + } +} diff --git a/tests/units/Auth/DatabaseAuthTest.php b/tests/units/Auth/DatabaseAuthTest.php index a13b7fee..ac099a7e 100644 --- a/tests/units/Auth/DatabaseAuthTest.php +++ b/tests/units/Auth/DatabaseAuthTest.php @@ -3,6 +3,7 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Auth\DatabaseAuth; +use Kanboard\Model\User; class DatabaseAuthTest extends Base { @@ -40,12 +41,21 @@ class DatabaseAuthTest extends Base public function testIsvalidSession() { + $userModel = new User($this->container); $provider = new DatabaseAuth($this->container); + $this->assertFalse($provider->isValidSession()); - $this->container['sessionStorage']->user = array('id' => 1); + $this->assertEquals(2, $userModel->create(array('username' => 'foobar'))); + + $this->container['sessionStorage']->user = array('id' => 2); $this->assertTrue($provider->isValidSession()); + $this->container['sessionStorage']->user = array('id' => 3); + $this->assertFalse($provider->isValidSession()); + + $this->assertTrue($userModel->disable(2)); + $this->container['sessionStorage']->user = array('id' => 2); $this->assertFalse($provider->isValidSession()); } diff --git a/tests/units/Model/ProjectGroupRoleTest.php b/tests/units/Model/ProjectGroupRoleTest.php index 29a9536b..e38e812a 100644 --- a/tests/units/Model/ProjectGroupRoleTest.php +++ b/tests/units/Model/ProjectGroupRoleTest.php @@ -204,6 +204,44 @@ class ProjectGroupRoleTest extends Base $this->assertEquals('', $users[1]['name']); } + public function testGetAssignableUsersWithDisabledUsers() + { + $userModel = new User($this->container); + $projectModel = new Project($this->container); + $groupModel = new Group($this->container); + $groupMemberModel = new GroupMember($this->container); + $groupRoleModel = new ProjectGroupRole($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'Project 2'))); + + $this->assertEquals(2, $userModel->create(array('username' => 'user 1', 'name' => 'User #1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user 2', 'is_active' => 0))); + $this->assertEquals(4, $userModel->create(array('username' => 'user 3'))); + + $this->assertEquals(1, $groupModel->create('Group A')); + $this->assertEquals(2, $groupModel->create('Group B')); + $this->assertEquals(3, $groupModel->create('Group C')); + + $this->assertTrue($groupMemberModel->addUser(1, 4)); + $this->assertTrue($groupMemberModel->addUser(2, 3)); + $this->assertTrue($groupMemberModel->addUser(3, 2)); + + $this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_VIEWER)); + $this->assertTrue($groupRoleModel->addGroup(1, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($groupRoleModel->addGroup(1, 3, Role::PROJECT_MANAGER)); + + $users = $groupRoleModel->getAssignableUsers(2); + $this->assertCount(0, $users); + + $users = $groupRoleModel->getAssignableUsers(1); + $this->assertCount(1, $users); + + $this->assertEquals(2, $users[0]['id']); + $this->assertEquals('user 1', $users[0]['username']); + $this->assertEquals('User #1', $users[0]['name']); + } + public function testGetProjectsByUser() { $userModel = new User($this->container); diff --git a/tests/units/Model/ProjectPermissionTest.php b/tests/units/Model/ProjectPermissionTest.php index 035a1246..10fcdcc2 100644 --- a/tests/units/Model/ProjectPermissionTest.php +++ b/tests/units/Model/ProjectPermissionTest.php @@ -192,6 +192,28 @@ class ProjectPermissionTest extends Base $this->assertFalse($projectPermission->isAssignable(2, 5)); } + public function testIsAssignableWhenUserIsDisabled() + { + $userModel = new User($this->container); + $projectModel = new Project($this->container); + $groupModel = new Group($this->container); + $groupRoleModel = new ProjectGroupRole($this->container); + $groupMemberModel = new GroupMember($this->container); + $userRoleModel = new ProjectUserRole($this->container); + $projectPermission = new ProjectPermission($this->container); + + $this->assertEquals(2, $userModel->create(array('username' => 'user 1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user 2', 'is_active' => 0))); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); + + $this->assertTrue($userRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); + + $this->assertTrue($projectPermission->isAssignable(1, 2)); + $this->assertFalse($projectPermission->isAssignable(1, 3)); + } + public function testIsMember() { $userModel = new User($this->container); diff --git a/tests/units/Model/ProjectUserRoleTest.php b/tests/units/Model/ProjectUserRoleTest.php index c6b4eb7c..06cd1b70 100644 --- a/tests/units/Model/ProjectUserRoleTest.php +++ b/tests/units/Model/ProjectUserRoleTest.php @@ -8,6 +8,7 @@ use Kanboard\Model\Group; use Kanboard\Model\GroupMember; use Kanboard\Model\ProjectGroupRole; use Kanboard\Model\ProjectUserRole; +use Kanboard\Model\ProjectPermission; use Kanboard\Core\Security\Role; class ProjectUserRoleTest extends Base @@ -100,6 +101,36 @@ class ProjectUserRoleTest extends Base $this->assertEquals('', $userRoleModel->getUserRole(1, 2)); } + public function testGetAssignableUsersWithDisabledUsers() + { + $projectModel = new Project($this->container); + $userModel = new User($this->container); + $userRoleModel = new ProjectUserRole($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Test'))); + $this->assertEquals(2, $userModel->create(array('username' => 'user1', 'name' => 'User1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user2', 'name' => 'User2'))); + + $this->assertTrue($userRoleModel->addUser(1, 1, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); + + $users = $userRoleModel->getAssignableUsers(1); + $this->assertCount(3, $users); + + $this->assertEquals('admin', $users[1]); + $this->assertEquals('User1', $users[2]); + $this->assertEquals('User2', $users[3]); + + $this->assertTrue($userModel->disable(2)); + + $users = $userRoleModel->getAssignableUsers(1); + $this->assertCount(2, $users); + + $this->assertEquals('admin', $users[1]); + $this->assertEquals('User2', $users[3]); + } + public function testGetAssignableUsersWithoutGroups() { $projectModel = new Project($this->container); @@ -219,6 +250,36 @@ class ProjectUserRoleTest extends Base $this->assertEquals('User4', $users[5]); } + public function testGetAssignableUsersWithDisabledUsersAndEverybodyAllowed() + { + $projectModel = new Project($this->container); + $projectPermission = new ProjectPermission($this->container); + $userModel = new User($this->container); + $userRoleModel = new ProjectUserRole($this->container); + + $this->assertEquals(2, $userModel->create(array('username' => 'user1', 'name' => 'User1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user2', 'name' => 'User2'))); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1', 'is_everybody_allowed' => 1))); + + $this->assertTrue($projectPermission->isEverybodyAllowed(1)); + + $users = $userRoleModel->getAssignableUsers(1); + $this->assertCount(3, $users); + + $this->assertEquals('admin', $users[1]); + $this->assertEquals('User1', $users[2]); + $this->assertEquals('User2', $users[3]); + + $this->assertTrue($userModel->disable(2)); + + $users = $userRoleModel->getAssignableUsers(1); + $this->assertCount(2, $users); + + $this->assertEquals('admin', $users[1]); + $this->assertEquals('User2', $users[3]); + } + public function testGetProjectsByUser() { $userModel = new User($this->container); diff --git a/tests/units/Model/UserTest.php b/tests/units/Model/UserTest.php index 0987fa56..e411da0c 100644 --- a/tests/units/Model/UserTest.php +++ b/tests/units/Model/UserTest.php @@ -96,13 +96,14 @@ class UserTest extends Base $this->assertEquals('you', $users[2]['username']); } - public function testGetList() + public function testGetActiveUsersList() { $u = new User($this->container); $this->assertEquals(2, $u->create(array('username' => 'you'))); $this->assertEquals(3, $u->create(array('username' => 'me', 'name' => 'Me too'))); + $this->assertEquals(4, $u->create(array('username' => 'foobar', 'is_active' => 0))); - $users = $u->getList(); + $users = $u->getActiveUsersList(); $expected = array( 1 => 'admin', @@ -112,7 +113,7 @@ class UserTest extends Base $this->assertEquals($expected, $users); - $users = $u->getList(true); + $users = $u->getActiveUsersList(true); $expected = array( User::EVERYBODY_ID => 'Everybody', @@ -391,4 +392,24 @@ class UserTest extends Base $this->assertEquals('toto', $user['username']); $this->assertEmpty($user['token']); } + + public function testEnableDisable() + { + $userModel = new User($this->container); + $this->assertEquals(2, $userModel->create(array('username' => 'toto'))); + + $this->assertTrue($userModel->isActive(2)); + $user = $userModel->getById(2); + $this->assertEquals(1, $user['is_active']); + + $this->assertTrue($userModel->disable(2)); + $user = $userModel->getById(2); + $this->assertEquals(0, $user['is_active']); + $this->assertFalse($userModel->isActive(2)); + + $this->assertTrue($userModel->enable(2)); + $user = $userModel->getById(2); + $this->assertEquals(1, $user['is_active']); + $this->assertTrue($userModel->isActive(2)); + } } -- cgit v1.2.3
    order(t('Id'), 'id') ?>order(t('Username'), 'username') ?>order(t('Name'), 'name') ?>order(t('Email'), 'email') ?>order(t('Role'), 'role') ?>order(t('Two factor authentication'), 'twofactor_activated') ?>order(t('Notifications'), 'notifications_enabled') ?>order(t('Account type'), 'is_ldap_user') ?>order(t('Username'), 'username') ?>order(t('Name'), 'name') ?>order(t('Email'), 'email') ?>order(t('Role'), 'role') ?>order(t('Two Factor'), 'twofactor_activated') ?>order(t('Account type'), 'is_ldap_user') ?>order(t('Status'), 'is_active') ?>
    - url->link('#'.$user['id'], 'user', 'show', array('user_id' => $user['id'])) ?> - +   url->link($this->e($user['username']), 'user', 'show', array('user_id' => $user['id'])) ?> @@ -44,14 +42,17 @@ - - + + + + - + - + render('user/dropdown', array('user' => $user)) ?>