From d560f84b374fa1b3345dc582eddd6bb7b9138674 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Thu, 23 Jun 2016 20:26:19 -0400 Subject: Added models for tags --- app/Core/Base.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/Core') diff --git a/app/Core/Base.php b/app/Core/Base.php index 7b4462e2..6712cbce 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -86,6 +86,7 @@ use Pimple\Container; * @property \Kanboard\Model\SubtaskModel $subtaskModel * @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel * @property \Kanboard\Model\SwimlaneModel $swimlaneModel + * @property \Kanboard\Model\TagModel $tagModel * @property \Kanboard\Model\TaskModel $taskModel * @property \Kanboard\Model\TaskAnalyticModel $taskAnalyticModel * @property \Kanboard\Model\TaskCreationModel $taskCreationModel @@ -96,6 +97,7 @@ use Pimple\Container; * @property \Kanboard\Model\TaskModificationModel $taskModificationModel * @property \Kanboard\Model\TaskPositionModel $taskPositionModel * @property \Kanboard\Model\TaskStatusModel $taskStatusModel + * @property \Kanboard\Model\TaskTagModel $taskTagModel * @property \Kanboard\Model\TaskMetadataModel $taskMetadataModel * @property \Kanboard\Model\TimezoneModel $timezoneModel * @property \Kanboard\Model\TransitionModel $transitionModel -- cgit v1.2.3 From ce367a24fca09bb1fa05da167f36db54712c8fa1 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Fri, 24 Jun 2016 22:10:14 -0400 Subject: Added tag modification from the user interface --- app/Controller/ProjectTagController.php | 134 +++++++++++++++++++++++++ app/Controller/TagController.php | 121 ++++++++++++++++++++++ app/Core/Base.php | 3 +- app/Model/TagModel.php | 23 +++++ app/ServiceProvider/AuthenticationProvider.php | 2 + app/ServiceProvider/ClassProvider.php | 3 +- app/ServiceProvider/RouteProvider.php | 2 + app/Template/config/sidebar.php | 3 + app/Template/project/sidebar.php | 3 + app/Template/project_tag/create.php | 16 +++ app/Template/project_tag/edit.php | 17 ++++ app/Template/project_tag/index.php | 31 ++++++ app/Template/project_tag/remove.php | 15 +++ app/Template/tag/create.php | 16 +++ app/Template/tag/edit.php | 17 ++++ app/Template/tag/index.php | 31 ++++++ app/Template/tag/remove.php | 15 +++ app/Validator/TagValidator.php | 77 ++++++++++++++ 18 files changed, 527 insertions(+), 2 deletions(-) create mode 100644 app/Controller/ProjectTagController.php create mode 100644 app/Controller/TagController.php create mode 100644 app/Template/project_tag/create.php create mode 100644 app/Template/project_tag/edit.php create mode 100644 app/Template/project_tag/index.php create mode 100644 app/Template/project_tag/remove.php create mode 100644 app/Template/tag/create.php create mode 100644 app/Template/tag/edit.php create mode 100644 app/Template/tag/index.php create mode 100644 app/Template/tag/remove.php create mode 100644 app/Validator/TagValidator.php (limited to 'app/Core') diff --git a/app/Controller/ProjectTagController.php b/app/Controller/ProjectTagController.php new file mode 100644 index 00000000..acf514d3 --- /dev/null +++ b/app/Controller/ProjectTagController.php @@ -0,0 +1,134 @@ +getProject(); + + $this->response->html($this->helper->layout->project('project_tag/index', array( + 'project' => $project, + 'tags' => $this->tagModel->getAllByProject($project['id']), + 'title' => t('Project tags management'), + ))); + } + + public function create(array $values = array(), array $errors = array()) + { + $project = $this->getProject(); + + if (empty($values)) { + $values['project_id'] = $project['id']; + } + + $this->response->html($this->template->render('project_tag/create', array( + 'project' => $project, + 'values' => $values, + 'errors' => $errors, + ))); + } + + public function save() + { + $project = $this->getProject(); + $values = $this->request->getValues(); + list($valid, $errors) = $this->tagValidator->validateCreation($values); + + if ($valid) { + if ($this->tagModel->create($project['id'], $values['name']) > 0) { + $this->flash->success(t('Tag created successfully.')); + } else { + $this->flash->failure(t('Unable to create this tag.')); + } + + $this->response->redirect($this->helper->url->to('ProjectTagController', 'index', array('project_id' => $project['id']))); + } else { + $this->create($values, $errors); + } + } + + public function edit(array $values = array(), array $errors = array()) + { + $project = $this->getProject(); + $tag_id = $this->request->getIntegerParam('tag_id'); + $tag = $this->tagModel->getById($tag_id); + + if (empty($values)) { + $values = $tag; + } + + $this->response->html($this->template->render('project_tag/edit', array( + 'project' => $project, + 'tag' => $tag, + 'values' => $values, + 'errors' => $errors, + ))); + } + + public function update() + { + $project = $this->getProject(); + $tag_id = $this->request->getIntegerParam('tag_id'); + $tag = $this->tagModel->getById($tag_id); + $values = $this->request->getValues(); + list($valid, $errors) = $this->tagValidator->validateModification($values); + + if ($tag['project_id'] != $project['id']) { + throw new AccessForbiddenException(); + } + + if ($valid) { + if ($this->tagModel->update($values['id'], $values['name'])) { + $this->flash->success(t('Tag updated successfully.')); + } else { + $this->flash->failure(t('Unable to update this tag.')); + } + + $this->response->redirect($this->helper->url->to('ProjectTagController', 'index', array('project_id' => $project['id']))); + } else { + $this->edit($values, $errors); + } + } + + public function confirm() + { + $project = $this->getProject(); + $tag_id = $this->request->getIntegerParam('tag_id'); + $tag = $this->tagModel->getById($tag_id); + + $this->response->html($this->template->render('project_tag/remove', array( + 'tag' => $tag, + 'project' => $project, + ))); + } + + public function remove() + { + $this->checkCSRFParam(); + $project = $this->getProject(); + $tag_id = $this->request->getIntegerParam('tag_id'); + $tag = $this->tagModel->getById($tag_id); + + if ($tag['project_id'] != $project['id']) { + throw new AccessForbiddenException(); + } + + if ($this->tagModel->remove($tag_id)) { + $this->flash->success(t('Tag removed successfully.')); + } else { + $this->flash->failure(t('Unable to remove this tag.')); + } + + $this->response->redirect($this->helper->url->to('ProjectTagController', 'index', array('project_id' => $project['id']))); + } +} diff --git a/app/Controller/TagController.php b/app/Controller/TagController.php new file mode 100644 index 00000000..b8389910 --- /dev/null +++ b/app/Controller/TagController.php @@ -0,0 +1,121 @@ +response->html($this->helper->layout->config('tag/index', array( + 'tags' => $this->tagModel->getAllByProject(0), + 'title' => t('Settings').' > '.t('Global tags management'), + ))); + } + + public function create(array $values = array(), array $errors = array()) + { + if (empty($values)) { + $values['project_id'] = 0; + } + + $this->response->html($this->template->render('tag/create', array( + 'values' => $values, + 'errors' => $errors, + ))); + } + + public function save() + { + $values = $this->request->getValues(); + list($valid, $errors) = $this->tagValidator->validateCreation($values); + + if ($valid) { + if ($this->tagModel->create(0, $values['name']) > 0) { + $this->flash->success(t('Tag created successfully.')); + } else { + $this->flash->failure(t('Unable to create this tag.')); + } + + $this->response->redirect($this->helper->url->to('TagController', 'index')); + } else { + $this->create($values, $errors); + } + } + + public function edit(array $values = array(), array $errors = array()) + { + $tag_id = $this->request->getIntegerParam('tag_id'); + $tag = $this->tagModel->getById($tag_id); + + if (empty($values)) { + $values = $tag; + } + + $this->response->html($this->template->render('tag/edit', array( + 'tag' => $tag, + 'values' => $values, + 'errors' => $errors, + ))); + } + + public function update() + { + $tag_id = $this->request->getIntegerParam('tag_id'); + $tag = $this->tagModel->getById($tag_id); + $values = $this->request->getValues(); + list($valid, $errors) = $this->tagValidator->validateModification($values); + + if ($tag['project_id'] != 0) { + throw new AccessForbiddenException(); + } + + if ($valid) { + if ($this->tagModel->update($values['id'], $values['name'])) { + $this->flash->success(t('Tag updated successfully.')); + } else { + $this->flash->failure(t('Unable to update this tag.')); + } + + $this->response->redirect($this->helper->url->to('TagController', 'index')); + } else { + $this->edit($values, $errors); + } + } + + public function confirm() + { + $tag_id = $this->request->getIntegerParam('tag_id'); + $tag = $this->tagModel->getById($tag_id); + + $this->response->html($this->template->render('tag/remove', array( + 'tag' => $tag, + ))); + } + + public function remove() + { + $this->checkCSRFParam(); + $tag_id = $this->request->getIntegerParam('tag_id'); + $tag = $this->tagModel->getById($tag_id); + + if ($tag['project_id'] != 0) { + throw new AccessForbiddenException(); + } + + if ($this->tagModel->remove($tag_id)) { + $this->flash->success(t('Tag removed successfully.')); + } else { + $this->flash->failure(t('Unable to remove this tag.')); + } + + $this->response->redirect($this->helper->url->to('TagController', 'index')); + } +} diff --git a/app/Core/Base.php b/app/Core/Base.php index 6712cbce..e5dd6ad9 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -116,14 +116,15 @@ use Pimple\Container; * @property \Kanboard\Validator\CommentValidator $commentValidator * @property \Kanboard\Validator\CurrencyValidator $currencyValidator * @property \Kanboard\Validator\CustomFilterValidator $customFilterValidator + * @property \Kanboard\Validator\ExternalLinkValidator $externalLinkValidator * @property \Kanboard\Validator\GroupValidator $groupValidator * @property \Kanboard\Validator\LinkValidator $linkValidator * @property \Kanboard\Validator\PasswordResetValidator $passwordResetValidator * @property \Kanboard\Validator\ProjectValidator $projectValidator * @property \Kanboard\Validator\SubtaskValidator $subtaskValidator * @property \Kanboard\Validator\SwimlaneValidator $swimlaneValidator + * @property \Kanboard\Validator\TagValidator $tagValidator * @property \Kanboard\Validator\TaskLinkValidator $taskLinkValidator - * @property \Kanboard\Validator\ExternalLinkValidator $externalLinkValidator * @property \Kanboard\Validator\TaskValidator $taskValidator * @property \Kanboard\Validator\UserValidator $userValidator * @property \Kanboard\Import\TaskImport $taskImport diff --git a/app/Model/TagModel.php b/app/Model/TagModel.php index 8eb5e5ba..e85c5a87 100644 --- a/app/Model/TagModel.php +++ b/app/Model/TagModel.php @@ -93,6 +93,29 @@ class TagModel extends Base ->findOneColumn('id'); } + /** + * Return true if the tag exists + * + * @access public + * @param integer $project_id + * @param string $tag + * @param integer $tag_id + * @return boolean + */ + public function exists($project_id, $tag, $tag_id = 0) + { + return $this->db + ->table(self::TABLE) + ->neq('id', $tag_id) + ->beginOr() + ->eq('project_id', 0) + ->eq('project_id', $project_id) + ->closeOr() + ->ilike('name', $tag) + ->asc('project_id') + ->exists(); + } + /** * Return tag id and create a new tag if necessary * diff --git a/app/ServiceProvider/AuthenticationProvider.php b/app/ServiceProvider/AuthenticationProvider.php index 2fad8a3a..84e4354d 100644 --- a/app/ServiceProvider/AuthenticationProvider.php +++ b/app/ServiceProvider/AuthenticationProvider.php @@ -88,6 +88,7 @@ class AuthenticationProvider implements ServiceProviderInterface $acl->add('ProjectFileController', '*', Role::PROJECT_MEMBER); $acl->add('ProjectUserOverviewController', '*', Role::PROJECT_MANAGER); $acl->add('ProjectStatusController', '*', Role::PROJECT_MANAGER); + $acl->add('ProjectTagController', '*', Role::PROJECT_MANAGER); $acl->add('SubtaskController', '*', Role::PROJECT_MEMBER); $acl->add('SubtaskRestrictionController', '*', Role::PROJECT_MEMBER); $acl->add('SubtaskStatusController', '*', Role::PROJECT_MEMBER); @@ -131,6 +132,7 @@ class AuthenticationProvider implements ServiceProviderInterface $acl->add('AvatarFileController', 'show', Role::APP_PUBLIC); $acl->add('ConfigController', '*', Role::APP_ADMIN); + $acl->add('TagController', '*', Role::APP_ADMIN); $acl->add('PluginController', '*', Role::APP_ADMIN); $acl->add('CurrencyController', '*', Role::APP_ADMIN); $acl->add('ProjectGanttController', '*', Role::APP_MANAGER); diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 778b4f9e..c0fb93bd 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -99,8 +99,9 @@ class ClassProvider implements ServiceProviderInterface 'ProjectValidator', 'SubtaskValidator', 'SwimlaneValidator', - 'TaskValidator', + 'TagValidator', 'TaskLinkValidator', + 'TaskValidator', 'UserValidator', ), 'Import' => array( diff --git a/app/ServiceProvider/RouteProvider.php b/app/ServiceProvider/RouteProvider.php index 3d1391df..8801e3d0 100644 --- a/app/ServiceProvider/RouteProvider.php +++ b/app/ServiceProvider/RouteProvider.php @@ -59,6 +59,7 @@ class RouteProvider implements ServiceProviderInterface $container['route']->addRoute('project/:project_id/duplicate', 'ProjectViewController', 'duplicate'); $container['route']->addRoute('project/:project_id/permissions', 'ProjectPermissionController', 'index'); $container['route']->addRoute('project/:project_id/activity', 'ActivityController', 'project'); + $container['route']->addRoute('project/:project_id/tags', 'ProjectTagController', 'index'); // Project Overview $container['route']->addRoute('project/:project_id/overview', 'ProjectOverviewController', 'show'); @@ -174,6 +175,7 @@ class RouteProvider implements ServiceProviderInterface $container['route']->addRoute('settings/api', 'ConfigController', 'api'); $container['route']->addRoute('settings/links', 'LinkController', 'index'); $container['route']->addRoute('settings/currencies', 'CurrencyController', 'index'); + $container['route']->addRoute('settings/tags', 'TagController', 'index'); // Plugins $container['route']->addRoute('extensions', 'PluginController', 'show'); diff --git a/app/Template/config/sidebar.php b/app/Template/config/sidebar.php index 29caa0ef..e304f0d0 100644 --- a/app/Template/config/sidebar.php +++ b/app/Template/config/sidebar.php @@ -19,6 +19,9 @@
  • app->checkMenuSelection('ConfigController', 'calendar') ?>> url->link(t('Calendar settings'), 'ConfigController', 'calendar') ?>
  • +
  • app->checkMenuSelection('TagController', 'index') ?>> + url->link(t('Tags management'), 'TagController', 'index') ?> +
  • app->checkMenuSelection('LinkController') ?>> url->link(t('Link settings'), 'LinkController', 'index') ?>
  • diff --git a/app/Template/project/sidebar.php b/app/Template/project/sidebar.php index 9bc0c9c4..d0f50596 100644 --- a/app/Template/project/sidebar.php +++ b/app/Template/project/sidebar.php @@ -32,6 +32,9 @@
  • app->checkMenuSelection('CategoryController') ?>> url->link(t('Categories'), 'CategoryController', 'index', array('project_id' => $project['id'])) ?>
  • +
  • app->checkMenuSelection('ProjectTagController') ?>> + url->link(t('Tags'), 'ProjectTagController', 'index', array('project_id' => $project['id'])) ?> +
  • app->checkMenuSelection('ProjectPermissionController') ?>> url->link(t('Permissions'), 'ProjectPermissionController', 'index', array('project_id' => $project['id'])) ?> diff --git a/app/Template/project_tag/create.php b/app/Template/project_tag/create.php new file mode 100644 index 00000000..bfd1084a --- /dev/null +++ b/app/Template/project_tag/create.php @@ -0,0 +1,16 @@ + +
    + form->csrf() ?> + form->hidden('project_id', $values) ?> + + form->label(t('Name'), 'name') ?> + form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="255"')) ?> + +
    + + + url->link(t('cancel'), 'ProjectTagController', 'index', array('project_id' => $project['id']), false, 'close-popover') ?> +
    +
    diff --git a/app/Template/project_tag/edit.php b/app/Template/project_tag/edit.php new file mode 100644 index 00000000..9bf261bd --- /dev/null +++ b/app/Template/project_tag/edit.php @@ -0,0 +1,17 @@ + +
    + form->csrf() ?> + form->hidden('id', $values) ?> + form->hidden('project_id', $values) ?> + + form->label(t('Name'), 'name') ?> + form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="255"')) ?> + +
    + + + url->link(t('cancel'), 'ProjectTagController', 'index', array(), false, 'close-popover') ?> +
    +
    diff --git a/app/Template/project_tag/index.php b/app/Template/project_tag/index.php new file mode 100644 index 00000000..8e8dd96c --- /dev/null +++ b/app/Template/project_tag/index.php @@ -0,0 +1,31 @@ + + + +

    + + + + + + + + + + + + +
    text->e($tag['name']) ?> + + url->link(t('Remove'), 'ProjectTagController', 'confirm', array('tag_id' => $tag['id'], 'project_id' => $project['id']), false, 'popover') ?> + + url->link(t('Edit'), 'ProjectTagController', 'edit', array('tag_id' => $tag['id'], 'project_id' => $project['id']), false, 'popover') ?> +
    + diff --git a/app/Template/project_tag/remove.php b/app/Template/project_tag/remove.php new file mode 100644 index 00000000..f4aadab1 --- /dev/null +++ b/app/Template/project_tag/remove.php @@ -0,0 +1,15 @@ + + +
    +

    + +

    + +
    + url->link(t('Yes'), 'ProjectTagController', 'remove', array('tag_id' => $tag['id'], 'project_id' => $project['id']), true, 'btn btn-red popover-link') ?> + + url->link(t('cancel'), 'ProjectTagController', 'index', array('project_id' => $project['id']), false, 'close-popover') ?> +
    +
    diff --git a/app/Template/tag/create.php b/app/Template/tag/create.php new file mode 100644 index 00000000..9b32bc46 --- /dev/null +++ b/app/Template/tag/create.php @@ -0,0 +1,16 @@ + +
    + form->csrf() ?> + form->hidden('project_id', $values) ?> + + form->label(t('Name'), 'name') ?> + form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="255"')) ?> + +
    + + + url->link(t('cancel'), 'TagController', 'index', array(), false, 'close-popover') ?> +
    +
    diff --git a/app/Template/tag/edit.php b/app/Template/tag/edit.php new file mode 100644 index 00000000..f751ff49 --- /dev/null +++ b/app/Template/tag/edit.php @@ -0,0 +1,17 @@ + +
    + form->csrf() ?> + form->hidden('id', $values) ?> + form->hidden('project_id', $values) ?> + + form->label(t('Name'), 'name') ?> + form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="255"')) ?> + +
    + + + url->link(t('cancel'), 'TagController', 'index', array(), false, 'close-popover') ?> +
    +
    diff --git a/app/Template/tag/index.php b/app/Template/tag/index.php new file mode 100644 index 00000000..2a495eb3 --- /dev/null +++ b/app/Template/tag/index.php @@ -0,0 +1,31 @@ + + + +

    + + + + + + + + + + + + +
    text->e($tag['name']) ?> + + url->link(t('Remove'), 'TagController', 'confirm', array('tag_id' => $tag['id']), false, 'popover') ?> + + url->link(t('Edit'), 'TagController', 'edit', array('tag_id' => $tag['id']), false, 'popover') ?> +
    + diff --git a/app/Template/tag/remove.php b/app/Template/tag/remove.php new file mode 100644 index 00000000..46ea3f99 --- /dev/null +++ b/app/Template/tag/remove.php @@ -0,0 +1,15 @@ + + +
    +

    + +

    + +
    + url->link(t('Yes'), 'TagController', 'remove', array('tag_id' => $tag['id']), true, 'btn btn-red popover-link') ?> + + url->link(t('cancel'), 'TagController', 'index', array(), false, 'close-popover') ?> +
    +
    diff --git a/app/Validator/TagValidator.php b/app/Validator/TagValidator.php new file mode 100644 index 00000000..32622583 --- /dev/null +++ b/app/Validator/TagValidator.php @@ -0,0 +1,77 @@ +commonValidationRules()); + $result = $v->execute(); + $errors = $v->getErrors(); + + if ($result && $this->tagModel->exists($values['project_id'], $values['name'])) { + $result = false; + $errors = array('name' => array(t('The name must be unique'))); + } + + return array($result, $errors); + } + + /** + * Validate modification + * + * @access public + * @param array $values Form values + * @return array $valid, $errors [0] = Success or not, [1] = List of errors + */ + public function validateModification(array $values) + { + $rules = array( + new Validators\Required('id', t('Field required')), + ); + + $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); + $result = $v->execute(); + $errors = $v->getErrors(); + + if ($result && $this->tagModel->exists($values['project_id'], $values['name'], $values['id'])) { + $result = false; + $errors = array('name' => array(t('The name must be unique'))); + } + + return array($result, $errors); + } + + /** + * Common validation rules + * + * @access protected + * @return array + */ + protected function commonValidationRules() + { + return array( + new Validators\Required('project_id', t('Field required')), + new Validators\Required('name', t('Field required')), + new Validators\MaxLength('name', t('The maximum length is %d characters', 255), 255), + ); + } +} -- cgit v1.2.3 From 4a230d331ec220fc32a48525afb308af0d9787fa Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 26 Jun 2016 10:25:13 -0400 Subject: Added application and project roles validation for API procedure calls --- ChangeLog | 4 + app/Api/ActionApi.php | 87 ---- app/Api/AppApi.php | 49 -- app/Api/Authorization/ActionAuthorization.php | 19 + app/Api/Authorization/CategoryAuthorization.php | 19 + app/Api/Authorization/ColumnAuthorization.php | 19 + app/Api/Authorization/CommentAuthorization.php | 19 + app/Api/Authorization/ProcedureAuthorization.php | 32 ++ app/Api/Authorization/ProjectAuthorization.php | 35 ++ app/Api/Authorization/SubtaskAuthorization.php | 19 + app/Api/Authorization/TaskAuthorization.php | 19 + app/Api/Authorization/TaskFileAuthorization.php | 19 + app/Api/Authorization/TaskLinkAuthorization.php | 19 + app/Api/Authorization/UserAuthorization.php | 22 + app/Api/BaseApi.php | 85 ---- app/Api/BoardApi.php | 24 - app/Api/CategoryApi.php | 51 -- app/Api/ColumnApi.php | 42 -- app/Api/CommentApi.php | 54 --- app/Api/GroupApi.php | 51 -- app/Api/GroupMemberApi.php | 39 -- app/Api/LinkApi.php | 113 ----- app/Api/MeApi.php | 72 --- app/Api/Middleware/AuthenticationApiMiddleware.php | 137 ------ app/Api/Middleware/AuthenticationMiddleware.php | 82 ++++ app/Api/Procedure/ActionProcedure.php | 91 ++++ app/Api/Procedure/AppProcedure.php | 47 ++ app/Api/Procedure/BaseProcedure.php | 86 ++++ app/Api/Procedure/BoardProcedure.php | 25 + app/Api/Procedure/CategoryProcedure.php | 59 +++ app/Api/Procedure/ColumnProcedure.php | 51 ++ app/Api/Procedure/CommentProcedure.php | 62 +++ app/Api/Procedure/GroupMemberProcedure.php | 37 ++ app/Api/Procedure/GroupProcedure.php | 49 ++ app/Api/Procedure/LinkProcedure.php | 111 +++++ app/Api/Procedure/MeProcedure.php | 72 +++ app/Api/Procedure/ProjectPermissionProcedure.php | 69 +++ app/Api/Procedure/ProjectProcedure.php | 106 +++++ app/Api/Procedure/SubtaskProcedure.php | 74 +++ app/Api/Procedure/SubtaskTimeTrackingProcedure.php | 39 ++ app/Api/Procedure/SwimlaneProcedure.php | 91 ++++ app/Api/Procedure/TaskFileProcedure.php | 70 +++ app/Api/Procedure/TaskLinkProcedure.php | 85 ++++ app/Api/Procedure/TaskProcedure.php | 167 +++++++ app/Api/Procedure/UserProcedure.php | 131 +++++ app/Api/ProjectApi.php | 87 ---- app/Api/ProjectPermissionApi.php | 55 --- app/Api/SubtaskApi.php | 66 --- app/Api/SubtaskTimeTrackingApi.php | 34 -- app/Api/SwimlaneApi.php | 80 ---- app/Api/TaskApi.php | 163 ------- app/Api/TaskFileApi.php | 59 --- app/Api/TaskLinkApi.php | 79 --- app/Api/UserApi.php | 131 ----- app/Core/Base.php | 4 + app/Model/ActionModel.php | 12 + app/Model/CategoryModel.php | 12 + app/Model/ColumnModel.php | 12 + app/Model/CommentModel.php | 16 + app/Model/SubtaskModel.php | 16 + app/Model/TaskFileModel.php | 16 + app/Model/TaskLinkModel.php | 16 + app/ServiceProvider/ApiProvider.php | 83 ++-- app/ServiceProvider/AuthenticationProvider.php | 57 +++ composer.json | 2 +- composer.lock | 251 ++++++++-- doc/api-authentication.markdown | 55 +-- doc/api-json-rpc.markdown | 12 +- doc/api-project-permission-procedures.markdown | 33 ++ doc/api-project-procedures.markdown | 4 + tests/integration/ActionProcedureTest.php | 66 +++ tests/integration/ActionTest.php | 66 --- tests/integration/AppProcedureTest.php | 54 +++ tests/integration/AppTest.php | 54 --- tests/integration/BaseIntegrationTest.php | 122 ----- tests/integration/BaseProcedureTest.php | 122 +++++ tests/integration/BoardProcedureTest.php | 25 + tests/integration/BoardTest.php | 25 - tests/integration/CategoryProcedureTest.php | 76 +++ tests/integration/CategoryTest.php | 76 --- tests/integration/ColumnProcedureTest.php | 69 +++ tests/integration/ColumnTest.php | 69 --- tests/integration/CommentProcedureTest.php | 63 +++ tests/integration/CommentTest.php | 63 --- tests/integration/GroupMemberProcedureTest.php | 53 +++ tests/integration/GroupMemberTest.php | 53 --- tests/integration/GroupProcedureTest.php | 50 ++ tests/integration/GroupTest.php | 50 -- tests/integration/LinkProcedureTest.php | 70 +++ tests/integration/LinkTest.php | 70 --- tests/integration/MeProcedureTest.php | 68 +++ tests/integration/MeTest.php | 73 --- tests/integration/OverdueTaskProcedureTest.php | 43 ++ tests/integration/OverdueTaskTest.php | 43 -- tests/integration/ProcedureAuthorizationTest.php | 306 ++++++++++++ .../integration/ProjectPermissionProcedureTest.php | 89 ++++ tests/integration/ProjectPermissionTest.php | 89 ---- tests/integration/ProjectProcedureTest.php | 89 ++++ tests/integration/ProjectTest.php | 89 ---- tests/integration/SubtaskProcedureTest.php | 64 +++ tests/integration/SubtaskTest.php | 64 --- tests/integration/SwimlaneProcedureTest.php | 93 ++++ tests/integration/SwimlaneTest.php | 93 ---- tests/integration/TaskFileProcedureTest.php | 67 +++ tests/integration/TaskFileTest.php | 67 --- tests/integration/TaskLinkProcedureTest.php | 68 +++ tests/integration/TaskLinkTest.php | 68 --- tests/integration/TaskProcedureTest.php | 55 +++ tests/integration/TaskTest.php | 55 --- tests/integration/UserProcedureTest.php | 63 +++ tests/integration/UserTest.php | 63 --- tests/units/Model/ActionModelTest.php | 527 +++++++++++++++++++++ tests/units/Model/ActionTest.php | 509 -------------------- tests/units/Model/CategoryModelTest.php | 229 +++++++++ tests/units/Model/CategoryTest.php | 217 --------- tests/units/Model/CommentTest.php | 86 ++-- tests/units/Model/SubtaskModelTest.php | 400 ++++++++++++++++ tests/units/Model/SubtaskTest.php | 388 --------------- tests/units/Model/TaskFileModelTest.php | 458 ++++++++++++++++++ tests/units/Model/TaskFileTest.php | 445 ----------------- tests/units/Model/TaskLinkModelTest.php | 211 +++++++++ tests/units/Model/TaskLinkTest.php | 196 -------- 122 files changed, 5845 insertions(+), 4834 deletions(-) delete mode 100644 app/Api/ActionApi.php delete mode 100644 app/Api/AppApi.php create mode 100644 app/Api/Authorization/ActionAuthorization.php create mode 100644 app/Api/Authorization/CategoryAuthorization.php create mode 100644 app/Api/Authorization/ColumnAuthorization.php create mode 100644 app/Api/Authorization/CommentAuthorization.php create mode 100644 app/Api/Authorization/ProcedureAuthorization.php create mode 100644 app/Api/Authorization/ProjectAuthorization.php create mode 100644 app/Api/Authorization/SubtaskAuthorization.php create mode 100644 app/Api/Authorization/TaskAuthorization.php create mode 100644 app/Api/Authorization/TaskFileAuthorization.php create mode 100644 app/Api/Authorization/TaskLinkAuthorization.php create mode 100644 app/Api/Authorization/UserAuthorization.php delete mode 100644 app/Api/BaseApi.php delete mode 100644 app/Api/BoardApi.php delete mode 100644 app/Api/CategoryApi.php delete mode 100644 app/Api/ColumnApi.php delete mode 100644 app/Api/CommentApi.php delete mode 100644 app/Api/GroupApi.php delete mode 100644 app/Api/GroupMemberApi.php delete mode 100644 app/Api/LinkApi.php delete mode 100644 app/Api/MeApi.php delete mode 100644 app/Api/Middleware/AuthenticationApiMiddleware.php create mode 100644 app/Api/Middleware/AuthenticationMiddleware.php create mode 100644 app/Api/Procedure/ActionProcedure.php create mode 100644 app/Api/Procedure/AppProcedure.php create mode 100644 app/Api/Procedure/BaseProcedure.php create mode 100644 app/Api/Procedure/BoardProcedure.php create mode 100644 app/Api/Procedure/CategoryProcedure.php create mode 100644 app/Api/Procedure/ColumnProcedure.php create mode 100644 app/Api/Procedure/CommentProcedure.php create mode 100644 app/Api/Procedure/GroupMemberProcedure.php create mode 100644 app/Api/Procedure/GroupProcedure.php create mode 100644 app/Api/Procedure/LinkProcedure.php create mode 100644 app/Api/Procedure/MeProcedure.php create mode 100644 app/Api/Procedure/ProjectPermissionProcedure.php create mode 100644 app/Api/Procedure/ProjectProcedure.php create mode 100644 app/Api/Procedure/SubtaskProcedure.php create mode 100644 app/Api/Procedure/SubtaskTimeTrackingProcedure.php create mode 100644 app/Api/Procedure/SwimlaneProcedure.php create mode 100644 app/Api/Procedure/TaskFileProcedure.php create mode 100644 app/Api/Procedure/TaskLinkProcedure.php create mode 100644 app/Api/Procedure/TaskProcedure.php create mode 100644 app/Api/Procedure/UserProcedure.php delete mode 100644 app/Api/ProjectApi.php delete mode 100644 app/Api/ProjectPermissionApi.php delete mode 100644 app/Api/SubtaskApi.php delete mode 100644 app/Api/SubtaskTimeTrackingApi.php delete mode 100644 app/Api/SwimlaneApi.php delete mode 100644 app/Api/TaskApi.php delete mode 100644 app/Api/TaskFileApi.php delete mode 100644 app/Api/TaskLinkApi.php delete mode 100644 app/Api/UserApi.php create mode 100644 tests/integration/ActionProcedureTest.php delete mode 100644 tests/integration/ActionTest.php create mode 100644 tests/integration/AppProcedureTest.php delete mode 100644 tests/integration/AppTest.php delete mode 100644 tests/integration/BaseIntegrationTest.php create mode 100644 tests/integration/BaseProcedureTest.php create mode 100644 tests/integration/BoardProcedureTest.php delete mode 100644 tests/integration/BoardTest.php create mode 100644 tests/integration/CategoryProcedureTest.php delete mode 100644 tests/integration/CategoryTest.php create mode 100644 tests/integration/ColumnProcedureTest.php delete mode 100644 tests/integration/ColumnTest.php create mode 100644 tests/integration/CommentProcedureTest.php delete mode 100644 tests/integration/CommentTest.php create mode 100644 tests/integration/GroupMemberProcedureTest.php delete mode 100644 tests/integration/GroupMemberTest.php create mode 100644 tests/integration/GroupProcedureTest.php delete mode 100644 tests/integration/GroupTest.php create mode 100644 tests/integration/LinkProcedureTest.php delete mode 100644 tests/integration/LinkTest.php create mode 100644 tests/integration/MeProcedureTest.php delete mode 100644 tests/integration/MeTest.php create mode 100644 tests/integration/OverdueTaskProcedureTest.php delete mode 100644 tests/integration/OverdueTaskTest.php create mode 100644 tests/integration/ProcedureAuthorizationTest.php create mode 100644 tests/integration/ProjectPermissionProcedureTest.php delete mode 100644 tests/integration/ProjectPermissionTest.php create mode 100644 tests/integration/ProjectProcedureTest.php delete mode 100644 tests/integration/ProjectTest.php create mode 100644 tests/integration/SubtaskProcedureTest.php delete mode 100644 tests/integration/SubtaskTest.php create mode 100644 tests/integration/SwimlaneProcedureTest.php delete mode 100644 tests/integration/SwimlaneTest.php create mode 100644 tests/integration/TaskFileProcedureTest.php delete mode 100644 tests/integration/TaskFileTest.php create mode 100644 tests/integration/TaskLinkProcedureTest.php delete mode 100644 tests/integration/TaskLinkTest.php create mode 100644 tests/integration/TaskProcedureTest.php delete mode 100644 tests/integration/TaskTest.php create mode 100644 tests/integration/UserProcedureTest.php delete mode 100644 tests/integration/UserTest.php create mode 100644 tests/units/Model/ActionModelTest.php delete mode 100644 tests/units/Model/ActionTest.php create mode 100644 tests/units/Model/CategoryModelTest.php delete mode 100644 tests/units/Model/CategoryTest.php create mode 100644 tests/units/Model/SubtaskModelTest.php delete mode 100644 tests/units/Model/SubtaskTest.php create mode 100644 tests/units/Model/TaskFileModelTest.php delete mode 100644 tests/units/Model/TaskFileTest.php create mode 100644 tests/units/Model/TaskLinkModelTest.php delete mode 100644 tests/units/Model/TaskLinkTest.php (limited to 'app/Core') diff --git a/ChangeLog b/ChangeLog index b86fea57..42af8ee3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ Version 1.0.31 (unreleased) -------------- +New features: + +* Added application and project roles validation for API procedure calls + Improvements: * Rewrite integration tests to run with Docker containers diff --git a/app/Api/ActionApi.php b/app/Api/ActionApi.php deleted file mode 100644 index 116742d8..00000000 --- a/app/Api/ActionApi.php +++ /dev/null @@ -1,87 +0,0 @@ -actionManager->getAvailableActions(); - } - - public function getAvailableActionEvents() - { - return $this->eventManager->getAll(); - } - - public function getCompatibleActionEvents($action_name) - { - return $this->actionManager->getCompatibleEvents($action_name); - } - - public function removeAction($action_id) - { - return $this->actionModel->remove($action_id); - } - - public function getActions($project_id) - { - return $this->actionModel->getAllByProject($project_id); - } - - public function createAction($project_id, $event_name, $action_name, array $params) - { - $values = array( - 'project_id' => $project_id, - 'event_name' => $event_name, - 'action_name' => $action_name, - 'params' => $params, - ); - - list($valid, ) = $this->actionValidator->validateCreation($values); - - if (! $valid) { - return false; - } - - // Check if the action exists - $actions = $this->actionManager->getAvailableActions(); - - if (! isset($actions[$action_name])) { - return false; - } - - // Check the event - $action = $this->actionManager->getAction($action_name); - - if (! in_array($event_name, $action->getEvents())) { - return false; - } - - $required_params = $action->getActionRequiredParameters(); - - // Check missing parameters - foreach ($required_params as $param => $value) { - if (! isset($params[$param])) { - return false; - } - } - - // Check extra parameters - foreach ($params as $param => $value) { - if (! isset($required_params[$param])) { - return false; - } - } - - return $this->actionModel->create($values); - } -} diff --git a/app/Api/AppApi.php b/app/Api/AppApi.php deleted file mode 100644 index 637de5c5..00000000 --- a/app/Api/AppApi.php +++ /dev/null @@ -1,49 +0,0 @@ -timezoneModel->getCurrentTimezone(); - } - - public function getVersion() - { - return APP_VERSION; - } - - public function getDefaultTaskColor() - { - return $this->colorModel->getDefaultColor(); - } - - public function getDefaultTaskColors() - { - return $this->colorModel->getDefaultColors(); - } - - public function getColorList() - { - return $this->colorModel->getList(); - } - - public function getApplicationRoles() - { - return $this->role->getApplicationRoles(); - } - - public function getProjectRoles() - { - return $this->role->getProjectRoles(); - } -} diff --git a/app/Api/Authorization/ActionAuthorization.php b/app/Api/Authorization/ActionAuthorization.php new file mode 100644 index 00000000..4b41ad82 --- /dev/null +++ b/app/Api/Authorization/ActionAuthorization.php @@ -0,0 +1,19 @@ +userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->actionModel->getProjectId($action_id)); + } + } +} diff --git a/app/Api/Authorization/CategoryAuthorization.php b/app/Api/Authorization/CategoryAuthorization.php new file mode 100644 index 00000000..f17265a2 --- /dev/null +++ b/app/Api/Authorization/CategoryAuthorization.php @@ -0,0 +1,19 @@ +userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->categoryModel->getProjectId($category_id)); + } + } +} diff --git a/app/Api/Authorization/ColumnAuthorization.php b/app/Api/Authorization/ColumnAuthorization.php new file mode 100644 index 00000000..37aecda2 --- /dev/null +++ b/app/Api/Authorization/ColumnAuthorization.php @@ -0,0 +1,19 @@ +userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->columnModel->getProjectId($column_id)); + } + } +} diff --git a/app/Api/Authorization/CommentAuthorization.php b/app/Api/Authorization/CommentAuthorization.php new file mode 100644 index 00000000..ed15512e --- /dev/null +++ b/app/Api/Authorization/CommentAuthorization.php @@ -0,0 +1,19 @@ +userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->commentModel->getProjectId($comment_id)); + } + } +} diff --git a/app/Api/Authorization/ProcedureAuthorization.php b/app/Api/Authorization/ProcedureAuthorization.php new file mode 100644 index 00000000..070a6371 --- /dev/null +++ b/app/Api/Authorization/ProcedureAuthorization.php @@ -0,0 +1,32 @@ +userSession->isLogged() && in_array($procedure, $this->userSpecificProcedures)) { + throw new AccessDeniedException('This procedure is not available with the API credentials'); + } + } +} diff --git a/app/Api/Authorization/ProjectAuthorization.php b/app/Api/Authorization/ProjectAuthorization.php new file mode 100644 index 00000000..21ecf311 --- /dev/null +++ b/app/Api/Authorization/ProjectAuthorization.php @@ -0,0 +1,35 @@ +userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $project_id); + } + } + + protected function checkProjectPermission($class, $method, $project_id) + { + if (empty($project_id)) { + throw new AccessDeniedException('Project not found'); + } + + $role = $this->projectUserRoleModel->getUserRole($project_id, $this->userSession->getId()); + + if (! $this->apiProjectAuthorization->isAllowed($class, $method, $role)) { + throw new AccessDeniedException('Project access denied'); + } + } +} diff --git a/app/Api/Authorization/SubtaskAuthorization.php b/app/Api/Authorization/SubtaskAuthorization.php new file mode 100644 index 00000000..fcb57929 --- /dev/null +++ b/app/Api/Authorization/SubtaskAuthorization.php @@ -0,0 +1,19 @@ +userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->subtaskModel->getProjectId($subtask_id)); + } + } +} diff --git a/app/Api/Authorization/TaskAuthorization.php b/app/Api/Authorization/TaskAuthorization.php new file mode 100644 index 00000000..db93b76b --- /dev/null +++ b/app/Api/Authorization/TaskAuthorization.php @@ -0,0 +1,19 @@ +userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->taskFinderModel->getProjectId($category_id)); + } + } +} diff --git a/app/Api/Authorization/TaskFileAuthorization.php b/app/Api/Authorization/TaskFileAuthorization.php new file mode 100644 index 00000000..e40783eb --- /dev/null +++ b/app/Api/Authorization/TaskFileAuthorization.php @@ -0,0 +1,19 @@ +userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->taskFileModel->getProjectId($file_id)); + } + } +} diff --git a/app/Api/Authorization/TaskLinkAuthorization.php b/app/Api/Authorization/TaskLinkAuthorization.php new file mode 100644 index 00000000..2f5fc8d5 --- /dev/null +++ b/app/Api/Authorization/TaskLinkAuthorization.php @@ -0,0 +1,19 @@ +userSession->isLogged()) { + $this->checkProjectPermission($class, $method, $this->taskLinkModel->getProjectId($task_link_id)); + } + } +} diff --git a/app/Api/Authorization/UserAuthorization.php b/app/Api/Authorization/UserAuthorization.php new file mode 100644 index 00000000..3fd6865c --- /dev/null +++ b/app/Api/Authorization/UserAuthorization.php @@ -0,0 +1,22 @@ +userSession->isLogged() && ! $this->apiAuthorization->isAllowed($class, $method, $this->userSession->getRole())) { + throw new AccessDeniedException('You are not allowed to access to this resource'); + } + } +} diff --git a/app/Api/BaseApi.php b/app/Api/BaseApi.php deleted file mode 100644 index 8f18802c..00000000 --- a/app/Api/BaseApi.php +++ /dev/null @@ -1,85 +0,0 @@ -userSession->isLogged() && ! $this->projectPermissionModel->isUserAllowed($project_id, $this->userSession->getId())) { - throw new AccessDeniedException('Permission denied'); - } - } - - public function checkTaskPermission($task_id) - { - if ($this->userSession->isLogged()) { - $this->checkProjectPermission($this->taskFinderModel->getProjectId($task_id)); - } - } - - protected function formatTask($task) - { - if (! empty($task)) { - $task['url'] = $this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), '', true); - $task['color'] = $this->colorModel->getColorProperties($task['color_id']); - } - - return $task; - } - - protected function formatTasks($tasks) - { - if (! empty($tasks)) { - foreach ($tasks as &$task) { - $task = $this->formatTask($task); - } - } - - return $tasks; - } - - protected function formatProject($project) - { - if (! empty($project)) { - $project['url'] = array( - 'board' => $this->helper->url->to('BoardViewController', 'show', array('project_id' => $project['id']), '', true), - 'calendar' => $this->helper->url->to('CalendarController', 'show', array('project_id' => $project['id']), '', true), - 'list' => $this->helper->url->to('TaskListController', 'show', array('project_id' => $project['id']), '', true), - ); - } - - return $project; - } - - protected function formatProjects($projects) - { - if (! empty($projects)) { - foreach ($projects as &$project) { - $project = $this->formatProject($project); - } - } - - return $projects; - } - - protected function filterValues(array $values) - { - foreach ($values as $key => $value) { - if (is_null($value)) { - unset($values[$key]); - } - } - - return $values; - } -} diff --git a/app/Api/BoardApi.php b/app/Api/BoardApi.php deleted file mode 100644 index 70f21c0e..00000000 --- a/app/Api/BoardApi.php +++ /dev/null @@ -1,24 +0,0 @@ -checkProjectPermission($project_id); - - return BoardFormatter::getInstance($this->container) - ->withProjectId($project_id) - ->withQuery($this->taskFinderModel->getExtendedQuery()) - ->format(); - } -} diff --git a/app/Api/CategoryApi.php b/app/Api/CategoryApi.php deleted file mode 100644 index c56cfb35..00000000 --- a/app/Api/CategoryApi.php +++ /dev/null @@ -1,51 +0,0 @@ -categoryModel->getById($category_id); - } - - public function getAllCategories($project_id) - { - return $this->categoryModel->getAll($project_id); - } - - public function removeCategory($category_id) - { - return $this->categoryModel->remove($category_id); - } - - public function createCategory($project_id, $name) - { - $values = array( - 'project_id' => $project_id, - 'name' => $name, - ); - - list($valid, ) = $this->categoryValidator->validateCreation($values); - return $valid ? $this->categoryModel->create($values) : false; - } - - public function updateCategory($id, $name) - { - $values = array( - 'id' => $id, - 'name' => $name, - ); - - list($valid, ) = $this->categoryValidator->validateModification($values); - return $valid && $this->categoryModel->update($values); - } -} diff --git a/app/Api/ColumnApi.php b/app/Api/ColumnApi.php deleted file mode 100644 index aa4026f6..00000000 --- a/app/Api/ColumnApi.php +++ /dev/null @@ -1,42 +0,0 @@ -columnModel->getAll($project_id); - } - - public function getColumn($column_id) - { - return $this->columnModel->getById($column_id); - } - - public function updateColumn($column_id, $title, $task_limit = 0, $description = '') - { - return $this->columnModel->update($column_id, $title, $task_limit, $description); - } - - public function addColumn($project_id, $title, $task_limit = 0, $description = '') - { - return $this->columnModel->create($project_id, $title, $task_limit, $description); - } - - public function removeColumn($column_id) - { - return $this->columnModel->remove($column_id); - } - - public function changeColumnPosition($project_id, $column_id, $position) - { - return $this->columnModel->changePosition($project_id, $column_id, $position); - } -} diff --git a/app/Api/CommentApi.php b/app/Api/CommentApi.php deleted file mode 100644 index 8358efee..00000000 --- a/app/Api/CommentApi.php +++ /dev/null @@ -1,54 +0,0 @@ -commentModel->getById($comment_id); - } - - public function getAllComments($task_id) - { - return $this->commentModel->getAll($task_id); - } - - public function removeComment($comment_id) - { - return $this->commentModel->remove($comment_id); - } - - public function createComment($task_id, $user_id, $content, $reference = '') - { - $values = array( - 'task_id' => $task_id, - 'user_id' => $user_id, - 'comment' => $content, - 'reference' => $reference, - ); - - list($valid, ) = $this->commentValidator->validateCreation($values); - - return $valid ? $this->commentModel->create($values) : false; - } - - public function updateComment($id, $content) - { - $values = array( - 'id' => $id, - 'comment' => $content, - ); - - list($valid, ) = $this->commentValidator->validateModification($values); - return $valid && $this->commentModel->update($values); - } -} diff --git a/app/Api/GroupApi.php b/app/Api/GroupApi.php deleted file mode 100644 index 1701edc3..00000000 --- a/app/Api/GroupApi.php +++ /dev/null @@ -1,51 +0,0 @@ -groupModel->create($name, $external_id); - } - - public function updateGroup($group_id, $name = null, $external_id = null) - { - $values = array( - 'id' => $group_id, - 'name' => $name, - 'external_id' => $external_id, - ); - - foreach ($values as $key => $value) { - if (is_null($value)) { - unset($values[$key]); - } - } - - return $this->groupModel->update($values); - } - - public function removeGroup($group_id) - { - return $this->groupModel->remove($group_id); - } - - public function getGroup($group_id) - { - return $this->groupModel->getById($group_id); - } - - public function getAllGroups() - { - return $this->groupModel->getAll(); - } -} diff --git a/app/Api/GroupMemberApi.php b/app/Api/GroupMemberApi.php deleted file mode 100644 index e09f6975..00000000 --- a/app/Api/GroupMemberApi.php +++ /dev/null @@ -1,39 +0,0 @@ -groupMemberModel->getGroups($user_id); - } - - public function getGroupMembers($group_id) - { - return $this->groupMemberModel->getMembers($group_id); - } - - public function addGroupMember($group_id, $user_id) - { - return $this->groupMemberModel->addUser($group_id, $user_id); - } - - public function removeGroupMember($group_id, $user_id) - { - return $this->groupMemberModel->removeUser($group_id, $user_id); - } - - public function isGroupMember($group_id, $user_id) - { - return $this->groupMemberModel->isMember($group_id, $user_id); - } -} diff --git a/app/Api/LinkApi.php b/app/Api/LinkApi.php deleted file mode 100644 index d8e525e4..00000000 --- a/app/Api/LinkApi.php +++ /dev/null @@ -1,113 +0,0 @@ -linkModel->getById($link_id); - } - - /** - * Get a link by name - * - * @access public - * @param string $label - * @return array - */ - public function getLinkByLabel($label) - { - return $this->linkModel->getByLabel($label); - } - - /** - * Get the opposite link id - * - * @access public - * @param integer $link_id Link id - * @return integer - */ - public function getOppositeLinkId($link_id) - { - return $this->linkModel->getOppositeLinkId($link_id); - } - - /** - * Get all links - * - * @access public - * @return array - */ - public function getAllLinks() - { - return $this->linkModel->getAll(); - } - - /** - * Create a new link label - * - * @access public - * @param string $label - * @param string $opposite_label - * @return boolean|integer - */ - public function createLink($label, $opposite_label = '') - { - $values = array( - 'label' => $label, - 'opposite_label' => $opposite_label, - ); - - list($valid, ) = $this->linkValidator->validateCreation($values); - return $valid ? $this->linkModel->create($label, $opposite_label) : false; - } - - /** - * Update a link - * - * @access public - * @param integer $link_id - * @param integer $opposite_link_id - * @param string $label - * @return boolean - */ - public function updateLink($link_id, $opposite_link_id, $label) - { - $values = array( - 'id' => $link_id, - 'opposite_id' => $opposite_link_id, - 'label' => $label, - ); - - list($valid, ) = $this->linkValidator->validateModification($values); - return $valid && $this->linkModel->update($values); - } - - /** - * Remove a link a the relation to its opposite - * - * @access public - * @param integer $link_id - * @return boolean - */ - public function removeLink($link_id) - { - return $this->linkModel->remove($link_id); - } -} diff --git a/app/Api/MeApi.php b/app/Api/MeApi.php deleted file mode 100644 index 497749b6..00000000 --- a/app/Api/MeApi.php +++ /dev/null @@ -1,72 +0,0 @@ -sessionStorage->user; - } - - public function getMyDashboard() - { - $user_id = $this->userSession->getId(); - $projects = $this->projectModel->getQueryColumnStats($this->projectPermissionModel->getActiveProjectIds($user_id))->findAll(); - $tasks = $this->taskFinderModel->getUserQuery($user_id)->findAll(); - - return array( - 'projects' => $this->formatProjects($projects), - 'tasks' => $this->formatTasks($tasks), - 'subtasks' => $this->subtaskModel->getUserQuery($user_id, array(SubtaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS))->findAll(), - ); - } - - public function getMyActivityStream() - { - $project_ids = $this->projectPermissionModel->getActiveProjectIds($this->userSession->getId()); - return $this->helper->projectActivity->getProjectsEvents($project_ids, 100); - } - - public function createMyPrivateProject($name, $description = null) - { - if ($this->configModel->get('disable_private_project', 0) == 1) { - return false; - } - - $values = array( - 'name' => $name, - 'description' => $description, - 'is_private' => 1, - ); - - list($valid, ) = $this->projectValidator->validateCreation($values); - return $valid ? $this->projectModel->create($values, $this->userSession->getId(), true) : false; - } - - public function getMyProjectsList() - { - return $this->projectUserRoleModel->getProjectsByUser($this->userSession->getId()); - } - - public function getMyOverdueTasks() - { - return $this->taskFinderModel->getOverdueTasksByUser($this->userSession->getId()); - } - - public function getMyProjects() - { - $project_ids = $this->projectPermissionModel->getActiveProjectIds($this->userSession->getId()); - $projects = $this->projectModel->getAllByIds($project_ids); - - return $this->formatProjects($projects); - } -} diff --git a/app/Api/Middleware/AuthenticationApiMiddleware.php b/app/Api/Middleware/AuthenticationApiMiddleware.php deleted file mode 100644 index b16e10b8..00000000 --- a/app/Api/Middleware/AuthenticationApiMiddleware.php +++ /dev/null @@ -1,137 +0,0 @@ -dispatcher->dispatch('app.bootstrap'); - - if ($this->isUserAuthenticated($username, $password)) { - $this->checkProcedurePermission(true, $procedureName); - $this->userSession->initialize($this->userModel->getByUsername($username)); - } elseif ($this->isAppAuthenticated($username, $password)) { - $this->checkProcedurePermission(false, $procedureName); - } else { - $this->logger->error('API authentication failure for '.$username); - throw new AuthenticationFailureException('Wrong credentials'); - } - } - - /** - * Check user credentials - * - * @access public - * @param string $username - * @param string $password - * @return boolean - */ - private function isUserAuthenticated($username, $password) - { - return $username !== 'jsonrpc' && - ! $this->userLockingModel->isLocked($username) && - $this->authenticationManager->passwordAuthentication($username, $password); - } - - /** - * Check administrative credentials - * - * @access public - * @param string $username - * @param string $password - * @return boolean - */ - private function isAppAuthenticated($username, $password) - { - return $username === 'jsonrpc' && $password === $this->getApiToken(); - } - - /** - * Get API Token - * - * @access private - * @return string - */ - private function getApiToken() - { - if (defined('API_AUTHENTICATION_TOKEN')) { - return API_AUTHENTICATION_TOKEN; - } - - return $this->configModel->get('api_token'); - } - - public function checkProcedurePermission($is_user, $procedure) - { - $is_both_procedure = in_array($procedure, $this->both_allowed_procedures); - $is_user_procedure = in_array($procedure, $this->user_allowed_procedures); - - if ($is_user && ! $is_both_procedure && ! $is_user_procedure) { - throw new AccessDeniedException('Permission denied'); - } elseif (! $is_user && ! $is_both_procedure && $is_user_procedure) { - throw new AccessDeniedException('Permission denied'); - } - - $this->logger->debug('API call: '.$procedure); - } -} diff --git a/app/Api/Middleware/AuthenticationMiddleware.php b/app/Api/Middleware/AuthenticationMiddleware.php new file mode 100644 index 00000000..8e309593 --- /dev/null +++ b/app/Api/Middleware/AuthenticationMiddleware.php @@ -0,0 +1,82 @@ +dispatcher->dispatch('app.bootstrap'); + + if ($this->isUserAuthenticated($username, $password)) { + $this->userSession->initialize($this->userModel->getByUsername($username)); + } elseif (! $this->isAppAuthenticated($username, $password)) { + $this->logger->error('API authentication failure for '.$username); + throw new AuthenticationFailureException('Wrong credentials'); + } + } + + /** + * Check user credentials + * + * @access public + * @param string $username + * @param string $password + * @return boolean + */ + private function isUserAuthenticated($username, $password) + { + return $username !== 'jsonrpc' && + ! $this->userLockingModel->isLocked($username) && + $this->authenticationManager->passwordAuthentication($username, $password); + } + + /** + * Check administrative credentials + * + * @access public + * @param string $username + * @param string $password + * @return boolean + */ + private function isAppAuthenticated($username, $password) + { + return $username === 'jsonrpc' && $password === $this->getApiToken(); + } + + /** + * Get API Token + * + * @access private + * @return string + */ + private function getApiToken() + { + if (defined('API_AUTHENTICATION_TOKEN')) { + return API_AUTHENTICATION_TOKEN; + } + + return $this->configModel->get('api_token'); + } +} diff --git a/app/Api/Procedure/ActionProcedure.php b/app/Api/Procedure/ActionProcedure.php new file mode 100644 index 00000000..4043dbb9 --- /dev/null +++ b/app/Api/Procedure/ActionProcedure.php @@ -0,0 +1,91 @@ +actionManager->getAvailableActions(); + } + + public function getAvailableActionEvents() + { + return $this->eventManager->getAll(); + } + + public function getCompatibleActionEvents($action_name) + { + return $this->actionManager->getCompatibleEvents($action_name); + } + + public function removeAction($action_id) + { + ActionAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeAction', $action_id); + return $this->actionModel->remove($action_id); + } + + public function getActions($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getActions', $project_id); + return $this->actionModel->getAllByProject($project_id); + } + + public function createAction($project_id, $event_name, $action_name, array $params) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createAction', $project_id); + $values = array( + 'project_id' => $project_id, + 'event_name' => $event_name, + 'action_name' => $action_name, + 'params' => $params, + ); + + list($valid, ) = $this->actionValidator->validateCreation($values); + + if (! $valid) { + return false; + } + + // Check if the action exists + $actions = $this->actionManager->getAvailableActions(); + + if (! isset($actions[$action_name])) { + return false; + } + + // Check the event + $action = $this->actionManager->getAction($action_name); + + if (! in_array($event_name, $action->getEvents())) { + return false; + } + + $required_params = $action->getActionRequiredParameters(); + + // Check missing parameters + foreach ($required_params as $param => $value) { + if (! isset($params[$param])) { + return false; + } + } + + // Check extra parameters + foreach ($params as $param => $value) { + if (! isset($required_params[$param])) { + return false; + } + } + + return $this->actionModel->create($values); + } +} diff --git a/app/Api/Procedure/AppProcedure.php b/app/Api/Procedure/AppProcedure.php new file mode 100644 index 00000000..60af4a60 --- /dev/null +++ b/app/Api/Procedure/AppProcedure.php @@ -0,0 +1,47 @@ +timezoneModel->getCurrentTimezone(); + } + + public function getVersion() + { + return APP_VERSION; + } + + public function getDefaultTaskColor() + { + return $this->colorModel->getDefaultColor(); + } + + public function getDefaultTaskColors() + { + return $this->colorModel->getDefaultColors(); + } + + public function getColorList() + { + return $this->colorModel->getList(); + } + + public function getApplicationRoles() + { + return $this->role->getApplicationRoles(); + } + + public function getProjectRoles() + { + return $this->role->getProjectRoles(); + } +} diff --git a/app/Api/Procedure/BaseProcedure.php b/app/Api/Procedure/BaseProcedure.php new file mode 100644 index 00000000..0aa43428 --- /dev/null +++ b/app/Api/Procedure/BaseProcedure.php @@ -0,0 +1,86 @@ +container)->check($procedure); + UserAuthorization::getInstance($this->container)->check($this->getClassName(), $procedure); + } + + protected function formatTask($task) + { + if (! empty($task)) { + $task['url'] = $this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), '', true); + $task['color'] = $this->colorModel->getColorProperties($task['color_id']); + } + + return $task; + } + + protected function formatTasks($tasks) + { + if (! empty($tasks)) { + foreach ($tasks as &$task) { + $task = $this->formatTask($task); + } + } + + return $tasks; + } + + protected function formatProject($project) + { + if (! empty($project)) { + $project['url'] = array( + 'board' => $this->helper->url->to('BoardViewController', 'show', array('project_id' => $project['id']), '', true), + 'calendar' => $this->helper->url->to('CalendarController', 'show', array('project_id' => $project['id']), '', true), + 'list' => $this->helper->url->to('TaskListController', 'show', array('project_id' => $project['id']), '', true), + ); + } + + return $project; + } + + protected function formatProjects($projects) + { + if (! empty($projects)) { + foreach ($projects as &$project) { + $project = $this->formatProject($project); + } + } + + return $projects; + } + + protected function filterValues(array $values) + { + foreach ($values as $key => $value) { + if (is_null($value)) { + unset($values[$key]); + } + } + + return $values; + } + + protected function getClassName() + { + $reflection = new ReflectionClass(get_called_class()); + return $reflection->getShortName(); + } +} diff --git a/app/Api/Procedure/BoardProcedure.php b/app/Api/Procedure/BoardProcedure.php new file mode 100644 index 00000000..674b5466 --- /dev/null +++ b/app/Api/Procedure/BoardProcedure.php @@ -0,0 +1,25 @@ +container)->check($this->getClassName(), 'getBoard', $project_id); + + return BoardFormatter::getInstance($this->container) + ->withProjectId($project_id) + ->withQuery($this->taskFinderModel->getExtendedQuery()) + ->format(); + } +} diff --git a/app/Api/Procedure/CategoryProcedure.php b/app/Api/Procedure/CategoryProcedure.php new file mode 100644 index 00000000..3ebbd908 --- /dev/null +++ b/app/Api/Procedure/CategoryProcedure.php @@ -0,0 +1,59 @@ +container)->check($this->getClassName(), 'getCategory', $category_id); + return $this->categoryModel->getById($category_id); + } + + public function getAllCategories($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllCategories', $project_id); + return $this->categoryModel->getAll($project_id); + } + + public function removeCategory($category_id) + { + CategoryAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeCategory', $category_id); + return $this->categoryModel->remove($category_id); + } + + public function createCategory($project_id, $name) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createCategory', $project_id); + + $values = array( + 'project_id' => $project_id, + 'name' => $name, + ); + + list($valid, ) = $this->categoryValidator->validateCreation($values); + return $valid ? $this->categoryModel->create($values) : false; + } + + public function updateCategory($id, $name) + { + CategoryAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateCategory', $id); + + $values = array( + 'id' => $id, + 'name' => $name, + ); + + list($valid, ) = $this->categoryValidator->validateModification($values); + return $valid && $this->categoryModel->update($values); + } +} diff --git a/app/Api/Procedure/ColumnProcedure.php b/app/Api/Procedure/ColumnProcedure.php new file mode 100644 index 00000000..ab9d173b --- /dev/null +++ b/app/Api/Procedure/ColumnProcedure.php @@ -0,0 +1,51 @@ +container)->check($this->getClassName(), 'getColumns', $project_id); + return $this->columnModel->getAll($project_id); + } + + public function getColumn($column_id) + { + ColumnAuthorization::getInstance($this->container)->check($this->getClassName(), 'getColumn', $column_id); + return $this->columnModel->getById($column_id); + } + + public function updateColumn($column_id, $title, $task_limit = 0, $description = '') + { + ColumnAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateColumn', $column_id); + return $this->columnModel->update($column_id, $title, $task_limit, $description); + } + + public function addColumn($project_id, $title, $task_limit = 0, $description = '') + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addColumn', $project_id); + return $this->columnModel->create($project_id, $title, $task_limit, $description); + } + + public function removeColumn($column_id) + { + ColumnAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeColumn', $column_id); + return $this->columnModel->remove($column_id); + } + + public function changeColumnPosition($project_id, $column_id, $position) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeColumnPosition', $project_id); + return $this->columnModel->changePosition($project_id, $column_id, $position); + } +} diff --git a/app/Api/Procedure/CommentProcedure.php b/app/Api/Procedure/CommentProcedure.php new file mode 100644 index 00000000..019a49bb --- /dev/null +++ b/app/Api/Procedure/CommentProcedure.php @@ -0,0 +1,62 @@ +container)->check($this->getClassName(), 'getComment', $comment_id); + return $this->commentModel->getById($comment_id); + } + + public function getAllComments($task_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllComments', $task_id); + return $this->commentModel->getAll($task_id); + } + + public function removeComment($comment_id) + { + CommentAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeComment', $comment_id); + return $this->commentModel->remove($comment_id); + } + + public function createComment($task_id, $user_id, $content, $reference = '') + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createComment', $task_id); + + $values = array( + 'task_id' => $task_id, + 'user_id' => $user_id, + 'comment' => $content, + 'reference' => $reference, + ); + + list($valid, ) = $this->commentValidator->validateCreation($values); + + return $valid ? $this->commentModel->create($values) : false; + } + + public function updateComment($id, $content) + { + CommentAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateComment', $id); + + $values = array( + 'id' => $id, + 'comment' => $content, + ); + + list($valid, ) = $this->commentValidator->validateModification($values); + return $valid && $this->commentModel->update($values); + } +} diff --git a/app/Api/Procedure/GroupMemberProcedure.php b/app/Api/Procedure/GroupMemberProcedure.php new file mode 100644 index 00000000..081d6ac8 --- /dev/null +++ b/app/Api/Procedure/GroupMemberProcedure.php @@ -0,0 +1,37 @@ +groupMemberModel->getGroups($user_id); + } + + public function getGroupMembers($group_id) + { + return $this->groupMemberModel->getMembers($group_id); + } + + public function addGroupMember($group_id, $user_id) + { + return $this->groupMemberModel->addUser($group_id, $user_id); + } + + public function removeGroupMember($group_id, $user_id) + { + return $this->groupMemberModel->removeUser($group_id, $user_id); + } + + public function isGroupMember($group_id, $user_id) + { + return $this->groupMemberModel->isMember($group_id, $user_id); + } +} diff --git a/app/Api/Procedure/GroupProcedure.php b/app/Api/Procedure/GroupProcedure.php new file mode 100644 index 00000000..804940a2 --- /dev/null +++ b/app/Api/Procedure/GroupProcedure.php @@ -0,0 +1,49 @@ +groupModel->create($name, $external_id); + } + + public function updateGroup($group_id, $name = null, $external_id = null) + { + $values = array( + 'id' => $group_id, + 'name' => $name, + 'external_id' => $external_id, + ); + + foreach ($values as $key => $value) { + if (is_null($value)) { + unset($values[$key]); + } + } + + return $this->groupModel->update($values); + } + + public function removeGroup($group_id) + { + return $this->groupModel->remove($group_id); + } + + public function getGroup($group_id) + { + return $this->groupModel->getById($group_id); + } + + public function getAllGroups() + { + return $this->groupModel->getAll(); + } +} diff --git a/app/Api/Procedure/LinkProcedure.php b/app/Api/Procedure/LinkProcedure.php new file mode 100644 index 00000000..b4cecf3a --- /dev/null +++ b/app/Api/Procedure/LinkProcedure.php @@ -0,0 +1,111 @@ +linkModel->getById($link_id); + } + + /** + * Get a link by name + * + * @access public + * @param string $label + * @return array + */ + public function getLinkByLabel($label) + { + return $this->linkModel->getByLabel($label); + } + + /** + * Get the opposite link id + * + * @access public + * @param integer $link_id Link id + * @return integer + */ + public function getOppositeLinkId($link_id) + { + return $this->linkModel->getOppositeLinkId($link_id); + } + + /** + * Get all links + * + * @access public + * @return array + */ + public function getAllLinks() + { + return $this->linkModel->getAll(); + } + + /** + * Create a new link label + * + * @access public + * @param string $label + * @param string $opposite_label + * @return boolean|integer + */ + public function createLink($label, $opposite_label = '') + { + $values = array( + 'label' => $label, + 'opposite_label' => $opposite_label, + ); + + list($valid, ) = $this->linkValidator->validateCreation($values); + return $valid ? $this->linkModel->create($label, $opposite_label) : false; + } + + /** + * Update a link + * + * @access public + * @param integer $link_id + * @param integer $opposite_link_id + * @param string $label + * @return boolean + */ + public function updateLink($link_id, $opposite_link_id, $label) + { + $values = array( + 'id' => $link_id, + 'opposite_id' => $opposite_link_id, + 'label' => $label, + ); + + list($valid, ) = $this->linkValidator->validateModification($values); + return $valid && $this->linkModel->update($values); + } + + /** + * Remove a link a the relation to its opposite + * + * @access public + * @param integer $link_id + * @return boolean + */ + public function removeLink($link_id) + { + return $this->linkModel->remove($link_id); + } +} diff --git a/app/Api/Procedure/MeProcedure.php b/app/Api/Procedure/MeProcedure.php new file mode 100644 index 00000000..e59e6522 --- /dev/null +++ b/app/Api/Procedure/MeProcedure.php @@ -0,0 +1,72 @@ +sessionStorage->user; + } + + public function getMyDashboard() + { + $user_id = $this->userSession->getId(); + $projects = $this->projectModel->getQueryColumnStats($this->projectPermissionModel->getActiveProjectIds($user_id))->findAll(); + $tasks = $this->taskFinderModel->getUserQuery($user_id)->findAll(); + + return array( + 'projects' => $this->formatProjects($projects), + 'tasks' => $this->formatTasks($tasks), + 'subtasks' => $this->subtaskModel->getUserQuery($user_id, array(SubtaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS))->findAll(), + ); + } + + public function getMyActivityStream() + { + $project_ids = $this->projectPermissionModel->getActiveProjectIds($this->userSession->getId()); + return $this->helper->projectActivity->getProjectsEvents($project_ids, 100); + } + + public function createMyPrivateProject($name, $description = null) + { + if ($this->configModel->get('disable_private_project', 0) == 1) { + return false; + } + + $values = array( + 'name' => $name, + 'description' => $description, + 'is_private' => 1, + ); + + list($valid, ) = $this->projectValidator->validateCreation($values); + return $valid ? $this->projectModel->create($values, $this->userSession->getId(), true) : false; + } + + public function getMyProjectsList() + { + return $this->projectUserRoleModel->getProjectsByUser($this->userSession->getId()); + } + + public function getMyOverdueTasks() + { + return $this->taskFinderModel->getOverdueTasksByUser($this->userSession->getId()); + } + + public function getMyProjects() + { + $project_ids = $this->projectPermissionModel->getActiveProjectIds($this->userSession->getId()); + $projects = $this->projectModel->getAllByIds($project_ids); + + return $this->formatProjects($projects); + } +} diff --git a/app/Api/Procedure/ProjectPermissionProcedure.php b/app/Api/Procedure/ProjectPermissionProcedure.php new file mode 100644 index 00000000..e22e1d62 --- /dev/null +++ b/app/Api/Procedure/ProjectPermissionProcedure.php @@ -0,0 +1,69 @@ +container)->check($this->getClassName(), 'getProjectUsers', $project_id); + return $this->projectUserRoleModel->getAllUsers($project_id); + } + + public function getAssignableUsers($project_id, $prepend_unassigned = false) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAssignableUsers', $project_id); + return $this->projectUserRoleModel->getAssignableUsersList($project_id, $prepend_unassigned); + } + + public function addProjectUser($project_id, $user_id, $role = Role::PROJECT_MEMBER) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addProjectUser', $project_id); + return $this->projectUserRoleModel->addUser($project_id, $user_id, $role); + } + + public function addProjectGroup($project_id, $group_id, $role = Role::PROJECT_MEMBER) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addProjectGroup', $project_id); + return $this->projectGroupRoleModel->addGroup($project_id, $group_id, $role); + } + + public function removeProjectUser($project_id, $user_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProjectUser', $project_id); + return $this->projectUserRoleModel->removeUser($project_id, $user_id); + } + + public function removeProjectGroup($project_id, $group_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProjectGroup', $project_id); + return $this->projectGroupRoleModel->removeGroup($project_id, $group_id); + } + + public function changeProjectUserRole($project_id, $user_id, $role) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeProjectUserRole', $project_id); + return $this->projectUserRoleModel->changeUserRole($project_id, $user_id, $role); + } + + public function changeProjectGroupRole($project_id, $group_id, $role) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeProjectGroupRole', $project_id); + return $this->projectGroupRoleModel->changeGroupRole($project_id, $group_id, $role); + } + + public function getProjectUserRole($project_id, $user_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectUserRole', $project_id); + return $this->projectUserRoleModel->getUserRole($project_id, $user_id); + } +} diff --git a/app/Api/Procedure/ProjectProcedure.php b/app/Api/Procedure/ProjectProcedure.php new file mode 100644 index 00000000..9187f221 --- /dev/null +++ b/app/Api/Procedure/ProjectProcedure.php @@ -0,0 +1,106 @@ +container)->check($this->getClassName(), 'getProjectById', $project_id); + return $this->formatProject($this->projectModel->getById($project_id)); + } + + public function getProjectByName($name) + { + $project = $this->projectModel->getByName($name); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectByName', $project['id']); + return $this->formatProject($project); + } + + public function getAllProjects() + { + return $this->formatProjects($this->projectModel->getAll()); + } + + public function removeProject($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProject', $project_id); + return $this->projectModel->remove($project_id); + } + + public function enableProject($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'enableProject', $project_id); + return $this->projectModel->enable($project_id); + } + + public function disableProject($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'disableProject', $project_id); + return $this->projectModel->disable($project_id); + } + + public function enableProjectPublicAccess($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'enableProjectPublicAccess', $project_id); + return $this->projectModel->enablePublicAccess($project_id); + } + + public function disableProjectPublicAccess($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'disableProjectPublicAccess', $project_id); + return $this->projectModel->disablePublicAccess($project_id); + } + + public function getProjectActivities(array $project_ids) + { + foreach ($project_ids as $project_id) { + ProjectAuthorization::getInstance($this->container) + ->check($this->getClassName(), 'getProjectActivities', $project_id); + } + + return $this->helper->projectActivity->getProjectsEvents($project_ids); + } + + public function getProjectActivity($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectActivity', $project_id); + return $this->helper->projectActivity->getProjectEvents($project_id); + } + + public function createProject($name, $description = null, $owner_id = 0, $identifier = null) + { + $values = array( + 'name' => $name, + 'description' => $description, + 'identifier' => $identifier, + ); + + list($valid, ) = $this->projectValidator->validateCreation($values); + return $valid ? $this->projectModel->create($values, $owner_id, $this->userSession->isLogged()) : false; + } + + public function updateProject($project_id, $name, $description = null, $owner_id = null, $identifier = null) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateProject', $project_id); + + $values = $this->filterValues(array( + 'id' => $project_id, + 'name' => $name, + 'description' => $description, + 'owner_id' => $owner_id, + 'identifier' => $identifier, + )); + + list($valid, ) = $this->projectValidator->validateModification($values); + return $valid && $this->projectModel->update($values); + } +} diff --git a/app/Api/Procedure/SubtaskProcedure.php b/app/Api/Procedure/SubtaskProcedure.php new file mode 100644 index 00000000..e2400912 --- /dev/null +++ b/app/Api/Procedure/SubtaskProcedure.php @@ -0,0 +1,74 @@ +container)->check($this->getClassName(), 'getSubtask', $subtask_id); + return $this->subtaskModel->getById($subtask_id); + } + + public function getAllSubtasks($task_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllSubtasks', $task_id); + return $this->subtaskModel->getAll($task_id); + } + + public function removeSubtask($subtask_id) + { + SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeSubtask', $subtask_id); + return $this->subtaskModel->remove($subtask_id); + } + + public function createSubtask($task_id, $title, $user_id = 0, $time_estimated = 0, $time_spent = 0, $status = 0) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createSubtask', $task_id); + + $values = array( + 'title' => $title, + 'task_id' => $task_id, + 'user_id' => $user_id, + 'time_estimated' => $time_estimated, + 'time_spent' => $time_spent, + 'status' => $status, + ); + + list($valid, ) = $this->subtaskValidator->validateCreation($values); + return $valid ? $this->subtaskModel->create($values) : false; + } + + public function updateSubtask($id, $task_id, $title = null, $user_id = null, $time_estimated = null, $time_spent = null, $status = null) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateSubtask', $task_id); + + $values = array( + 'id' => $id, + 'task_id' => $task_id, + 'title' => $title, + 'user_id' => $user_id, + 'time_estimated' => $time_estimated, + 'time_spent' => $time_spent, + 'status' => $status, + ); + + foreach ($values as $key => $value) { + if (is_null($value)) { + unset($values[$key]); + } + } + + list($valid, ) = $this->subtaskValidator->validateApiModification($values); + return $valid && $this->subtaskModel->update($values); + } +} diff --git a/app/Api/Procedure/SubtaskTimeTrackingProcedure.php b/app/Api/Procedure/SubtaskTimeTrackingProcedure.php new file mode 100644 index 00000000..5d1988d6 --- /dev/null +++ b/app/Api/Procedure/SubtaskTimeTrackingProcedure.php @@ -0,0 +1,39 @@ +container)->check($this->getClassName(), 'hasSubtaskTimer', $subtask_id); + return $this->subtaskTimeTrackingModel->hasTimer($subtask_id, $user_id); + } + + public function logSubtaskStartTime($subtask_id, $user_id) + { + SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'logSubtaskStartTime', $subtask_id); + return $this->subtaskTimeTrackingModel->logStartTime($subtask_id, $user_id); + } + + public function logSubtaskEndTime($subtask_id,$user_id) + { + SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'logSubtaskEndTime', $subtask_id); + return $this->subtaskTimeTrackingModel->logEndTime($subtask_id, $user_id); + } + + public function getSubtaskTimeSpent($subtask_id,$user_id) + { + SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSubtaskTimeSpent', $subtask_id); + return $this->subtaskTimeTrackingModel->getTimeSpent($subtask_id, $user_id); + } +} diff --git a/app/Api/Procedure/SwimlaneProcedure.php b/app/Api/Procedure/SwimlaneProcedure.php new file mode 100644 index 00000000..9b7d181d --- /dev/null +++ b/app/Api/Procedure/SwimlaneProcedure.php @@ -0,0 +1,91 @@ +container)->check($this->getClassName(), 'getActiveSwimlanes', $project_id); + return $this->swimlaneModel->getSwimlanes($project_id); + } + + public function getAllSwimlanes($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllSwimlanes', $project_id); + return $this->swimlaneModel->getAll($project_id); + } + + public function getSwimlaneById($swimlane_id) + { + $swimlane = $this->swimlaneModel->getById($swimlane_id); + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSwimlaneById', $swimlane['project_id']); + return $swimlane; + } + + public function getSwimlaneByName($project_id, $name) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSwimlaneByName', $project_id); + return $this->swimlaneModel->getByName($project_id, $name); + } + + public function getSwimlane($swimlane_id) + { + return $this->swimlaneModel->getById($swimlane_id); + } + + public function getDefaultSwimlane($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getDefaultSwimlane', $project_id); + return $this->swimlaneModel->getDefault($project_id); + } + + public function addSwimlane($project_id, $name, $description = '') + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addSwimlane', $project_id); + return $this->swimlaneModel->create(array('project_id' => $project_id, 'name' => $name, 'description' => $description)); + } + + public function updateSwimlane($swimlane_id, $name, $description = null) + { + $values = array('id' => $swimlane_id, 'name' => $name); + + if (!is_null($description)) { + $values['description'] = $description; + } + + return $this->swimlaneModel->update($values); + } + + public function removeSwimlane($project_id, $swimlane_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeSwimlane', $project_id); + return $this->swimlaneModel->remove($project_id, $swimlane_id); + } + + public function disableSwimlane($project_id, $swimlane_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'disableSwimlane', $project_id); + return $this->swimlaneModel->disable($project_id, $swimlane_id); + } + + public function enableSwimlane($project_id, $swimlane_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'enableSwimlane', $project_id); + return $this->swimlaneModel->enable($project_id, $swimlane_id); + } + + public function changeSwimlanePosition($project_id, $swimlane_id, $position) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeSwimlanePosition', $project_id); + return $this->swimlaneModel->changePosition($project_id, $swimlane_id, $position); + } +} diff --git a/app/Api/Procedure/TaskFileProcedure.php b/app/Api/Procedure/TaskFileProcedure.php new file mode 100644 index 00000000..5aa7ea0b --- /dev/null +++ b/app/Api/Procedure/TaskFileProcedure.php @@ -0,0 +1,70 @@ +container)->check($this->getClassName(), 'getTaskFile', $file_id); + return $this->taskFileModel->getById($file_id); + } + + public function getAllTaskFiles($task_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTaskFiles', $task_id); + return $this->taskFileModel->getAll($task_id); + } + + public function downloadTaskFile($file_id) + { + TaskFileAuthorization::getInstance($this->container)->check($this->getClassName(), 'downloadTaskFile', $file_id); + + try { + $file = $this->taskFileModel->getById($file_id); + + if (! empty($file)) { + return base64_encode($this->objectStorage->get($file['path'])); + } + } catch (ObjectStorageException $e) { + $this->logger->error($e->getMessage()); + } + + return ''; + } + + public function createTaskFile($project_id, $task_id, $filename, $blob) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTaskFile', $project_id); + + try { + return $this->taskFileModel->uploadContent($task_id, $filename, $blob); + } catch (ObjectStorageException $e) { + $this->logger->error($e->getMessage()); + return false; + } + } + + public function removeTaskFile($file_id) + { + TaskFileAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeTaskFile', $file_id); + return $this->taskFileModel->remove($file_id); + } + + public function removeAllTaskFiles($task_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeAllTaskFiles', $task_id); + return $this->taskFileModel->removeAll($task_id); + } +} diff --git a/app/Api/Procedure/TaskLinkProcedure.php b/app/Api/Procedure/TaskLinkProcedure.php new file mode 100644 index 00000000..375266fb --- /dev/null +++ b/app/Api/Procedure/TaskLinkProcedure.php @@ -0,0 +1,85 @@ +container)->check($this->getClassName(), 'getTaskLinkById', $task_link_id); + return $this->taskLinkModel->getById($task_link_id); + } + + /** + * Get all links attached to a task + * + * @access public + * @param integer $task_id Task id + * @return array + */ + public function getAllTaskLinks($task_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTaskLinks', $task_id); + return $this->taskLinkModel->getAll($task_id); + } + + /** + * Create a new link + * + * @access public + * @param integer $task_id Task id + * @param integer $opposite_task_id Opposite task id + * @param integer $link_id Link id + * @return integer Task link id + */ + public function createTaskLink($task_id, $opposite_task_id, $link_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTaskLink', $task_id); + return $this->taskLinkModel->create($task_id, $opposite_task_id, $link_id); + } + + /** + * Update a task link + * + * @access public + * @param integer $task_link_id Task link id + * @param integer $task_id Task id + * @param integer $opposite_task_id Opposite task id + * @param integer $link_id Link id + * @return boolean + */ + public function updateTaskLink($task_link_id, $task_id, $opposite_task_id, $link_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateTaskLink', $task_id); + return $this->taskLinkModel->update($task_link_id, $task_id, $opposite_task_id, $link_id); + } + + /** + * Remove a link between two tasks + * + * @access public + * @param integer $task_link_id + * @return boolean + */ + public function removeTaskLink($task_link_id) + { + TaskLinkAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeTaskLink', $task_link_id); + return $this->taskLinkModel->remove($task_link_id); + } +} diff --git a/app/Api/Procedure/TaskProcedure.php b/app/Api/Procedure/TaskProcedure.php new file mode 100644 index 00000000..2d29a4ef --- /dev/null +++ b/app/Api/Procedure/TaskProcedure.php @@ -0,0 +1,167 @@ +container)->check($this->getClassName(), 'searchTasks', $project_id); + return $this->taskLexer->build($query)->withFilter(new TaskProjectFilter($project_id))->toArray(); + } + + public function getTask($task_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTask', $task_id); + return $this->formatTask($this->taskFinderModel->getById($task_id)); + } + + public function getTaskByReference($project_id, $reference) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTaskByReference', $project_id); + return $this->formatTask($this->taskFinderModel->getByReference($project_id, $reference)); + } + + public function getAllTasks($project_id, $status_id = TaskModel::STATUS_OPEN) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTasks', $project_id); + return $this->formatTasks($this->taskFinderModel->getAll($project_id, $status_id)); + } + + public function getOverdueTasks() + { + return $this->taskFinderModel->getOverdueTasks(); + } + + public function getOverdueTasksByProject($project_id) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getOverdueTasksByProject', $project_id); + return $this->taskFinderModel->getOverdueTasksByProject($project_id); + } + + public function openTask($task_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'openTask', $task_id); + return $this->taskStatusModel->open($task_id); + } + + public function closeTask($task_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'closeTask', $task_id); + return $this->taskStatusModel->close($task_id); + } + + public function removeTask($task_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeTask', $task_id); + return $this->taskModel->remove($task_id); + } + + public function moveTaskPosition($project_id, $task_id, $column_id, $position, $swimlane_id = 0) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'moveTaskPosition', $project_id); + return $this->taskPositionModel->movePosition($project_id, $task_id, $column_id, $position, $swimlane_id); + } + + public function moveTaskToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'moveTaskToProject', $project_id); + return $this->taskDuplicationModel->moveToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id); + } + + public function duplicateTaskToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null) + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'duplicateTaskToProject', $project_id); + return $this->taskDuplicationModel->duplicateToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id); + } + + public function createTask($title, $project_id, $color_id = '', $column_id = 0, $owner_id = 0, $creator_id = 0, + $date_due = '', $description = '', $category_id = 0, $score = 0, $swimlane_id = 0, $priority = 0, + $recurrence_status = 0, $recurrence_trigger = 0, $recurrence_factor = 0, $recurrence_timeframe = 0, + $recurrence_basedate = 0, $reference = '') + { + ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTask', $project_id); + + if ($owner_id !== 0 && ! $this->projectPermissionModel->isAssignable($project_id, $owner_id)) { + return false; + } + + if ($this->userSession->isLogged()) { + $creator_id = $this->userSession->getId(); + } + + $values = array( + 'title' => $title, + 'project_id' => $project_id, + 'color_id' => $color_id, + 'column_id' => $column_id, + 'owner_id' => $owner_id, + 'creator_id' => $creator_id, + 'date_due' => $date_due, + 'description' => $description, + 'category_id' => $category_id, + 'score' => $score, + 'swimlane_id' => $swimlane_id, + 'recurrence_status' => $recurrence_status, + 'recurrence_trigger' => $recurrence_trigger, + 'recurrence_factor' => $recurrence_factor, + 'recurrence_timeframe' => $recurrence_timeframe, + 'recurrence_basedate' => $recurrence_basedate, + 'reference' => $reference, + 'priority' => $priority, + ); + + list($valid, ) = $this->taskValidator->validateCreation($values); + + return $valid ? $this->taskCreationModel->create($values) : false; + } + + public function updateTask($id, $title = null, $color_id = null, $owner_id = null, + $date_due = null, $description = null, $category_id = null, $score = null, $priority = null, + $recurrence_status = null, $recurrence_trigger = null, $recurrence_factor = null, + $recurrence_timeframe = null, $recurrence_basedate = null, $reference = null) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateTask', $id); + $project_id = $this->taskFinderModel->getProjectId($id); + + if ($project_id === 0) { + return false; + } + + if ($owner_id !== null && $owner_id != 0 && ! $this->projectPermissionModel->isAssignable($project_id, $owner_id)) { + return false; + } + + $values = $this->filterValues(array( + 'id' => $id, + 'title' => $title, + 'color_id' => $color_id, + 'owner_id' => $owner_id, + 'date_due' => $date_due, + 'description' => $description, + 'category_id' => $category_id, + 'score' => $score, + 'recurrence_status' => $recurrence_status, + 'recurrence_trigger' => $recurrence_trigger, + 'recurrence_factor' => $recurrence_factor, + 'recurrence_timeframe' => $recurrence_timeframe, + 'recurrence_basedate' => $recurrence_basedate, + 'reference' => $reference, + 'priority' => $priority, + )); + + list($valid) = $this->taskValidator->validateApiModification($values); + return $valid && $this->taskModificationModel->update($values); + } +} diff --git a/app/Api/Procedure/UserProcedure.php b/app/Api/Procedure/UserProcedure.php new file mode 100644 index 00000000..145f85bf --- /dev/null +++ b/app/Api/Procedure/UserProcedure.php @@ -0,0 +1,131 @@ +userModel->getById($user_id); + } + + public function getUserByName($username) + { + return $this->userModel->getByUsername($username); + } + + public function getAllUsers() + { + return $this->userModel->getAll(); + } + + public function removeUser($user_id) + { + return $this->userModel->remove($user_id); + } + + public function disableUser($user_id) + { + return $this->userModel->disable($user_id); + } + + public function enableUser($user_id) + { + return $this->userModel->enable($user_id); + } + + public function isActiveUser($user_id) + { + return $this->userModel->isActive($user_id); + } + + public function createUser($username, $password, $name = '', $email = '', $role = Role::APP_USER) + { + $values = array( + 'username' => $username, + 'password' => $password, + 'confirmation' => $password, + 'name' => $name, + 'email' => $email, + 'role' => $role, + ); + + list($valid, ) = $this->userValidator->validateCreation($values); + return $valid ? $this->userModel->create($values) : false; + } + + /** + * Create LDAP user in the database + * + * Only "anonymous" and "proxy" LDAP authentication are supported by this method + * + * User information will be fetched from the LDAP server + * + * @access public + * @param string $username + * @return bool|int + */ + public function createLdapUser($username) + { + if (LDAP_BIND_TYPE === 'user') { + $this->logger->error('LDAP authentication "user" is not supported by this API call'); + return false; + } + + try { + + $ldap = LdapClient::connect(); + $ldap->setLogger($this->logger); + $user = LdapUser::getUser($ldap, $username); + + if ($user === null) { + $this->logger->info('User not found in LDAP server'); + return false; + } + + if ($user->getUsername() === '') { + throw new LogicException('Username not found in LDAP profile, check the parameter LDAP_USER_ATTRIBUTE_USERNAME'); + } + + $values = array( + 'username' => $user->getUsername(), + 'name' => $user->getName(), + 'email' => $user->getEmail(), + 'role' => $user->getRole(), + 'is_ldap_user' => 1, + ); + + return $this->userModel->create($values); + + } catch (LdapException $e) { + $this->logger->error($e->getMessage()); + return false; + } + } + + public function updateUser($id, $username = null, $name = null, $email = null, $role = null) + { + $values = $this->filterValues(array( + 'id' => $id, + 'username' => $username, + 'name' => $name, + 'email' => $email, + 'role' => $role, + )); + + list($valid, ) = $this->userValidator->validateApiModification($values); + return $valid && $this->userModel->update($values); + } +} diff --git a/app/Api/ProjectApi.php b/app/Api/ProjectApi.php deleted file mode 100644 index a726d4eb..00000000 --- a/app/Api/ProjectApi.php +++ /dev/null @@ -1,87 +0,0 @@ -checkProjectPermission($project_id); - return $this->formatProject($this->projectModel->getById($project_id)); - } - - public function getProjectByName($name) - { - return $this->formatProject($this->projectModel->getByName($name)); - } - - public function getAllProjects() - { - return $this->formatProjects($this->projectModel->getAll()); - } - - public function removeProject($project_id) - { - return $this->projectModel->remove($project_id); - } - - public function enableProject($project_id) - { - return $this->projectModel->enable($project_id); - } - - public function disableProject($project_id) - { - return $this->projectModel->disable($project_id); - } - - public function enableProjectPublicAccess($project_id) - { - return $this->projectModel->enablePublicAccess($project_id); - } - - public function disableProjectPublicAccess($project_id) - { - return $this->projectModel->disablePublicAccess($project_id); - } - - public function getProjectActivities(array $project_ids) - { - return $this->helper->projectActivity->getProjectsEvents($project_ids); - } - - public function getProjectActivity($project_id) - { - $this->checkProjectPermission($project_id); - return $this->helper->projectActivity->getProjectEvents($project_id); - } - - public function createProject($name, $description = null) - { - $values = array( - 'name' => $name, - 'description' => $description - ); - - list($valid, ) = $this->projectValidator->validateCreation($values); - return $valid ? $this->projectModel->create($values) : false; - } - - public function updateProject($project_id, $name, $description = null) - { - $values = $this->filterValues(array( - 'id' => $project_id, - 'name' => $name, - 'description' => $description - )); - - list($valid, ) = $this->projectValidator->validateModification($values); - return $valid && $this->projectModel->update($values); - } -} diff --git a/app/Api/ProjectPermissionApi.php b/app/Api/ProjectPermissionApi.php deleted file mode 100644 index 37c5e13c..00000000 --- a/app/Api/ProjectPermissionApi.php +++ /dev/null @@ -1,55 +0,0 @@ -projectUserRoleModel->getAllUsers($project_id); - } - - public function getAssignableUsers($project_id, $prepend_unassigned = false) - { - return $this->projectUserRoleModel->getAssignableUsersList($project_id, $prepend_unassigned); - } - - public function addProjectUser($project_id, $user_id, $role = Role::PROJECT_MEMBER) - { - return $this->projectUserRoleModel->addUser($project_id, $user_id, $role); - } - - public function addProjectGroup($project_id, $group_id, $role = Role::PROJECT_MEMBER) - { - return $this->projectGroupRoleModel->addGroup($project_id, $group_id, $role); - } - - public function removeProjectUser($project_id, $user_id) - { - return $this->projectUserRoleModel->removeUser($project_id, $user_id); - } - - public function removeProjectGroup($project_id, $group_id) - { - return $this->projectGroupRoleModel->removeGroup($project_id, $group_id); - } - - public function changeProjectUserRole($project_id, $user_id, $role) - { - return $this->projectUserRoleModel->changeUserRole($project_id, $user_id, $role); - } - - public function changeProjectGroupRole($project_id, $group_id, $role) - { - return $this->projectGroupRoleModel->changeGroupRole($project_id, $group_id, $role); - } -} diff --git a/app/Api/SubtaskApi.php b/app/Api/SubtaskApi.php deleted file mode 100644 index 5764ff7d..00000000 --- a/app/Api/SubtaskApi.php +++ /dev/null @@ -1,66 +0,0 @@ -subtaskModel->getById($subtask_id); - } - - public function getAllSubtasks($task_id) - { - return $this->subtaskModel->getAll($task_id); - } - - public function removeSubtask($subtask_id) - { - return $this->subtaskModel->remove($subtask_id); - } - - public function createSubtask($task_id, $title, $user_id = 0, $time_estimated = 0, $time_spent = 0, $status = 0) - { - $values = array( - 'title' => $title, - 'task_id' => $task_id, - 'user_id' => $user_id, - 'time_estimated' => $time_estimated, - 'time_spent' => $time_spent, - 'status' => $status, - ); - - list($valid, ) = $this->subtaskValidator->validateCreation($values); - return $valid ? $this->subtaskModel->create($values) : false; - } - - public function updateSubtask($id, $task_id, $title = null, $user_id = null, $time_estimated = null, $time_spent = null, $status = null) - { - $values = array( - 'id' => $id, - 'task_id' => $task_id, - 'title' => $title, - 'user_id' => $user_id, - 'time_estimated' => $time_estimated, - 'time_spent' => $time_spent, - 'status' => $status, - ); - - foreach ($values as $key => $value) { - if (is_null($value)) { - unset($values[$key]); - } - } - - list($valid, ) = $this->subtaskValidator->validateApiModification($values); - return $valid && $this->subtaskModel->update($values); - } -} diff --git a/app/Api/SubtaskTimeTrackingApi.php b/app/Api/SubtaskTimeTrackingApi.php deleted file mode 100644 index 0e700b31..00000000 --- a/app/Api/SubtaskTimeTrackingApi.php +++ /dev/null @@ -1,34 +0,0 @@ -subtaskTimeTrackingModel->hasTimer($subtask_id,$user_id); - } - - public function logStartTime($subtask_id,$user_id) - { - return $this->subtaskTimeTrackingModel->logStartTime($subtask_id,$user_id); - } - - public function logEndTime($subtask_id,$user_id) - { - return $this->subtaskTimeTrackingModel->logEndTime($subtask_id,$user_id); - } - - public function getTimeSpent($subtask_id,$user_id) - { - return $this->subtaskTimeTrackingModel->getTimeSpent($subtask_id,$user_id); - } -} diff --git a/app/Api/SwimlaneApi.php b/app/Api/SwimlaneApi.php deleted file mode 100644 index c3c56a71..00000000 --- a/app/Api/SwimlaneApi.php +++ /dev/null @@ -1,80 +0,0 @@ -swimlaneModel->getSwimlanes($project_id); - } - - public function getAllSwimlanes($project_id) - { - return $this->swimlaneModel->getAll($project_id); - } - - public function getSwimlaneById($swimlane_id) - { - return $this->swimlaneModel->getById($swimlane_id); - } - - public function getSwimlaneByName($project_id, $name) - { - return $this->swimlaneModel->getByName($project_id, $name); - } - - public function getSwimlane($swimlane_id) - { - return $this->swimlaneModel->getById($swimlane_id); - } - - public function getDefaultSwimlane($project_id) - { - return $this->swimlaneModel->getDefault($project_id); - } - - public function addSwimlane($project_id, $name, $description = '') - { - return $this->swimlaneModel->create(array('project_id' => $project_id, 'name' => $name, 'description' => $description)); - } - - public function updateSwimlane($swimlane_id, $name, $description = null) - { - $values = array('id' => $swimlane_id, 'name' => $name); - - if (!is_null($description)) { - $values['description'] = $description; - } - - return $this->swimlaneModel->update($values); - } - - public function removeSwimlane($project_id, $swimlane_id) - { - return $this->swimlaneModel->remove($project_id, $swimlane_id); - } - - public function disableSwimlane($project_id, $swimlane_id) - { - return $this->swimlaneModel->disable($project_id, $swimlane_id); - } - - public function enableSwimlane($project_id, $swimlane_id) - { - return $this->swimlaneModel->enable($project_id, $swimlane_id); - } - - public function changeSwimlanePosition($project_id, $swimlane_id, $position) - { - return $this->swimlaneModel->changePosition($project_id, $swimlane_id, $position); - } -} diff --git a/app/Api/TaskApi.php b/app/Api/TaskApi.php deleted file mode 100644 index 523bfaa0..00000000 --- a/app/Api/TaskApi.php +++ /dev/null @@ -1,163 +0,0 @@ -checkProjectPermission($project_id); - return $this->taskLexer->build($query)->withFilter(new TaskProjectFilter($project_id))->toArray(); - } - - public function getTask($task_id) - { - $this->checkTaskPermission($task_id); - return $this->formatTask($this->taskFinderModel->getById($task_id)); - } - - public function getTaskByReference($project_id, $reference) - { - $this->checkProjectPermission($project_id); - return $this->formatTask($this->taskFinderModel->getByReference($project_id, $reference)); - } - - public function getAllTasks($project_id, $status_id = TaskModel::STATUS_OPEN) - { - $this->checkProjectPermission($project_id); - return $this->formatTasks($this->taskFinderModel->getAll($project_id, $status_id)); - } - - public function getOverdueTasks() - { - return $this->taskFinderModel->getOverdueTasks(); - } - - public function getOverdueTasksByProject($project_id) - { - $this->checkProjectPermission($project_id); - return $this->taskFinderModel->getOverdueTasksByProject($project_id); - } - - public function openTask($task_id) - { - $this->checkTaskPermission($task_id); - return $this->taskStatusModel->open($task_id); - } - - public function closeTask($task_id) - { - $this->checkTaskPermission($task_id); - return $this->taskStatusModel->close($task_id); - } - - public function removeTask($task_id) - { - return $this->taskModel->remove($task_id); - } - - public function moveTaskPosition($project_id, $task_id, $column_id, $position, $swimlane_id = 0) - { - $this->checkProjectPermission($project_id); - return $this->taskPositionModel->movePosition($project_id, $task_id, $column_id, $position, $swimlane_id); - } - - public function moveTaskToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null) - { - return $this->taskDuplicationModel->moveToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id); - } - - public function duplicateTaskToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null) - { - return $this->taskDuplicationModel->duplicateToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id); - } - - public function createTask($title, $project_id, $color_id = '', $column_id = 0, $owner_id = 0, $creator_id = 0, - $date_due = '', $description = '', $category_id = 0, $score = 0, $swimlane_id = 0, $priority = 0, - $recurrence_status = 0, $recurrence_trigger = 0, $recurrence_factor = 0, $recurrence_timeframe = 0, - $recurrence_basedate = 0, $reference = '') - { - $this->checkProjectPermission($project_id); - - if ($owner_id !== 0 && ! $this->projectPermissionModel->isAssignable($project_id, $owner_id)) { - return false; - } - - if ($this->userSession->isLogged()) { - $creator_id = $this->userSession->getId(); - } - - $values = array( - 'title' => $title, - 'project_id' => $project_id, - 'color_id' => $color_id, - 'column_id' => $column_id, - 'owner_id' => $owner_id, - 'creator_id' => $creator_id, - 'date_due' => $date_due, - 'description' => $description, - 'category_id' => $category_id, - 'score' => $score, - 'swimlane_id' => $swimlane_id, - 'recurrence_status' => $recurrence_status, - 'recurrence_trigger' => $recurrence_trigger, - 'recurrence_factor' => $recurrence_factor, - 'recurrence_timeframe' => $recurrence_timeframe, - 'recurrence_basedate' => $recurrence_basedate, - 'reference' => $reference, - 'priority' => $priority, - ); - - list($valid, ) = $this->taskValidator->validateCreation($values); - - return $valid ? $this->taskCreationModel->create($values) : false; - } - - public function updateTask($id, $title = null, $color_id = null, $owner_id = null, - $date_due = null, $description = null, $category_id = null, $score = null, $priority = null, - $recurrence_status = null, $recurrence_trigger = null, $recurrence_factor = null, - $recurrence_timeframe = null, $recurrence_basedate = null, $reference = null) - { - $this->checkTaskPermission($id); - - $project_id = $this->taskFinderModel->getProjectId($id); - - if ($project_id === 0) { - return false; - } - - if ($owner_id !== null && $owner_id != 0 && ! $this->projectPermissionModel->isAssignable($project_id, $owner_id)) { - return false; - } - - $values = $this->filterValues(array( - 'id' => $id, - 'title' => $title, - 'color_id' => $color_id, - 'owner_id' => $owner_id, - 'date_due' => $date_due, - 'description' => $description, - 'category_id' => $category_id, - 'score' => $score, - 'recurrence_status' => $recurrence_status, - 'recurrence_trigger' => $recurrence_trigger, - 'recurrence_factor' => $recurrence_factor, - 'recurrence_timeframe' => $recurrence_timeframe, - 'recurrence_basedate' => $recurrence_basedate, - 'reference' => $reference, - 'priority' => $priority, - )); - - list($valid) = $this->taskValidator->validateApiModification($values); - return $valid && $this->taskModificationModel->update($values); - } -} diff --git a/app/Api/TaskFileApi.php b/app/Api/TaskFileApi.php deleted file mode 100644 index 7b27477c..00000000 --- a/app/Api/TaskFileApi.php +++ /dev/null @@ -1,59 +0,0 @@ -taskFileModel->getById($file_id); - } - - public function getAllTaskFiles($task_id) - { - return $this->taskFileModel->getAll($task_id); - } - - public function downloadTaskFile($file_id) - { - try { - $file = $this->taskFileModel->getById($file_id); - - if (! empty($file)) { - return base64_encode($this->objectStorage->get($file['path'])); - } - } catch (ObjectStorageException $e) { - $this->logger->error($e->getMessage()); - } - - return ''; - } - - public function createTaskFile($project_id, $task_id, $filename, $blob) - { - try { - return $this->taskFileModel->uploadContent($task_id, $filename, $blob); - } catch (ObjectStorageException $e) { - $this->logger->error($e->getMessage()); - return false; - } - } - - public function removeTaskFile($file_id) - { - return $this->taskFileModel->remove($file_id); - } - - public function removeAllTaskFiles($task_id) - { - return $this->taskFileModel->removeAll($task_id); - } -} diff --git a/app/Api/TaskLinkApi.php b/app/Api/TaskLinkApi.php deleted file mode 100644 index bb809133..00000000 --- a/app/Api/TaskLinkApi.php +++ /dev/null @@ -1,79 +0,0 @@ -taskLinkModel->getById($task_link_id); - } - - /** - * Get all links attached to a task - * - * @access public - * @param integer $task_id Task id - * @return array - */ - public function getAllTaskLinks($task_id) - { - return $this->taskLinkModel->getAll($task_id); - } - - /** - * Create a new link - * - * @access public - * @param integer $task_id Task id - * @param integer $opposite_task_id Opposite task id - * @param integer $link_id Link id - * @return integer Task link id - */ - public function createTaskLink($task_id, $opposite_task_id, $link_id) - { - return $this->taskLinkModel->create($task_id, $opposite_task_id, $link_id); - } - - /** - * Update a task link - * - * @access public - * @param integer $task_link_id Task link id - * @param integer $task_id Task id - * @param integer $opposite_task_id Opposite task id - * @param integer $link_id Link id - * @return boolean - */ - public function updateTaskLink($task_link_id, $task_id, $opposite_task_id, $link_id) - { - return $this->taskLinkModel->update($task_link_id, $task_id, $opposite_task_id, $link_id); - } - - /** - * Remove a link between two tasks - * - * @access public - * @param integer $task_link_id - * @return boolean - */ - public function removeTaskLink($task_link_id) - { - return $this->taskLinkModel->remove($task_link_id); - } -} diff --git a/app/Api/UserApi.php b/app/Api/UserApi.php deleted file mode 100644 index 6cb9df1c..00000000 --- a/app/Api/UserApi.php +++ /dev/null @@ -1,131 +0,0 @@ -userModel->getById($user_id); - } - - public function getUserByName($username) - { - return $this->userModel->getByUsername($username); - } - - public function getAllUsers() - { - return $this->userModel->getAll(); - } - - public function removeUser($user_id) - { - return $this->userModel->remove($user_id); - } - - public function disableUser($user_id) - { - return $this->userModel->disable($user_id); - } - - public function enableUser($user_id) - { - return $this->userModel->enable($user_id); - } - - public function isActiveUser($user_id) - { - return $this->userModel->isActive($user_id); - } - - public function createUser($username, $password, $name = '', $email = '', $role = Role::APP_USER) - { - $values = array( - 'username' => $username, - 'password' => $password, - 'confirmation' => $password, - 'name' => $name, - 'email' => $email, - 'role' => $role, - ); - - list($valid, ) = $this->userValidator->validateCreation($values); - return $valid ? $this->userModel->create($values) : false; - } - - /** - * Create LDAP user in the database - * - * Only "anonymous" and "proxy" LDAP authentication are supported by this method - * - * User information will be fetched from the LDAP server - * - * @access public - * @param string $username - * @return bool|int - */ - public function createLdapUser($username) - { - if (LDAP_BIND_TYPE === 'user') { - $this->logger->error('LDAP authentication "user" is not supported by this API call'); - return false; - } - - try { - - $ldap = LdapClient::connect(); - $ldap->setLogger($this->logger); - $user = LdapUser::getUser($ldap, $username); - - if ($user === null) { - $this->logger->info('User not found in LDAP server'); - return false; - } - - if ($user->getUsername() === '') { - throw new LogicException('Username not found in LDAP profile, check the parameter LDAP_USER_ATTRIBUTE_USERNAME'); - } - - $values = array( - 'username' => $user->getUsername(), - 'name' => $user->getName(), - 'email' => $user->getEmail(), - 'role' => $user->getRole(), - 'is_ldap_user' => 1, - ); - - return $this->userModel->create($values); - - } catch (LdapException $e) { - $this->logger->error($e->getMessage()); - return false; - } - } - - public function updateUser($id, $username = null, $name = null, $email = null, $role = null) - { - $values = $this->filterValues(array( - 'id' => $id, - 'username' => $username, - 'name' => $name, - 'email' => $email, - 'role' => $role, - )); - - list($valid, ) = $this->userValidator->validateApiModification($values); - return $valid && $this->userModel->update($values); - } -} diff --git a/app/Core/Base.php b/app/Core/Base.php index e5dd6ad9..eacca65d 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -35,8 +35,12 @@ use Pimple\Container; * @property \Kanboard\Core\Security\AuthenticationManager $authenticationManager * @property \Kanboard\Core\Security\AccessMap $applicationAccessMap * @property \Kanboard\Core\Security\AccessMap $projectAccessMap + * @property \Kanboard\Core\Security\AccessMap $apiAccessMap + * @property \Kanboard\Core\Security\AccessMap $apiProjectAccessMap * @property \Kanboard\Core\Security\Authorization $applicationAuthorization * @property \Kanboard\Core\Security\Authorization $projectAuthorization + * @property \Kanboard\Core\Security\Authorization $apiAuthorization + * @property \Kanboard\Core\Security\Authorization $apiProjectAuthorization * @property \Kanboard\Core\Security\Role $role * @property \Kanboard\Core\Security\Token $token * @property \Kanboard\Core\Session\FlashMessage $flash diff --git a/app/Model/ActionModel.php b/app/Model/ActionModel.php index 53393ed5..b5d2bd06 100644 --- a/app/Model/ActionModel.php +++ b/app/Model/ActionModel.php @@ -85,6 +85,18 @@ class ActionModel extends Base return $action; } + /** + * Get the projectId by the actionId + * + * @access public + * @param integer $action_id + * @return integer + */ + public function getProjectId($action_id) + { + return $this->db->table(self::TABLE)->eq('id', $action_id)->findOneColumn('project_id') ?: 0; + } + /** * Attach parameters to actions * diff --git a/app/Model/CategoryModel.php b/app/Model/CategoryModel.php index 62fb5611..024d0026 100644 --- a/app/Model/CategoryModel.php +++ b/app/Model/CategoryModel.php @@ -55,6 +55,18 @@ class CategoryModel extends Base return $this->db->table(self::TABLE)->eq('id', $category_id)->findOneColumn('name') ?: ''; } + /** + * Get the projectId by the category id + * + * @access public + * @param integer $category_id Category id + * @return integer + */ + public function getProjectId($category_id) + { + return $this->db->table(self::TABLE)->eq('id', $category_id)->findOneColumn('project_id') ?: 0; + } + /** * Get a category id by the category name and project id * diff --git a/app/Model/ColumnModel.php b/app/Model/ColumnModel.php index 1adac0f2..795fe692 100644 --- a/app/Model/ColumnModel.php +++ b/app/Model/ColumnModel.php @@ -31,6 +31,18 @@ class ColumnModel extends Base return $this->db->table(self::TABLE)->eq('id', $column_id)->findOne(); } + /** + * Get projectId by the columnId + * + * @access public + * @param integer $column_id Column id + * @return integer + */ + public function getProjectId($column_id) + { + return $this->db->table(self::TABLE)->eq('id', $column_id)->findOneColumn('project_id'); + } + /** * Get the first column id for a given project * diff --git a/app/Model/CommentModel.php b/app/Model/CommentModel.php index 36e1fc48..4231f29d 100644 --- a/app/Model/CommentModel.php +++ b/app/Model/CommentModel.php @@ -29,6 +29,22 @@ class CommentModel extends Base const EVENT_CREATE = 'comment.create'; const EVENT_USER_MENTION = 'comment.user.mention'; + /** + * Get projectId from commentId + * + * @access public + * @param integer $comment_id + * @return integer + */ + public function getProjectId($comment_id) + { + return $this->db + ->table(self::TABLE) + ->eq(self::TABLE.'.id', $comment_id) + ->join(TaskModel::TABLE, 'id', 'task_id') + ->findOneColumn(TaskModel::TABLE . '.project_id') ?: 0; + } + /** * Get all comments for a given task * diff --git a/app/Model/SubtaskModel.php b/app/Model/SubtaskModel.php index 019064ad..a97bddbf 100644 --- a/app/Model/SubtaskModel.php +++ b/app/Model/SubtaskModel.php @@ -51,6 +51,22 @@ class SubtaskModel extends Base const EVENT_CREATE = 'subtask.create'; const EVENT_DELETE = 'subtask.delete'; + /** + * Get projectId from subtaskId + * + * @access public + * @param integer $subtask_id + * @return integer + */ + public function getProjectId($subtask_id) + { + return $this->db + ->table(self::TABLE) + ->eq(self::TABLE.'.id', $subtask_id) + ->join(TaskModel::TABLE, 'id', 'task_id') + ->findOneColumn(TaskModel::TABLE . '.project_id') ?: 0; + } + /** * Get available status * diff --git a/app/Model/TaskFileModel.php b/app/Model/TaskFileModel.php index 24c1ad4b..7603019a 100644 --- a/app/Model/TaskFileModel.php +++ b/app/Model/TaskFileModel.php @@ -72,6 +72,22 @@ class TaskFileModel extends FileModel return self::EVENT_CREATE; } + /** + * Get projectId from fileId + * + * @access public + * @param integer $file_id + * @return integer + */ + public function getProjectId($file_id) + { + return $this->db + ->table(self::TABLE) + ->eq(self::TABLE.'.id', $file_id) + ->join(TaskModel::TABLE, 'id', 'task_id') + ->findOneColumn(TaskModel::TABLE . '.project_id') ?: 0; + } + /** * Handle screenshot upload * diff --git a/app/Model/TaskLinkModel.php b/app/Model/TaskLinkModel.php index 45225e35..09978eae 100644 --- a/app/Model/TaskLinkModel.php +++ b/app/Model/TaskLinkModel.php @@ -28,6 +28,22 @@ class TaskLinkModel extends Base */ const EVENT_CREATE_UPDATE = 'tasklink.create_update'; + /** + * Get projectId from $task_link_id + * + * @access public + * @param integer $task_link_id + * @return integer + */ + public function getProjectId($task_link_id) + { + return $this->db + ->table(self::TABLE) + ->eq(self::TABLE.'.id', $task_link_id) + ->join(TaskModel::TABLE, 'id', 'task_id') + ->findOneColumn(TaskModel::TABLE . '.project_id') ?: 0; + } + /** * Get a task link * diff --git a/app/ServiceProvider/ApiProvider.php b/app/ServiceProvider/ApiProvider.php index e0312056..f88d9b4f 100644 --- a/app/ServiceProvider/ApiProvider.php +++ b/app/ServiceProvider/ApiProvider.php @@ -3,26 +3,26 @@ namespace Kanboard\ServiceProvider; use JsonRPC\Server; -use Kanboard\Api\ActionApi; -use Kanboard\Api\AppApi; -use Kanboard\Api\BoardApi; -use Kanboard\Api\CategoryApi; -use Kanboard\Api\ColumnApi; -use Kanboard\Api\CommentApi; -use Kanboard\Api\TaskFileApi; -use Kanboard\Api\GroupApi; -use Kanboard\Api\GroupMemberApi; -use Kanboard\Api\LinkApi; -use Kanboard\Api\MeApi; -use Kanboard\Api\Middleware\AuthenticationApiMiddleware; -use Kanboard\Api\ProjectApi; -use Kanboard\Api\ProjectPermissionApi; -use Kanboard\Api\SubtaskApi; -use Kanboard\Api\SubtaskTimeTrackingApi; -use Kanboard\Api\SwimlaneApi; -use Kanboard\Api\TaskApi; -use Kanboard\Api\TaskLinkApi; -use Kanboard\Api\UserApi; +use Kanboard\Api\Procedure\ActionProcedure; +use Kanboard\Api\Procedure\AppProcedure; +use Kanboard\Api\Procedure\BoardProcedure; +use Kanboard\Api\Procedure\CategoryProcedure; +use Kanboard\Api\Procedure\ColumnProcedure; +use Kanboard\Api\Procedure\CommentProcedure; +use Kanboard\Api\Procedure\TaskFileProcedure; +use Kanboard\Api\Procedure\GroupProcedure; +use Kanboard\Api\Procedure\GroupMemberProcedure; +use Kanboard\Api\Procedure\LinkProcedure; +use Kanboard\Api\Procedure\MeProcedure; +use Kanboard\Api\Middleware\AuthenticationMiddleware; +use Kanboard\Api\Procedure\ProjectProcedure; +use Kanboard\Api\Procedure\ProjectPermissionProcedure; +use Kanboard\Api\Procedure\SubtaskProcedure; +use Kanboard\Api\Procedure\SubtaskTimeTrackingProcedure; +use Kanboard\Api\Procedure\SwimlaneProcedure; +use Kanboard\Api\Procedure\TaskProcedure; +use Kanboard\Api\Procedure\TaskLinkProcedure; +use Kanboard\Api\Procedure\UserProcedure; use Pimple\Container; use Pimple\ServiceProviderInterface; @@ -45,31 +45,32 @@ class ApiProvider implements ServiceProviderInterface $server = new Server(); $server->setAuthenticationHeader(API_AUTHENTICATION_HEADER); $server->getMiddlewareHandler() - ->withMiddleware(new AuthenticationApiMiddleware($container)) + ->withMiddleware(new AuthenticationMiddleware($container)) ; $server->getProcedureHandler() - ->withObject(new MeApi($container)) - ->withObject(new ActionApi($container)) - ->withObject(new AppApi($container)) - ->withObject(new BoardApi($container)) - ->withObject(new ColumnApi($container)) - ->withObject(new CategoryApi($container)) - ->withObject(new CommentApi($container)) - ->withObject(new TaskFileApi($container)) - ->withObject(new LinkApi($container)) - ->withObject(new ProjectApi($container)) - ->withObject(new ProjectPermissionApi($container)) - ->withObject(new SubtaskApi($container)) - ->withObject(new SubtaskTimeTrackingApi($container)) - ->withObject(new SwimlaneApi($container)) - ->withObject(new TaskApi($container)) - ->withObject(new TaskLinkApi($container)) - ->withObject(new UserApi($container)) - ->withObject(new GroupApi($container)) - ->withObject(new GroupMemberApi($container)) + ->withObject(new MeProcedure($container)) + ->withObject(new ActionProcedure($container)) + ->withObject(new AppProcedure($container)) + ->withObject(new BoardProcedure($container)) + ->withObject(new ColumnProcedure($container)) + ->withObject(new CategoryProcedure($container)) + ->withObject(new CommentProcedure($container)) + ->withObject(new TaskFileProcedure($container)) + ->withObject(new LinkProcedure($container)) + ->withObject(new ProjectProcedure($container)) + ->withObject(new ProjectPermissionProcedure($container)) + ->withObject(new SubtaskProcedure($container)) + ->withObject(new SubtaskTimeTrackingProcedure($container)) + ->withObject(new SwimlaneProcedure($container)) + ->withObject(new TaskProcedure($container)) + ->withObject(new TaskLinkProcedure($container)) + ->withObject(new UserProcedure($container)) + ->withObject(new GroupProcedure($container)) + ->withObject(new GroupMemberProcedure($container)) + ->withBeforeMethod('beforeProcedure') ; - + $container['api'] = $server; return $container; } diff --git a/app/ServiceProvider/AuthenticationProvider.php b/app/ServiceProvider/AuthenticationProvider.php index 84e4354d..751fe514 100644 --- a/app/ServiceProvider/AuthenticationProvider.php +++ b/app/ServiceProvider/AuthenticationProvider.php @@ -46,9 +46,13 @@ class AuthenticationProvider implements ServiceProviderInterface $container['projectAccessMap'] = $this->getProjectAccessMap(); $container['applicationAccessMap'] = $this->getApplicationAccessMap(); + $container['apiAccessMap'] = $this->getApiAccessMap(); + $container['apiProjectAccessMap'] = $this->getApiProjectAccessMap(); $container['projectAuthorization'] = new Authorization($container['projectAccessMap']); $container['applicationAuthorization'] = new Authorization($container['applicationAccessMap']); + $container['apiAuthorization'] = new Authorization($container['apiAccessMap']); + $container['apiProjectAuthorization'] = new Authorization($container['apiProjectAccessMap']); return $container; } @@ -151,4 +155,57 @@ class AuthenticationProvider implements ServiceProviderInterface return $acl; } + + /** + * Get ACL for the API + * + * @access public + * @return AccessMap + */ + public function getApiAccessMap() + { + $acl = new AccessMap; + $acl->setDefaultRole(Role::APP_USER); + $acl->setRoleHierarchy(Role::APP_ADMIN, array(Role::APP_MANAGER, Role::APP_USER, Role::APP_PUBLIC)); + $acl->setRoleHierarchy(Role::APP_MANAGER, array(Role::APP_USER, Role::APP_PUBLIC)); + + $acl->add('UserProcedure', '*', Role::APP_ADMIN); + $acl->add('GroupMemberProcedure', '*', Role::APP_ADMIN); + $acl->add('GroupProcedure', '*', Role::APP_ADMIN); + $acl->add('LinkProcedure', '*', Role::APP_ADMIN); + $acl->add('TaskProcedure', array('getOverdueTasks'), Role::APP_ADMIN); + $acl->add('ProjectProcedure', array('getAllProjects'), Role::APP_ADMIN); + $acl->add('ProjectProcedure', array('createProject'), Role::APP_MANAGER); + + return $acl; + } + + /** + * Get ACL for the API + * + * @access public + * @return AccessMap + */ + public function getApiProjectAccessMap() + { + $acl = new AccessMap; + $acl->setDefaultRole(Role::PROJECT_VIEWER); + $acl->setRoleHierarchy(Role::PROJECT_MANAGER, array(Role::PROJECT_MEMBER, Role::PROJECT_VIEWER)); + $acl->setRoleHierarchy(Role::PROJECT_MEMBER, array(Role::PROJECT_VIEWER)); + + $acl->add('ActionProcedure', array('removeAction', 'getActions', 'createAction'), Role::PROJECT_MANAGER); + $acl->add('CategoryProcedure', '*', Role::PROJECT_MANAGER); + $acl->add('ColumnProcedure', '*', Role::PROJECT_MANAGER); + $acl->add('CommentProcedure', array('removeComment', 'createComment', 'updateComment'), Role::PROJECT_MEMBER); + $acl->add('ProjectPermissionProcedure', '*', Role::PROJECT_MANAGER); + $acl->add('ProjectProcedure', array('updateProject', 'removeProject', 'enableProject', 'disableProject', 'enableProjectPublicAccess', 'disableProjectPublicAccess'), Role::PROJECT_MANAGER); + $acl->add('SubtaskProcedure', '*', Role::PROJECT_MEMBER); + $acl->add('SubtaskTimeTrackingProcedure', '*', Role::PROJECT_MEMBER); + $acl->add('SwimlaneProcedure', '*', Role::PROJECT_MANAGER); + $acl->add('TaskFileProcedure', '*', Role::PROJECT_MEMBER); + $acl->add('TaskLinkProcedure', '*', Role::PROJECT_MEMBER); + $acl->add('TaskProcedure', '*', Role::PROJECT_MEMBER); + + return $acl; + } } diff --git a/composer.json b/composer.json index 85fdb5ad..bcac020e 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "christian-riesen/otp" : "1.4", "eluceo/ical": "0.8.0", "erusev/parsedown" : "1.6.0", - "fguillot/json-rpc" : "1.2.0", + "fguillot/json-rpc" : "1.2.1", "fguillot/picodb" : "1.0.12", "fguillot/simpleLogger" : "1.0.1", "fguillot/simple-validator" : "1.0.0", diff --git a/composer.lock b/composer.lock index e0177ed5..e6a72582 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "2de2026649db7bc41653bef80f974c6a", - "content-hash": "ea8ef74f1f1cf53b9f96b7609d756873", + "hash": "283af0b856598f5bc3d8ee0b226959e5", + "content-hash": "18c0bbff5406ceb8b567d9655de26746", "packages": [ { "name": "christian-riesen/base32", @@ -203,16 +203,16 @@ }, { "name": "fguillot/json-rpc", - "version": "v1.2.0", + "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/fguillot/JsonRPC.git", - "reference": "b002320b10aa1eeb7aee83f7b703cd6a6e99ff78" + "reference": "d491bb549bfa11aff4c37abcea2ffb28c9523f69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fguillot/JsonRPC/zipball/b002320b10aa1eeb7aee83f7b703cd6a6e99ff78", - "reference": "b002320b10aa1eeb7aee83f7b703cd6a6e99ff78", + "url": "https://api.github.com/repos/fguillot/JsonRPC/zipball/d491bb549bfa11aff4c37abcea2ffb28c9523f69", + "reference": "d491bb549bfa11aff4c37abcea2ffb28c9523f69", "shasum": "" }, "require": { @@ -238,7 +238,7 @@ ], "description": "Simple Json-RPC client/server library that just works", "homepage": "https://github.com/fguillot/JsonRPC", - "time": "2016-05-29 13:06:36" + "time": "2016-06-25 23:11:10" }, { "name": "fguillot/picodb", @@ -682,16 +682,16 @@ }, { "name": "symfony/console", - "version": "v2.8.6", + "version": "v2.8.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "48221d3de4dc22d2cd57c97e8b9361821da86609" + "reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/48221d3de4dc22d2cd57c97e8b9361821da86609", - "reference": "48221d3de4dc22d2cd57c97e8b9361821da86609", + "url": "https://api.github.com/repos/symfony/console/zipball/5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3", + "reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3", "shasum": "" }, "require": { @@ -738,20 +738,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-04-26 12:00:47" + "time": "2016-06-06 15:06:25" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.6", + "version": "v2.8.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "a158f13992a3147d466af7a23b564ac719a4ddd8" + "reference": "2a6b8713f8bdb582058cfda463527f195b066110" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a158f13992a3147d466af7a23b564ac719a4ddd8", - "reference": "a158f13992a3147d466af7a23b564ac719a4ddd8", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2a6b8713f8bdb582058cfda463527f195b066110", + "reference": "2a6b8713f8bdb582058cfda463527f195b066110", "shasum": "" }, "require": { @@ -798,7 +798,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-05-03 18:59:18" + "time": "2016-06-06 11:11:27" }, { "name": "symfony/polyfill-mbstring", @@ -915,39 +915,136 @@ ], "time": "2015-06-14 21:17:01" }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2015-12-27 11:43:31" + }, { "name": "phpdocumentor/reflection-docblock", - "version": "2.0.4", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" + "reference": "9270140b940ff02e58ec577c237274e92cd40cdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9270140b940ff02e58ec577c237274e92cd40cdd", + "reference": "9270140b940ff02e58ec577c237274e92cd40cdd", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/type-resolver": "^0.2.0", + "webmozart/assert": "^1.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" }, - "suggest": { - "dflydev/markdown": "~1.0", - "erusev/parsedown": "~1.0" + "type": "library", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2016-06-10 09:48:41" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "phpDocumentor": [ + "psr-4": { + "phpDocumentor\\Reflection\\": [ "src/" ] } @@ -959,39 +1056,39 @@ "authors": [ { "name": "Mike van Riel", - "email": "mike.vanriel@naenius.com" + "email": "me@mikevanriel.com" } ], - "time": "2015-02-03 12:10:50" + "time": "2016-06-10 07:14:17" }, { "name": "phpspec/prophecy", - "version": "v1.6.0", + "version": "v1.6.1", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972" + "reference": "58a8137754bc24b25740d4281399a4a3596058e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972", - "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", + "reference": "58a8137754bc24b25740d4281399a4a3596058e0", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "~2.0", - "sebastian/comparator": "~1.1", - "sebastian/recursion-context": "~1.0" + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1", + "sebastian/recursion-context": "^1.0" }, "require-dev": { - "phpspec/phpspec": "~2.0" + "phpspec/phpspec": "^2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.5.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { @@ -1024,7 +1121,7 @@ "spy", "stub" ], - "time": "2016-02-15 07:46:21" + "time": "2016-06-07 08:13:47" }, { "name": "phpunit/php-code-coverage", @@ -1629,16 +1726,16 @@ }, { "name": "sebastian/exporter", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e" + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", "shasum": "" }, "require": { @@ -1646,12 +1743,13 @@ "sebastian/recursion-context": "~1.0" }, "require-dev": { + "ext-mbstring": "*", "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { @@ -1691,7 +1789,7 @@ "export", "exporter" ], - "time": "2015-06-21 07:55:53" + "time": "2016-06-17 09:04:28" }, { "name": "sebastian/global-state", @@ -1834,16 +1932,16 @@ }, { "name": "symfony/stopwatch", - "version": "v2.8.6", + "version": "v2.8.7", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "9e24824b2a9a16e17ab997f61d70bc03948e434e" + "reference": "5e628055488bcc42dbace3af65be435d094e37e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/9e24824b2a9a16e17ab997f61d70bc03948e434e", - "reference": "9e24824b2a9a16e17ab997f61d70bc03948e434e", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5e628055488bcc42dbace3af65be435d094e37e4", + "reference": "5e628055488bcc42dbace3af65be435d094e37e4", "shasum": "" }, "require": { @@ -1879,7 +1977,7 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2016-03-04 07:54:35" + "time": "2016-06-06 11:11:27" }, { "name": "symfony/yaml", @@ -1927,6 +2025,55 @@ "description": "Symfony Yaml Component", "homepage": "http://symfony.com", "time": "2012-08-22 13:48:41" + }, + { + "name": "webmozart/assert", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", + "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2015-08-24 13:29:44" } ], "aliases": [], diff --git a/doc/api-authentication.markdown b/doc/api-authentication.markdown index 962e5b1b..3ba1e8f5 100644 --- a/doc/api-authentication.markdown +++ b/doc/api-authentication.markdown @@ -1,48 +1,26 @@ API Authentication ================== -Default method (HTTP Basic) ---------------------------- +API endpoint +------------ + +URL: `https://YOUR_SERVER/jsonrpc.php` -The API credentials are available on the settings page. -- API end-point: `https://YOUR_SERVER/jsonrpc.php` +Default method (HTTP Basic) +--------------------------- -If you want to use the "application api": +### Application credentials - Username: `jsonrpc` - Password: API token on the settings page -Otherwise for the "user api", just use the real username/passsword. +### User credentials + +- Use the real username and password The API use the [HTTP Basic Authentication Scheme described in the RFC2617](http://www.ietf.org/rfc/rfc2617.txt). -If there is an authentication error, you will receive the HTTP status code `401 Not Authorized`. - -### Authorized User API procedures - -- getMe -- getMyDashboard -- getMyActivityStream -- createMyPrivateProject -- getMyProjectsList -- getMyProjects -- getTimezone -- getVersion -- getDefaultTaskColor -- getDefaultTaskColors -- getColorList -- getProjectById -- getTask -- getTaskByReference -- getAllTasks -- openTask -- closeTask -- moveTaskPosition -- createTask -- updateTask -- getBoard -- getProjectActivity -- getMyOverdueTasks + Custom HTTP header ------------------ @@ -64,3 +42,14 @@ curl \ -d '{"jsonrpc": "2.0", "method": "getAllProjects", "id": 1}' \ http://localhost/kanboard/jsonrpc.php ``` + +Authentication error +-------------------- + +If the credentials are wrong, you will receive a `401 Not Authorized` and the corresponding JSON response. + + +Authorization error +------------------- + +If the connected user is not allowed to access to the resource, you will receive a `403 Forbidden`. diff --git a/doc/api-json-rpc.markdown b/doc/api-json-rpc.markdown index bb14b008..0f922a7c 100644 --- a/doc/api-json-rpc.markdown +++ b/doc/api-json-rpc.markdown @@ -8,25 +8,25 @@ There are two types of API access: ### Application API -- Access to the API with the user "jsonrpc" and the token available in settings +- Access to the API with the user "jsonrpc" and the token available on the settings page - Access to all procedures - No permission checked - There is no user session on the server +- No access to procedures that starts with "My..." (example: "getMe" or "getMyProjects") - Example of possible clients: tools to migrate/import data, create tasks from another system, etc... ### User API - Access to the API with the user credentials (username and password) -- Access to a restricted set of procedures -- The project permissions are checked +- Application role and project permissions are checked for each procedure - A user session is created on the server -- Example of possible clients: mobile/desktop application, command line utility, etc... +- Example of possible clients: native mobile/desktop application, command line utility, etc... Security -------- -- Always use HTTPS with a valid certificate -- If you make a mobile application, it's your job to store securely the user credentials on the device +- Always use HTTPS with a valid certificate (avoid clear text communication) +- If you make a mobile application, it's your responsability to store securely the user credentials on the device - After 3 authentication failure on the user api, the end-user have to unlock his account by using the login form - Two factor authentication is not yet available through the API diff --git a/doc/api-project-permission-procedures.markdown b/doc/api-project-permission-procedures.markdown index 2844ae3c..d5e9b066 100644 --- a/doc/api-project-permission-procedures.markdown +++ b/doc/api-project-permission-procedures.markdown @@ -272,3 +272,36 @@ Response example: "result": true } ``` + +## getProjectUserRole + +- Purpose: **Get the role of a user for a given project** +- Parameters: + - **project_id** (integer, required) + - **user_id** (integer, required) +- Result on success: **role name** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "getProjectUserRole", + "id": 2114673298, + "params": [ + "2", + "3" + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 2114673298, + "result": "project-viewer" +} +``` diff --git a/doc/api-project-procedures.markdown b/doc/api-project-procedures.markdown index f8e2cc5e..3f8d33c2 100644 --- a/doc/api-project-procedures.markdown +++ b/doc/api-project-procedures.markdown @@ -7,6 +7,8 @@ API Project Procedures - Parameters: - **name** (string, required) - **description** (string, optional) + - **owner_id** (integer, optional) + - **identifier** (string, optional) - Result on success: **project_id** - Result on failure: **false** @@ -186,6 +188,8 @@ Response example: - **project_id** (integer, required) - **name** (string, required) - **description** (string, optional) + - **owner_id** (integer, optional) + - **identifier** (string, optional) - Result on success: **true** - Result on failure: **false** diff --git a/tests/integration/ActionProcedureTest.php b/tests/integration/ActionProcedureTest.php new file mode 100644 index 00000000..432de3d3 --- /dev/null +++ b/tests/integration/ActionProcedureTest.php @@ -0,0 +1,66 @@ +app->getAvailableActions(); + $this->assertNotEmpty($actions); + $this->assertInternalType('array', $actions); + $this->assertArrayHasKey('\Kanboard\Action\TaskCloseColumn', $actions); + } + + public function testGetAvailableActionEvents() + { + $events = $this->app->getAvailableActionEvents(); + $this->assertNotEmpty($events); + $this->assertInternalType('array', $events); + $this->assertArrayHasKey('task.move.column', $events); + } + + public function testGetCompatibleActionEvents() + { + $events = $this->app->getCompatibleActionEvents('\Kanboard\Action\TaskCloseColumn'); + $this->assertNotEmpty($events); + $this->assertInternalType('array', $events); + $this->assertArrayHasKey('task.move.column', $events); + } + + public function testCRUD() + { + $this->assertCreateTeamProject(); + $this->assertCreateAction(); + $this->assertGetActions(); + $this->assertRemoveAction(); + } + + public function assertCreateAction() + { + $actionId = $this->app->createAction($this->projectId, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1)); + $this->assertNotFalse($actionId); + $this->assertTrue($actionId > 0); + } + + public function assertGetActions() + { + $actions = $this->app->getActions($this->projectId); + $this->assertNotEmpty($actions); + $this->assertInternalType('array', $actions); + $this->assertArrayHasKey('id', $actions[0]); + $this->assertArrayHasKey('project_id', $actions[0]); + $this->assertArrayHasKey('event_name', $actions[0]); + $this->assertArrayHasKey('action_name', $actions[0]); + $this->assertArrayHasKey('params', $actions[0]); + $this->assertArrayHasKey('column_id', $actions[0]['params']); + } + + public function assertRemoveAction() + { + $actionId = $this->app->createAction($this->projectId, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1)); + $this->assertTrue($this->app->removeAction($actionId)); + } +} diff --git a/tests/integration/ActionTest.php b/tests/integration/ActionTest.php deleted file mode 100644 index 7a5adc4a..00000000 --- a/tests/integration/ActionTest.php +++ /dev/null @@ -1,66 +0,0 @@ -app->getAvailableActions(); - $this->assertNotEmpty($actions); - $this->assertInternalType('array', $actions); - $this->assertArrayHasKey('\Kanboard\Action\TaskCloseColumn', $actions); - } - - public function testGetAvailableActionEvents() - { - $events = $this->app->getAvailableActionEvents(); - $this->assertNotEmpty($events); - $this->assertInternalType('array', $events); - $this->assertArrayHasKey('task.move.column', $events); - } - - public function testGetCompatibleActionEvents() - { - $events = $this->app->getCompatibleActionEvents('\Kanboard\Action\TaskCloseColumn'); - $this->assertNotEmpty($events); - $this->assertInternalType('array', $events); - $this->assertArrayHasKey('task.move.column', $events); - } - - public function testCRUD() - { - $this->assertCreateTeamProject(); - $this->assertCreateAction(); - $this->assertGetActions(); - $this->assertRemoveAction(); - } - - public function assertCreateAction() - { - $actionId = $this->app->createAction($this->projectId, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1)); - $this->assertNotFalse($actionId); - $this->assertTrue($actionId > 0); - } - - public function assertGetActions() - { - $actions = $this->app->getActions($this->projectId); - $this->assertNotEmpty($actions); - $this->assertInternalType('array', $actions); - $this->assertArrayHasKey('id', $actions[0]); - $this->assertArrayHasKey('project_id', $actions[0]); - $this->assertArrayHasKey('event_name', $actions[0]); - $this->assertArrayHasKey('action_name', $actions[0]); - $this->assertArrayHasKey('params', $actions[0]); - $this->assertArrayHasKey('column_id', $actions[0]['params']); - } - - public function assertRemoveAction() - { - $actionId = $this->app->createAction($this->projectId, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1)); - $this->assertTrue($this->app->removeAction($actionId)); - } -} diff --git a/tests/integration/AppProcedureTest.php b/tests/integration/AppProcedureTest.php new file mode 100644 index 00000000..06135dac --- /dev/null +++ b/tests/integration/AppProcedureTest.php @@ -0,0 +1,54 @@ +assertEquals('UTC', $this->app->getTimezone()); + } + + public function testGetVersion() + { + $this->assertEquals('master', $this->app->getVersion()); + } + + public function testGetApplicationRoles() + { + $roles = $this->app->getApplicationRoles(); + $this->assertCount(3, $roles); + $this->assertEquals('Administrator', $roles['app-admin']); + $this->assertEquals('Manager', $roles['app-manager']); + $this->assertEquals('User', $roles['app-user']); + } + + public function testGetProjectRoles() + { + $roles = $this->app->getProjectRoles(); + $this->assertCount(3, $roles); + $this->assertEquals('Project Manager', $roles['project-manager']); + $this->assertEquals('Project Member', $roles['project-member']); + $this->assertEquals('Project Viewer', $roles['project-viewer']); + } + + public function testGetDefaultColor() + { + $this->assertEquals('yellow', $this->user->getDefaultTaskColor()); + } + + public function testGetDefaultColors() + { + $colors = $this->user->getDefaultTaskColors(); + $this->assertNotEmpty($colors); + $this->assertArrayHasKey('red', $colors); + } + + public function testGetColorList() + { + $colors = $this->user->getColorList(); + $this->assertNotEmpty($colors); + $this->assertArrayHasKey('red', $colors); + $this->assertEquals('Red', $colors['red']); + } +} diff --git a/tests/integration/AppTest.php b/tests/integration/AppTest.php deleted file mode 100644 index 287e6299..00000000 --- a/tests/integration/AppTest.php +++ /dev/null @@ -1,54 +0,0 @@ -assertEquals('UTC', $this->app->getTimezone()); - } - - public function testGetVersion() - { - $this->assertEquals('master', $this->app->getVersion()); - } - - public function testGetApplicationRoles() - { - $roles = $this->app->getApplicationRoles(); - $this->assertCount(3, $roles); - $this->assertEquals('Administrator', $roles['app-admin']); - $this->assertEquals('Manager', $roles['app-manager']); - $this->assertEquals('User', $roles['app-user']); - } - - public function testGetProjectRoles() - { - $roles = $this->app->getProjectRoles(); - $this->assertCount(3, $roles); - $this->assertEquals('Project Manager', $roles['project-manager']); - $this->assertEquals('Project Member', $roles['project-member']); - $this->assertEquals('Project Viewer', $roles['project-viewer']); - } - - public function testGetDefaultColor() - { - $this->assertEquals('yellow', $this->user->getDefaultTaskColor()); - } - - public function testGetDefaultColors() - { - $colors = $this->user->getDefaultTaskColors(); - $this->assertNotEmpty($colors); - $this->assertArrayHasKey('red', $colors); - } - - public function testGetColorList() - { - $colors = $this->user->getColorList(); - $this->assertNotEmpty($colors); - $this->assertArrayHasKey('red', $colors); - $this->assertEquals('Red', $colors['red']); - } -} diff --git a/tests/integration/BaseIntegrationTest.php b/tests/integration/BaseIntegrationTest.php deleted file mode 100644 index cd837173..00000000 --- a/tests/integration/BaseIntegrationTest.php +++ /dev/null @@ -1,122 +0,0 @@ -setUpAppClient(); - $this->setUpAdminUser(); - $this->setUpManagerUser(); - $this->setUpStandardUser(); - } - - public function setUpAppClient() - { - $this->app = new JsonRPC\Client(API_URL); - $this->app->authentication('jsonrpc', API_KEY); - $this->app->getHttpClient()->withDebug()->withTimeout(10); - } - - public function setUpAdminUser() - { - $this->adminUserId = $this->getUserId('superuser'); - - if (! $this->adminUserId) { - $this->adminUserId = $this->app->createUser('superuser', 'password', 'Admin User', 'user@localhost', 'app-admin'); - $this->assertNotFalse($this->adminUserId); - } - - $this->admin = new JsonRPC\Client(API_URL); - $this->admin->authentication('superuser', 'password'); - $this->admin->getHttpClient()->withDebug(); - } - - public function setUpManagerUser() - { - $this->managerUserId = $this->getUserId('manager'); - - if (! $this->managerUserId) { - $this->managerUserId = $this->app->createUser('manager', 'password', 'Manager User', 'user@localhost', 'app-manager'); - $this->assertNotFalse($this->managerUserId); - } - - $this->manager = new JsonRPC\Client(API_URL); - $this->manager->authentication('manager', 'password'); - $this->manager->getHttpClient()->withDebug(); - } - - public function setUpStandardUser() - { - $this->userUserId = $this->getUserId('user'); - - if (! $this->userUserId) { - $this->userUserId = $this->app->createUser('user', 'password', 'Standard User', 'user@localhost', 'app-user'); - $this->assertNotFalse($this->userUserId); - } - - $this->user = new JsonRPC\Client(API_URL); - $this->user->authentication('user', 'password'); - $this->user->getHttpClient()->withDebug(); - } - - public function getUserId($username) - { - $user = $this->app->getUserByName($username); - - if (! empty($user)) { - return $user['id']; - } - - return 0; - } - - public function assertCreateTeamProject() - { - $this->projectId = $this->app->createProject($this->projectName, 'Description'); - $this->assertNotFalse($this->projectId); - } - - public function assertCreateUser() - { - $this->userId = $this->app->createUser($this->username, 'password'); - $this->assertNotFalse($this->userId); - } - - public function assertCreateGroups() - { - $this->groupId1 = $this->app->createGroup($this->groupName1); - $this->groupId2 = $this->app->createGroup($this->groupName2, 'External ID'); - $this->assertNotFalse($this->groupId1); - $this->assertNotFalse($this->groupId2); - } - - public function assertCreateTask() - { - $this->taskId = $this->app->createTask(array('title' => $this->taskTitle, 'project_id' => $this->projectId)); - $this->assertNotFalse($this->taskId); - } -} diff --git a/tests/integration/BaseProcedureTest.php b/tests/integration/BaseProcedureTest.php new file mode 100644 index 00000000..e3382e82 --- /dev/null +++ b/tests/integration/BaseProcedureTest.php @@ -0,0 +1,122 @@ +setUpAppClient(); + $this->setUpAdminUser(); + $this->setUpManagerUser(); + $this->setUpStandardUser(); + } + + public function setUpAppClient() + { + $this->app = new JsonRPC\Client(API_URL); + $this->app->authentication('jsonrpc', API_KEY); + $this->app->getHttpClient()->withDebug()->withTimeout(10); + } + + public function setUpAdminUser() + { + $this->adminUserId = $this->getUserId('superuser'); + + if (! $this->adminUserId) { + $this->adminUserId = $this->app->createUser('superuser', 'password', 'Admin User', 'user@localhost', 'app-admin'); + $this->assertNotFalse($this->adminUserId); + } + + $this->admin = new JsonRPC\Client(API_URL); + $this->admin->authentication('superuser', 'password'); + $this->admin->getHttpClient()->withDebug(); + } + + public function setUpManagerUser() + { + $this->managerUserId = $this->getUserId('manager'); + + if (! $this->managerUserId) { + $this->managerUserId = $this->app->createUser('manager', 'password', 'Manager User', 'user@localhost', 'app-manager'); + $this->assertNotFalse($this->managerUserId); + } + + $this->manager = new JsonRPC\Client(API_URL); + $this->manager->authentication('manager', 'password'); + $this->manager->getHttpClient()->withDebug(); + } + + public function setUpStandardUser() + { + $this->userUserId = $this->getUserId('user'); + + if (! $this->userUserId) { + $this->userUserId = $this->app->createUser('user', 'password', 'Standard User', 'user@localhost', 'app-user'); + $this->assertNotFalse($this->userUserId); + } + + $this->user = new JsonRPC\Client(API_URL); + $this->user->authentication('user', 'password'); + $this->user->getHttpClient()->withDebug(); + } + + public function getUserId($username) + { + $user = $this->app->getUserByName($username); + + if (! empty($user)) { + return $user['id']; + } + + return 0; + } + + public function assertCreateTeamProject() + { + $this->projectId = $this->app->createProject($this->projectName, 'Description'); + $this->assertNotFalse($this->projectId); + } + + public function assertCreateUser() + { + $this->userId = $this->app->createUser($this->username, 'password'); + $this->assertNotFalse($this->userId); + } + + public function assertCreateGroups() + { + $this->groupId1 = $this->app->createGroup($this->groupName1); + $this->groupId2 = $this->app->createGroup($this->groupName2, 'External ID'); + $this->assertNotFalse($this->groupId1); + $this->assertNotFalse($this->groupId2); + } + + public function assertCreateTask() + { + $this->taskId = $this->app->createTask(array('title' => $this->taskTitle, 'project_id' => $this->projectId)); + $this->assertNotFalse($this->taskId); + } +} diff --git a/tests/integration/BoardProcedureTest.php b/tests/integration/BoardProcedureTest.php new file mode 100644 index 00000000..273e93c7 --- /dev/null +++ b/tests/integration/BoardProcedureTest.php @@ -0,0 +1,25 @@ +assertCreateTeamProject(); + $this->assertGetBoard(); + } + + public function assertGetBoard() + { + $board = $this->app->getBoard($this->projectId); + $this->assertNotNull($board); + $this->assertCount(1, $board); + $this->assertEquals('Default swimlane', $board[0]['name']); + + $this->assertCount(4, $board[0]['columns']); + $this->assertEquals('Ready', $board[0]['columns'][1]['title']); + } +} diff --git a/tests/integration/BoardTest.php b/tests/integration/BoardTest.php deleted file mode 100644 index aa0f61ff..00000000 --- a/tests/integration/BoardTest.php +++ /dev/null @@ -1,25 +0,0 @@ -assertCreateTeamProject(); - $this->assertGetBoard(); - } - - public function assertGetBoard() - { - $board = $this->app->getBoard($this->projectId); - $this->assertNotNull($board); - $this->assertCount(1, $board); - $this->assertEquals('Default swimlane', $board[0]['name']); - - $this->assertCount(4, $board[0]['columns']); - $this->assertEquals('Ready', $board[0]['columns'][1]['title']); - } -} diff --git a/tests/integration/CategoryProcedureTest.php b/tests/integration/CategoryProcedureTest.php new file mode 100644 index 00000000..2f5294ba --- /dev/null +++ b/tests/integration/CategoryProcedureTest.php @@ -0,0 +1,76 @@ +assertCreateTeamProject(); + $this->assertCreateCategory(); + $this->assertThatCategoriesAreUnique(); + $this->assertGetCategory(); + $this->assertGetAllCategories(); + $this->assertCategoryUpdate(); + $this->assertRemoveCategory(); + } + + public function assertCreateCategory() + { + $this->categoryId = $this->app->createCategory(array( + 'name' => 'Category', + 'project_id' => $this->projectId, + )); + + $this->assertNotFalse($this->categoryId); + } + + public function assertThatCategoriesAreUnique() + { + $this->assertFalse($this->app->execute('createCategory', array( + 'name' => 'Category', + 'project_id' => $this->projectId, + ))); + } + + public function assertGetCategory() + { + $category = $this->app->getCategory($this->categoryId); + + $this->assertInternalType('array', $category); + $this->assertEquals($this->categoryId, $category['id']); + $this->assertEquals('Category', $category['name']); + $this->assertEquals($this->projectId, $category['project_id']); + } + + public function assertGetAllCategories() + { + $categories = $this->app->getAllCategories($this->projectId); + + $this->assertCount(1, $categories); + $this->assertEquals($this->categoryId, $categories[0]['id']); + $this->assertEquals('Category', $categories[0]['name']); + $this->assertEquals($this->projectId, $categories[0]['project_id']); + } + + public function assertCategoryUpdate() + { + $this->assertTrue($this->app->execute('updateCategory', array( + 'id' => $this->categoryId, + 'name' => 'Renamed category', + ))); + + $category = $this->app->getCategory($this->categoryId); + $this->assertEquals('Renamed category', $category['name']); + } + + public function assertRemoveCategory() + { + $this->assertTrue($this->app->removeCategory($this->categoryId)); + $this->assertFalse($this->app->removeCategory($this->categoryId)); + $this->assertFalse($this->app->removeCategory(1111)); + } +} diff --git a/tests/integration/CategoryTest.php b/tests/integration/CategoryTest.php deleted file mode 100644 index c1aec0bc..00000000 --- a/tests/integration/CategoryTest.php +++ /dev/null @@ -1,76 +0,0 @@ -assertCreateTeamProject(); - $this->assertCreateCategory(); - $this->assertThatCategoriesAreUnique(); - $this->assertGetCategory(); - $this->assertGetAllCategories(); - $this->assertCategoryUpdate(); - $this->assertRemoveCategory(); - } - - public function assertCreateCategory() - { - $this->categoryId = $this->app->createCategory(array( - 'name' => 'Category', - 'project_id' => $this->projectId, - )); - - $this->assertNotFalse($this->categoryId); - } - - public function assertThatCategoriesAreUnique() - { - $this->assertFalse($this->app->execute('createCategory', array( - 'name' => 'Category', - 'project_id' => $this->projectId, - ))); - } - - public function assertGetCategory() - { - $category = $this->app->getCategory($this->categoryId); - - $this->assertInternalType('array', $category); - $this->assertEquals($this->categoryId, $category['id']); - $this->assertEquals('Category', $category['name']); - $this->assertEquals($this->projectId, $category['project_id']); - } - - public function assertGetAllCategories() - { - $categories = $this->app->getAllCategories($this->projectId); - - $this->assertCount(1, $categories); - $this->assertEquals($this->categoryId, $categories[0]['id']); - $this->assertEquals('Category', $categories[0]['name']); - $this->assertEquals($this->projectId, $categories[0]['project_id']); - } - - public function assertCategoryUpdate() - { - $this->assertTrue($this->app->execute('updateCategory', array( - 'id' => $this->categoryId, - 'name' => 'Renamed category', - ))); - - $category = $this->app->getCategory($this->categoryId); - $this->assertEquals('Renamed category', $category['name']); - } - - public function assertRemoveCategory() - { - $this->assertTrue($this->app->removeCategory($this->categoryId)); - $this->assertFalse($this->app->removeCategory($this->categoryId)); - $this->assertFalse($this->app->removeCategory(1111)); - } -} diff --git a/tests/integration/ColumnProcedureTest.php b/tests/integration/ColumnProcedureTest.php new file mode 100644 index 00000000..fb6a27c3 --- /dev/null +++ b/tests/integration/ColumnProcedureTest.php @@ -0,0 +1,69 @@ +assertCreateTeamProject(); + $this->assertGetColumns(); + $this->assertUpdateColumn(); + $this->assertAddColumn(); + $this->assertRemoveColumn(); + $this->assertChangeColumnPosition(); + } + + public function assertGetColumns() + { + $this->columns = $this->app->getColumns($this->projectId); + $this->assertCount(4, $this->columns); + $this->assertEquals('Done', $this->columns[3]['title']); + } + + public function assertUpdateColumn() + { + $this->assertTrue($this->app->updateColumn($this->columns[3]['id'], 'Another column', 2)); + + $this->columns = $this->app->getColumns($this->projectId); + $this->assertEquals('Another column', $this->columns[3]['title']); + $this->assertEquals(2, $this->columns[3]['task_limit']); + } + + public function assertAddColumn() + { + $column_id = $this->app->addColumn($this->projectId, 'New column'); + $this->assertNotFalse($column_id); + $this->assertTrue($column_id > 0); + + $this->columns = $this->app->getColumns($this->projectId); + $this->assertCount(5, $this->columns); + $this->assertEquals('New column', $this->columns[4]['title']); + } + + public function assertRemoveColumn() + { + $this->assertTrue($this->app->removeColumn($this->columns[3]['id'])); + + $this->columns = $this->app->getColumns($this->projectId); + $this->assertCount(4, $this->columns); + } + + public function assertChangeColumnPosition() + { + $this->assertTrue($this->app->changeColumnPosition($this->projectId, $this->columns[0]['id'], 3)); + + $this->columns = $this->app->getColumns($this->projectId); + $this->assertEquals('Ready', $this->columns[0]['title']); + $this->assertEquals(1, $this->columns[0]['position']); + $this->assertEquals('Work in progress', $this->columns[1]['title']); + $this->assertEquals(2, $this->columns[1]['position']); + $this->assertEquals('Backlog', $this->columns[2]['title']); + $this->assertEquals(3, $this->columns[2]['position']); + $this->assertEquals('New column', $this->columns[3]['title']); + $this->assertEquals(4, $this->columns[3]['position']); + } +} diff --git a/tests/integration/ColumnTest.php b/tests/integration/ColumnTest.php deleted file mode 100644 index 5a81badc..00000000 --- a/tests/integration/ColumnTest.php +++ /dev/null @@ -1,69 +0,0 @@ -assertCreateTeamProject(); - $this->assertGetColumns(); - $this->assertUpdateColumn(); - $this->assertAddColumn(); - $this->assertRemoveColumn(); - $this->assertChangeColumnPosition(); - } - - public function assertGetColumns() - { - $this->columns = $this->app->getColumns($this->projectId); - $this->assertCount(4, $this->columns); - $this->assertEquals('Done', $this->columns[3]['title']); - } - - public function assertUpdateColumn() - { - $this->assertTrue($this->app->updateColumn($this->columns[3]['id'], 'Another column', 2)); - - $this->columns = $this->app->getColumns($this->projectId); - $this->assertEquals('Another column', $this->columns[3]['title']); - $this->assertEquals(2, $this->columns[3]['task_limit']); - } - - public function assertAddColumn() - { - $column_id = $this->app->addColumn($this->projectId, 'New column'); - $this->assertNotFalse($column_id); - $this->assertTrue($column_id > 0); - - $this->columns = $this->app->getColumns($this->projectId); - $this->assertCount(5, $this->columns); - $this->assertEquals('New column', $this->columns[4]['title']); - } - - public function assertRemoveColumn() - { - $this->assertTrue($this->app->removeColumn($this->columns[3]['id'])); - - $this->columns = $this->app->getColumns($this->projectId); - $this->assertCount(4, $this->columns); - } - - public function assertChangeColumnPosition() - { - $this->assertTrue($this->app->changeColumnPosition($this->projectId, $this->columns[0]['id'], 3)); - - $this->columns = $this->app->getColumns($this->projectId); - $this->assertEquals('Ready', $this->columns[0]['title']); - $this->assertEquals(1, $this->columns[0]['position']); - $this->assertEquals('Work in progress', $this->columns[1]['title']); - $this->assertEquals(2, $this->columns[1]['position']); - $this->assertEquals('Backlog', $this->columns[2]['title']); - $this->assertEquals(3, $this->columns[2]['position']); - $this->assertEquals('New column', $this->columns[3]['title']); - $this->assertEquals(4, $this->columns[3]['position']); - } -} diff --git a/tests/integration/CommentProcedureTest.php b/tests/integration/CommentProcedureTest.php new file mode 100644 index 00000000..881d938c --- /dev/null +++ b/tests/integration/CommentProcedureTest.php @@ -0,0 +1,63 @@ +assertCreateTeamProject(); + $this->assertCreateTask(); + $this->assertCreateComment(); + $this->assertUpdateComment(); + $this->assertGetAllComments(); + $this->assertRemoveComment(); + } + + public function assertCreateComment() + { + $this->commentId = $this->app->execute('createComment', array( + 'task_id' => $this->taskId, + 'user_id' => 1, + 'content' => 'foobar', + )); + + $this->assertNotFalse($this->commentId); + } + + public function assertGetComment() + { + $comment = $this->app->getComment($this->commentId); + $this->assertNotFalse($comment); + $this->assertNotEmpty($comment); + $this->assertEquals(1, $comment['user_id']); + $this->assertEquals('foobar', $comment['comment']); + } + + public function assertUpdateComment() + { + $this->assertTrue($this->app->execute('updateComment', array( + 'id' => $this->commentId, + 'content' => 'test', + ))); + + $comment = $this->app->getComment($this->commentId); + $this->assertEquals('test', $comment['comment']); + } + + public function assertGetAllComments() + { + $comments = $this->app->getAllComments($this->taskId); + $this->assertCount(1, $comments); + $this->assertEquals('test', $comments[0]['comment']); + } + + public function assertRemoveComment() + { + $this->assertTrue($this->app->removeComment($this->commentId)); + $this->assertFalse($this->app->removeComment($this->commentId)); + } +} diff --git a/tests/integration/CommentTest.php b/tests/integration/CommentTest.php deleted file mode 100644 index 34376838..00000000 --- a/tests/integration/CommentTest.php +++ /dev/null @@ -1,63 +0,0 @@ -assertCreateTeamProject(); - $this->assertCreateTask(); - $this->assertCreateComment(); - $this->assertUpdateComment(); - $this->assertGetAllComments(); - $this->assertRemoveComment(); - } - - public function assertCreateComment() - { - $this->commentId = $this->app->execute('createComment', array( - 'task_id' => $this->taskId, - 'user_id' => 1, - 'content' => 'foobar', - )); - - $this->assertNotFalse($this->commentId); - } - - public function assertGetComment() - { - $comment = $this->app->getComment($this->commentId); - $this->assertNotFalse($comment); - $this->assertNotEmpty($comment); - $this->assertEquals(1, $comment['user_id']); - $this->assertEquals('foobar', $comment['comment']); - } - - public function assertUpdateComment() - { - $this->assertTrue($this->app->execute('updateComment', array( - 'id' => $this->commentId, - 'content' => 'test', - ))); - - $comment = $this->app->getComment($this->commentId); - $this->assertEquals('test', $comment['comment']); - } - - public function assertGetAllComments() - { - $comments = $this->app->getAllComments($this->taskId); - $this->assertCount(1, $comments); - $this->assertEquals('test', $comments[0]['comment']); - } - - public function assertRemoveComment() - { - $this->assertTrue($this->app->removeComment($this->commentId)); - $this->assertFalse($this->app->removeComment($this->commentId)); - } -} diff --git a/tests/integration/GroupMemberProcedureTest.php b/tests/integration/GroupMemberProcedureTest.php new file mode 100644 index 00000000..fe243533 --- /dev/null +++ b/tests/integration/GroupMemberProcedureTest.php @@ -0,0 +1,53 @@ +assertCreateGroups(); + $this->assertCreateUser(); + $this->assertAddMember(); + $this->assertGetMembers(); + $this->assertIsGroupMember(); + $this->assertGetGroups(); + $this->assertRemove(); + } + + public function assertAddMember() + { + $this->assertTrue($this->app->addGroupMember($this->groupId1, $this->userId)); + } + + public function assertGetMembers() + { + $members = $this->app->getGroupMembers($this->groupId1); + $this->assertCount(1, $members); + $this->assertEquals($this->username, $members[0]['username']); + } + + public function assertIsGroupMember() + { + $this->assertTrue($this->app->isGroupMember($this->groupId1, $this->userId)); + $this->assertFalse($this->app->isGroupMember($this->groupId1, $this->adminUserId)); + } + + public function assertGetGroups() + { + $groups = $this->app->getMemberGroups($this->userId); + $this->assertCount(1, $groups); + $this->assertEquals($this->groupId1, $groups[0]['id']); + $this->assertEquals($this->groupName1, $groups[0]['name']); + } + + public function assertRemove() + { + $this->assertTrue($this->app->removeGroupMember($this->groupId1, $this->userId)); + $this->assertFalse($this->app->isGroupMember($this->groupId1, $this->userId)); + } +} diff --git a/tests/integration/GroupMemberTest.php b/tests/integration/GroupMemberTest.php deleted file mode 100644 index f79499a4..00000000 --- a/tests/integration/GroupMemberTest.php +++ /dev/null @@ -1,53 +0,0 @@ -assertCreateGroups(); - $this->assertCreateUser(); - $this->assertAddMember(); - $this->assertGetMembers(); - $this->assertIsGroupMember(); - $this->assertGetGroups(); - $this->assertRemove(); - } - - public function assertAddMember() - { - $this->assertTrue($this->app->addGroupMember($this->groupId1, $this->userId)); - } - - public function assertGetMembers() - { - $members = $this->app->getGroupMembers($this->groupId1); - $this->assertCount(1, $members); - $this->assertEquals($this->username, $members[0]['username']); - } - - public function assertIsGroupMember() - { - $this->assertTrue($this->app->isGroupMember($this->groupId1, $this->userId)); - $this->assertFalse($this->app->isGroupMember($this->groupId1, $this->adminUserId)); - } - - public function assertGetGroups() - { - $groups = $this->app->getMemberGroups($this->userId); - $this->assertCount(1, $groups); - $this->assertEquals($this->groupId1, $groups[0]['id']); - $this->assertEquals($this->groupName1, $groups[0]['name']); - } - - public function assertRemove() - { - $this->assertTrue($this->app->removeGroupMember($this->groupId1, $this->userId)); - $this->assertFalse($this->app->isGroupMember($this->groupId1, $this->userId)); - } -} diff --git a/tests/integration/GroupProcedureTest.php b/tests/integration/GroupProcedureTest.php new file mode 100644 index 00000000..610c121d --- /dev/null +++ b/tests/integration/GroupProcedureTest.php @@ -0,0 +1,50 @@ +assertCreateGroups(); + $this->assertGetAllGroups(); + $this->assertGetGroup(); + $this->assertUpdateGroup(); + $this->assertRemove(); + } + + public function assertGetAllGroups() + { + $groups = $this->app->getAllGroups(); + $this->assertNotEmpty($groups); + $this->assertArrayHasKey('name', $groups[0]); + $this->assertArrayHasKey('external_id', $groups[0]); + } + + public function assertGetGroup() + { + $group = $this->app->getGroup($this->groupId1); + $this->assertNotEmpty($group); + $this->assertEquals($this->groupName1, $group['name']); + $this->assertEquals('', $group['external_id']); + } + + public function assertUpdateGroup() + { + $this->assertTrue($this->app->updateGroup(array( + 'group_id' => $this->groupId2, + 'name' => 'My Group C', + 'external_id' => 'something else', + ))); + + $group = $this->app->getGroup($this->groupId2); + $this->assertNotEmpty($group); + $this->assertEquals('My Group C', $group['name']); + $this->assertEquals('something else', $group['external_id']); + } + + public function assertRemove() + { + $this->assertTrue($this->app->removeGroup($this->groupId1)); + } +} diff --git a/tests/integration/GroupTest.php b/tests/integration/GroupTest.php deleted file mode 100644 index ffcd7a71..00000000 --- a/tests/integration/GroupTest.php +++ /dev/null @@ -1,50 +0,0 @@ -assertCreateGroups(); - $this->assertGetAllGroups(); - $this->assertGetGroup(); - $this->assertUpdateGroup(); - $this->assertRemove(); - } - - public function assertGetAllGroups() - { - $groups = $this->app->getAllGroups(); - $this->assertNotEmpty($groups); - $this->assertArrayHasKey('name', $groups[0]); - $this->assertArrayHasKey('external_id', $groups[0]); - } - - public function assertGetGroup() - { - $group = $this->app->getGroup($this->groupId1); - $this->assertNotEmpty($group); - $this->assertEquals($this->groupName1, $group['name']); - $this->assertEquals('', $group['external_id']); - } - - public function assertUpdateGroup() - { - $this->assertTrue($this->app->updateGroup(array( - 'group_id' => $this->groupId2, - 'name' => 'My Group C', - 'external_id' => 'something else', - ))); - - $group = $this->app->getGroup($this->groupId2); - $this->assertNotEmpty($group); - $this->assertEquals('My Group C', $group['name']); - $this->assertEquals('something else', $group['external_id']); - } - - public function assertRemove() - { - $this->assertTrue($this->app->removeGroup($this->groupId1)); - } -} diff --git a/tests/integration/LinkProcedureTest.php b/tests/integration/LinkProcedureTest.php new file mode 100644 index 00000000..fb07e694 --- /dev/null +++ b/tests/integration/LinkProcedureTest.php @@ -0,0 +1,70 @@ +app->getAllLinks(); + $this->assertNotEmpty($links); + $this->assertArrayHasKey('id', $links[0]); + $this->assertArrayHasKey('label', $links[0]); + $this->assertArrayHasKey('opposite_id', $links[0]); + } + + public function testGetOppositeLink() + { + $link = $this->app->getOppositeLinkId(1); + $this->assertEquals(1, $link); + + $link = $this->app->getOppositeLinkId(2); + $this->assertEquals(3, $link); + } + + public function testGetLinkByLabel() + { + $link = $this->app->getLinkByLabel('blocks'); + $this->assertNotEmpty($link); + $this->assertEquals(2, $link['id']); + $this->assertEquals(3, $link['opposite_id']); + } + + public function testGetLinkById() + { + $link = $this->app->getLinkById(4); + $this->assertNotEmpty($link); + $this->assertEquals(4, $link['id']); + $this->assertEquals(5, $link['opposite_id']); + $this->assertEquals('duplicates', $link['label']); + } + + public function testCreateLink() + { + $link_id = $this->app->createLink(array('label' => 'test')); + $this->assertNotFalse($link_id); + $this->assertInternalType('int', $link_id); + + $link_id = $this->app->createLink(array('label' => 'foo', 'opposite_label' => 'bar')); + $this->assertNotFalse($link_id); + $this->assertInternalType('int', $link_id); + } + + public function testUpdateLink() + { + $link1 = $this->app->getLinkByLabel('bar'); + $this->assertNotEmpty($link1); + + $link2 = $this->app->getLinkByLabel('test'); + $this->assertNotEmpty($link2); + + $this->assertNotFalse($this->app->updateLink($link1['id'], $link2['id'], 'my link')); + + $link = $this->app->getLinkById($link1['id']); + $this->assertNotEmpty($link); + $this->assertEquals($link2['id'], $link['opposite_id']); + $this->assertEquals('my link', $link['label']); + + $this->assertTrue($this->app->removeLink($link1['id'])); + } +} diff --git a/tests/integration/LinkTest.php b/tests/integration/LinkTest.php deleted file mode 100644 index 16b16e50..00000000 --- a/tests/integration/LinkTest.php +++ /dev/null @@ -1,70 +0,0 @@ -app->getAllLinks(); - $this->assertNotEmpty($links); - $this->assertArrayHasKey('id', $links[0]); - $this->assertArrayHasKey('label', $links[0]); - $this->assertArrayHasKey('opposite_id', $links[0]); - } - - public function testGetOppositeLink() - { - $link = $this->app->getOppositeLinkId(1); - $this->assertEquals(1, $link); - - $link = $this->app->getOppositeLinkId(2); - $this->assertEquals(3, $link); - } - - public function testGetLinkByLabel() - { - $link = $this->app->getLinkByLabel('blocks'); - $this->assertNotEmpty($link); - $this->assertEquals(2, $link['id']); - $this->assertEquals(3, $link['opposite_id']); - } - - public function testGetLinkById() - { - $link = $this->app->getLinkById(4); - $this->assertNotEmpty($link); - $this->assertEquals(4, $link['id']); - $this->assertEquals(5, $link['opposite_id']); - $this->assertEquals('duplicates', $link['label']); - } - - public function testCreateLink() - { - $link_id = $this->app->createLink(array('label' => 'test')); - $this->assertNotFalse($link_id); - $this->assertInternalType('int', $link_id); - - $link_id = $this->app->createLink(array('label' => 'foo', 'opposite_label' => 'bar')); - $this->assertNotFalse($link_id); - $this->assertInternalType('int', $link_id); - } - - public function testUpdateLink() - { - $link1 = $this->app->getLinkByLabel('bar'); - $this->assertNotEmpty($link1); - - $link2 = $this->app->getLinkByLabel('test'); - $this->assertNotEmpty($link2); - - $this->assertNotFalse($this->app->updateLink($link1['id'], $link2['id'], 'my link')); - - $link = $this->app->getLinkById($link1['id']); - $this->assertNotEmpty($link); - $this->assertEquals($link2['id'], $link['opposite_id']); - $this->assertEquals('my link', $link['label']); - - $this->assertTrue($this->app->removeLink($link1['id'])); - } -} diff --git a/tests/integration/MeProcedureTest.php b/tests/integration/MeProcedureTest.php new file mode 100644 index 00000000..2106419c --- /dev/null +++ b/tests/integration/MeProcedureTest.php @@ -0,0 +1,68 @@ +assertGetMe(); + $this->assertCreateMyPrivateProject(); + $this->assertGetMyProjectsList(); + $this->assertGetMyProjects(); + $this->assertCreateTask(); + $this->assertGetMyDashboard(); + $this->assertGetMyActivityStream(); + } + + public function assertGetMe() + { + $profile = $this->user->getMe(); + $this->assertEquals('user', $profile['username']); + $this->assertEquals('app-user', $profile['role']); + } + + public function assertCreateMyPrivateProject() + { + $this->projectId = $this->user->createMyPrivateProject($this->projectName); + $this->assertNotFalse($this->projectId); + } + + public function assertGetMyProjectsList() + { + $projects = $this->user->getMyProjectsList(); + $this->assertNotEmpty($projects); + $this->assertEquals($this->projectName, $projects[$this->projectId]); + } + + public function assertGetMyProjects() + { + $projects = $this->user->getMyProjects(); + $this->assertNotEmpty($projects); + } + + public function assertCreateTask() + { + $taskId = $this->user->createTask(array('title' => 'My task', 'project_id' => $this->projectId, 'owner_id' => $this->userUserId)); + $this->assertNotFalse($taskId); + } + + public function assertGetMyDashboard() + { + $dashboard = $this->user->getMyDashboard(); + $this->assertNotEmpty($dashboard); + $this->assertArrayHasKey('projects', $dashboard); + $this->assertArrayHasKey('tasks', $dashboard); + $this->assertArrayHasKey('subtasks', $dashboard); + $this->assertNotEmpty($dashboard['projects']); + $this->assertNotEmpty($dashboard['tasks']); + } + + public function assertGetMyActivityStream() + { + $activity = $this->user->getMyActivityStream(); + $this->assertNotEmpty($activity); + } +} diff --git a/tests/integration/MeTest.php b/tests/integration/MeTest.php deleted file mode 100644 index 047ebf85..00000000 --- a/tests/integration/MeTest.php +++ /dev/null @@ -1,73 +0,0 @@ -assertGetMe(); - $this->assertCreateMyPrivateProject(); - $this->assertGetMyProjectsList(); - $this->assertGetMyProjects(); - $this->assertCreateTask(); - $this->assertGetMyDashboard(); - $this->assertGetMyActivityStream(); - } - - public function assertGetMe() - { - $profile = $this->user->getMe(); - $this->assertEquals('user', $profile['username']); - $this->assertEquals('app-user', $profile['role']); - } - - public function assertCreateMyPrivateProject() - { - $this->projectId = $this->user->createMyPrivateProject($this->projectName); - $this->assertNotFalse($this->projectId); - } - - public function assertGetMyProjectsList() - { - $projects = $this->user->getMyProjectsList(); - $this->assertNotEmpty($projects); - $this->assertEquals($this->projectName, $projects[$this->projectId]); - } - - public function assertGetMyProjects() - { - $projects = $this->user->getMyProjects(); - $this->assertNotEmpty($projects); - $this->assertCount(1, $projects); - $this->assertEquals($this->projectName, $projects[0]['name']); - $this->assertNotEmpty($projects[0]['url']['calendar']); - $this->assertNotEmpty($projects[0]['url']['board']); - $this->assertNotEmpty($projects[0]['url']['list']); - } - - public function assertCreateTask() - { - $taskId = $this->user->createTask(array('title' => 'My task', 'project_id' => $this->projectId, 'owner_id' => $this->userUserId)); - $this->assertNotFalse($taskId); - } - - public function assertGetMyDashboard() - { - $dashboard = $this->user->getMyDashboard(); - $this->assertNotEmpty($dashboard); - $this->assertArrayHasKey('projects', $dashboard); - $this->assertArrayHasKey('tasks', $dashboard); - $this->assertArrayHasKey('subtasks', $dashboard); - $this->assertNotEmpty($dashboard['projects']); - $this->assertNotEmpty($dashboard['tasks']); - } - - public function assertGetMyActivityStream() - { - $activity = $this->user->getMyActivityStream(); - $this->assertNotEmpty($activity); - } -} diff --git a/tests/integration/OverdueTaskProcedureTest.php b/tests/integration/OverdueTaskProcedureTest.php new file mode 100644 index 00000000..65f52301 --- /dev/null +++ b/tests/integration/OverdueTaskProcedureTest.php @@ -0,0 +1,43 @@ +assertCreateTeamProject(); + $this->assertCreateOverdueTask(); + $this->assertGetOverdueTasksByProject(); + $this->assertGetOverdueTasks(); + } + + public function assertCreateOverdueTask() + { + $this->assertNotFalse($this->app->createTask(array( + 'title' => 'overdue task', + 'project_id' => $this->projectId, + 'date_due' => date('Y-m-d', strtotime('-2days')), + ))); + } + + public function assertGetOverdueTasksByProject() + { + $tasks = $this->app->getOverdueTasksByProject($this->projectId); + $this->assertNotEmpty($tasks); + $this->assertCount(1, $tasks); + $this->assertEquals('overdue task', $tasks[0]['title']); + $this->assertEquals($this->projectName, $tasks[0]['project_name']); + } + + public function assertGetOverdueTasks() + { + $tasks = $this->app->getOverdueTasks(); + $this->assertNotEmpty($tasks); + $this->assertCount(1, $tasks); + $this->assertEquals('overdue task', $tasks[0]['title']); + $this->assertEquals($this->projectName, $tasks[0]['project_name']); + } +} diff --git a/tests/integration/OverdueTaskTest.php b/tests/integration/OverdueTaskTest.php deleted file mode 100644 index 1dea5030..00000000 --- a/tests/integration/OverdueTaskTest.php +++ /dev/null @@ -1,43 +0,0 @@ -assertCreateTeamProject(); - $this->assertCreateOverdueTask(); - $this->assertGetOverdueTasksByProject(); - $this->assertGetOverdueTasks(); - } - - public function assertCreateOverdueTask() - { - $this->assertNotFalse($this->app->createTask(array( - 'title' => 'overdue task', - 'project_id' => $this->projectId, - 'date_due' => date('Y-m-d', strtotime('-2days')), - ))); - } - - public function assertGetOverdueTasksByProject() - { - $tasks = $this->app->getOverdueTasksByProject($this->projectId); - $this->assertNotEmpty($tasks); - $this->assertCount(1, $tasks); - $this->assertEquals('overdue task', $tasks[0]['title']); - $this->assertEquals($this->projectName, $tasks[0]['project_name']); - } - - public function assertGetOverdueTasks() - { - $tasks = $this->app->getOverdueTasks(); - $this->assertNotEmpty($tasks); - $this->assertCount(1, $tasks); - $this->assertEquals('overdue task', $tasks[0]['title']); - $this->assertEquals($this->projectName, $tasks[0]['project_name']); - } -} diff --git a/tests/integration/ProcedureAuthorizationTest.php b/tests/integration/ProcedureAuthorizationTest.php new file mode 100644 index 00000000..a63e9d8c --- /dev/null +++ b/tests/integration/ProcedureAuthorizationTest.php @@ -0,0 +1,306 @@ +setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->app->getMe(); + } + + public function testUserCredentialDoNotHaveAccessToAdminProcedures() + { + $this->setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->user->getUser(1); + } + + public function testManagerCredentialDoNotHaveAccessToAdminProcedures() + { + $this->setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->user->getAllProjects(); + } + + public function testUserCredentialDoNotHaveAccessToManagerProcedures() + { + $this->setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->user->createProject('Team project creation are only for app managers'); + } + + public function testAppManagerCanCreateTeamProject() + { + $this->assertNotFalse($this->manager->createProject('Team project created by app manager')); + } + + public function testAdminManagerCanCreateTeamProject() + { + $projectId = $this->admin->createProject('Team project created by admin'); + $this->assertNotFalse($projectId); + + $this->setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->assertNotNull($this->manager->getProjectById($projectId)); + } + + public function testProjectManagerCanUpdateHisProject() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Team project can be updated', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + $this->assertEquals('project-manager', $this->app->getProjectUserRole($projectId, $this->managerUserId)); + $this->assertNotNull($this->manager->getProjectById($projectId)); + + $this->assertTrue($this->manager->updateProject($projectId, 'My team project have been updated')); + } + + public function testProjectAuthorizationForbidden() + { + $projectId = $this->manager->createProject('A team project without members'); + $this->assertNotFalse($projectId); + + $this->setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->user->getProjectById($projectId); + } + + public function testProjectAuthorizationGranted() + { + $projectId = $this->manager->createProject(array( + 'name' => 'A team project with members', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + + $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId)); + $this->assertNotNull($this->user->getProjectById($projectId)); + } + + public function testActionAuthorizationForbidden() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Test Project', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + + $actionId = $this->manager->createAction($projectId, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1)); + $this->assertNotFalse($actionId); + + $this->setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->user->removeAction($projectId); + } + + public function testActionAuthorizationForbiddenBecauseNotProjectManager() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Test Project', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + + $actionId = $this->manager->createAction($projectId, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1)); + $this->assertNotFalse($actionId); + + $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-member')); + + $this->setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->user->removeAction($actionId); + } + + public function testActionAuthorizationGranted() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Test Project', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + + $actionId = $this->manager->createAction($projectId, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1)); + $this->assertNotFalse($actionId); + + $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-manager')); + $this->assertTrue($this->user->removeAction($actionId)); + } + + public function testCategoryAuthorizationForbidden() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Test Project', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + + $categoryId = $this->manager->createCategory($projectId, 'Test'); + $this->assertNotFalse($categoryId); + + $this->setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->user->removeCategory($categoryId); + } + + public function testCategoryAuthorizationForbiddenBecauseNotProjectManager() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Test Project', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + + $categoryId = $this->manager->createCategory($projectId, 'Test'); + $this->assertNotFalse($categoryId); + + $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-member')); + $this->setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->user->removeCategory($categoryId); + } + + public function testCategoryAuthorizationGranted() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Test Project', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + + $categoryId = $this->manager->createCategory($projectId, 'Test'); + $this->assertNotFalse($categoryId); + + $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-manager')); + $this->assertTrue($this->user->removeCategory($categoryId)); + } + + public function testColumnAuthorizationForbidden() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Test Project', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + + $columnId = $this->manager->addColumn($projectId, 'Test'); + $this->assertNotFalse($columnId); + + $this->setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->user->removeColumn($columnId); + } + + public function testColumnAuthorizationForbiddenBecauseNotProjectManager() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Test Project', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + + $columnId = $this->manager->addColumn($projectId, 'Test'); + $this->assertNotFalse($columnId); + + $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-member')); + $this->setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->user->removeColumn($columnId); + } + + public function testColumnAuthorizationGranted() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Test Project', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + + $columnId = $this->manager->addColumn($projectId, 'Test'); + $this->assertNotFalse($columnId); + + $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-manager')); + $this->assertTrue($this->user->removeColumn($columnId)); + } + + public function testCommentAuthorizationForbidden() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Test Project', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-viewer')); + + $taskId = $this->manager->createTask('My Task', $projectId); + $this->assertNotFalse($taskId); + + $commentId = $this->manager->createComment($taskId, $this->userUserId, 'My comment'); + $this->assertNotFalse($commentId); + + $this->setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->user->updateComment($commentId, 'something else'); + } + + public function testCommentAuthorizationGranted() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Test Project', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-member')); + + $taskId = $this->user->createTask('My Task', $projectId); + $this->assertNotFalse($taskId); + + $commentId = $this->user->createComment($taskId, $this->userUserId, 'My comment'); + $this->assertNotFalse($commentId); + + $this->assertTrue($this->user->updateComment($commentId, 'something else')); + } + + public function testSubtaskAuthorizationForbidden() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Test Project', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-viewer')); + + $taskId = $this->manager->createTask('My Task', $projectId); + $this->assertNotFalse($taskId); + + $subtaskId = $this->manager->createSubtask($taskId, 'My subtask'); + $this->assertNotFalse($subtaskId); + + $this->setExpectedException('JsonRPC\Exception\AccessDeniedException'); + $this->user->removeSubtask($subtaskId); + } + + public function testSubtaskAuthorizationGranted() + { + $projectId = $this->manager->createProject(array( + 'name' => 'Test Project', + 'owner_id' => $this->managerUserId, + )); + + $this->assertNotFalse($projectId); + $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-member')); + + $taskId = $this->user->createTask('My Task', $projectId); + $this->assertNotFalse($taskId); + + $subtaskId = $this->manager->createSubtask($taskId, 'My subtask'); + $this->assertNotFalse($subtaskId); + + $this->assertTrue($this->user->removeSubtask($subtaskId)); + } +} diff --git a/tests/integration/ProjectPermissionProcedureTest.php b/tests/integration/ProjectPermissionProcedureTest.php new file mode 100644 index 00000000..74313dc4 --- /dev/null +++ b/tests/integration/ProjectPermissionProcedureTest.php @@ -0,0 +1,89 @@ +assertCreateTeamProject(); + $this->assertCreateGroups(); + $this->assertCreateUser(); + + $this->assertAddProjectUser(); + $this->assertGetProjectUsers(); + $this->assertGetAssignableUsers(); + $this->assertChangeProjectUserRole(); + $this->assertRemoveProjectUser(); + + $this->assertAddProjectGroup(); + $this->assertGetProjectUsers(); + $this->assertGetAssignableUsers(); + $this->assertChangeProjectGroupRole(); + $this->assertRemoveProjectGroup(); + } + + public function assertAddProjectUser() + { + $this->assertTrue($this->app->addProjectUser($this->projectId, $this->userId)); + } + + public function assertGetProjectUsers() + { + $members = $this->app->getProjectUsers($this->projectId); + $this->assertCount(1, $members); + $this->assertArrayHasKey($this->userId, $members); + $this->assertEquals($this->username, $members[$this->userId]); + } + + public function assertGetAssignableUsers() + { + $members = $this->app->getAssignableUsers($this->projectId); + $this->assertCount(1, $members); + $this->assertArrayHasKey($this->userId, $members); + $this->assertEquals($this->username, $members[$this->userId]); + } + + public function assertChangeProjectUserRole() + { + $this->assertTrue($this->app->changeProjectUserRole($this->projectId, $this->userId, 'project-viewer')); + + $members = $this->app->getAssignableUsers($this->projectId); + $this->assertCount(0, $members); + } + + public function assertRemoveProjectUser() + { + $this->assertTrue($this->app->removeProjectUser($this->projectId, $this->userId)); + + $members = $this->app->getProjectUsers($this->projectId); + $this->assertCount(0, $members); + } + + public function assertAddProjectGroup() + { + $this->assertTrue($this->app->addGroupMember($this->groupId1, $this->userId)); + $this->assertTrue($this->app->addProjectGroup($this->projectId, $this->groupId1)); + } + + public function assertChangeProjectGroupRole() + { + $this->assertTrue($this->app->changeProjectGroupRole($this->projectId, $this->groupId1, 'project-viewer')); + + $members = $this->app->getAssignableUsers($this->projectId); + $this->assertCount(0, $members); + } + + public function assertRemoveProjectGroup() + { + $this->assertTrue($this->app->removeProjectGroup($this->projectId, $this->groupId1)); + + $members = $this->app->getProjectUsers($this->projectId); + $this->assertCount(0, $members); + } +} diff --git a/tests/integration/ProjectPermissionTest.php b/tests/integration/ProjectPermissionTest.php deleted file mode 100644 index 3ceda07d..00000000 --- a/tests/integration/ProjectPermissionTest.php +++ /dev/null @@ -1,89 +0,0 @@ -assertCreateTeamProject(); - $this->assertCreateGroups(); - $this->assertCreateUser(); - - $this->assertAddProjectUser(); - $this->assertGetProjectUsers(); - $this->assertGetAssignableUsers(); - $this->assertChangeProjectUserRole(); - $this->assertRemoveProjectUser(); - - $this->assertAddProjectGroup(); - $this->assertGetProjectUsers(); - $this->assertGetAssignableUsers(); - $this->assertChangeProjectGroupRole(); - $this->assertRemoveProjectGroup(); - } - - public function assertAddProjectUser() - { - $this->assertTrue($this->app->addProjectUser($this->projectId, $this->userId)); - } - - public function assertGetProjectUsers() - { - $members = $this->app->getProjectUsers($this->projectId); - $this->assertCount(1, $members); - $this->assertArrayHasKey($this->userId, $members); - $this->assertEquals($this->username, $members[$this->userId]); - } - - public function assertGetAssignableUsers() - { - $members = $this->app->getAssignableUsers($this->projectId); - $this->assertCount(1, $members); - $this->assertArrayHasKey($this->userId, $members); - $this->assertEquals($this->username, $members[$this->userId]); - } - - public function assertChangeProjectUserRole() - { - $this->assertTrue($this->app->changeProjectUserRole($this->projectId, $this->userId, 'project-viewer')); - - $members = $this->app->getAssignableUsers($this->projectId); - $this->assertCount(0, $members); - } - - public function assertRemoveProjectUser() - { - $this->assertTrue($this->app->removeProjectUser($this->projectId, $this->userId)); - - $members = $this->app->getProjectUsers($this->projectId); - $this->assertCount(0, $members); - } - - public function assertAddProjectGroup() - { - $this->assertTrue($this->app->addGroupMember($this->groupId1, $this->userId)); - $this->assertTrue($this->app->addProjectGroup($this->projectId, $this->groupId1)); - } - - public function assertChangeProjectGroupRole() - { - $this->assertTrue($this->app->changeProjectGroupRole($this->projectId, $this->groupId1, 'project-viewer')); - - $members = $this->app->getAssignableUsers($this->projectId); - $this->assertCount(0, $members); - } - - public function assertRemoveProjectGroup() - { - $this->assertTrue($this->app->removeProjectGroup($this->projectId, $this->groupId1)); - - $members = $this->app->getProjectUsers($this->projectId); - $this->assertCount(0, $members); - } -} diff --git a/tests/integration/ProjectProcedureTest.php b/tests/integration/ProjectProcedureTest.php new file mode 100644 index 00000000..1ebd48ae --- /dev/null +++ b/tests/integration/ProjectProcedureTest.php @@ -0,0 +1,89 @@ +assertCreateTeamProject(); + $this->assertGetProjectById(); + $this->assertGetProjectByName(); + $this->assertGetAllProjects(); + $this->assertUpdateProject(); + $this->assertGetProjectActivity(); + $this->assertGetProjectsActivity(); + $this->assertEnableDisableProject(); + $this->assertEnableDisablePublicAccess(); + $this->assertRemoveProject(); + } + + public function assertGetProjectById() + { + $project = $this->app->getProjectById($this->projectId); + $this->assertNotNull($project); + $this->assertEquals($this->projectName, $project['name']); + $this->assertEquals('Description', $project['description']); + } + + public function assertGetProjectByName() + { + $project = $this->app->getProjectByName($this->projectName); + $this->assertNotNull($project); + $this->assertEquals($this->projectId, $project['id']); + $this->assertEquals($this->projectName, $project['name']); + $this->assertEquals('Description', $project['description']); + } + + public function assertGetAllProjects() + { + $projects = $this->app->getAllProjects(); + $this->assertNotEmpty($projects); + } + + public function assertGetProjectActivity() + { + $activities = $this->app->getProjectActivity($this->projectId); + $this->assertInternalType('array', $activities); + $this->assertCount(0, $activities); + } + + public function assertGetProjectsActivity() + { + $activities = $this->app->getProjectActivities(array('project_ids' => array($this->projectId))); + $this->assertInternalType('array', $activities); + $this->assertCount(0, $activities); + } + + public function assertUpdateProject() + { + $this->assertTrue($this->app->updateProject(array('project_id' => $this->projectId, 'name' => 'test', 'description' => 'test'))); + + $project = $this->app->getProjectById($this->projectId); + $this->assertNotNull($project); + $this->assertEquals('test', $project['name']); + $this->assertEquals('test', $project['description']); + + $this->assertTrue($this->app->updateProject(array('project_id' => $this->projectId, 'name' => $this->projectName))); + } + + public function assertEnableDisableProject() + { + $this->assertTrue($this->app->disableProject($this->projectId)); + $this->assertTrue($this->app->enableProject($this->projectId)); + } + + public function assertEnableDisablePublicAccess() + { + $this->assertTrue($this->app->disableProjectPublicAccess($this->projectId)); + $this->assertTrue($this->app->enableProjectPublicAccess($this->projectId)); + } + + public function assertRemoveProject() + { + $this->assertTrue($this->app->removeProject($this->projectId)); + $this->assertNull($this->app->getProjectById($this->projectId)); + } +} diff --git a/tests/integration/ProjectTest.php b/tests/integration/ProjectTest.php deleted file mode 100644 index 50d4fc53..00000000 --- a/tests/integration/ProjectTest.php +++ /dev/null @@ -1,89 +0,0 @@ -assertCreateTeamProject(); - $this->assertGetProjectById(); - $this->assertGetProjectByName(); - $this->assertGetAllProjects(); - $this->assertUpdateProject(); - $this->assertGetProjectActivity(); - $this->assertGetProjectsActivity(); - $this->assertEnableDisableProject(); - $this->assertEnableDisablePublicAccess(); - $this->assertRemoveProject(); - } - - public function assertGetProjectById() - { - $project = $this->app->getProjectById($this->projectId); - $this->assertNotNull($project); - $this->assertEquals($this->projectName, $project['name']); - $this->assertEquals('Description', $project['description']); - } - - public function assertGetProjectByName() - { - $project = $this->app->getProjectByName($this->projectName); - $this->assertNotNull($project); - $this->assertEquals($this->projectId, $project['id']); - $this->assertEquals($this->projectName, $project['name']); - $this->assertEquals('Description', $project['description']); - } - - public function assertGetAllProjects() - { - $projects = $this->app->getAllProjects(); - $this->assertNotEmpty($projects); - } - - public function assertGetProjectActivity() - { - $activities = $this->app->getProjectActivity($this->projectId); - $this->assertInternalType('array', $activities); - $this->assertCount(0, $activities); - } - - public function assertGetProjectsActivity() - { - $activities = $this->app->getProjectActivities(array('project_ids' => array($this->projectId))); - $this->assertInternalType('array', $activities); - $this->assertCount(0, $activities); - } - - public function assertUpdateProject() - { - $this->assertTrue($this->app->updateProject(array('project_id' => $this->projectId, 'name' => 'test', 'description' => 'test'))); - - $project = $this->app->getProjectById($this->projectId); - $this->assertNotNull($project); - $this->assertEquals('test', $project['name']); - $this->assertEquals('test', $project['description']); - - $this->assertTrue($this->app->updateProject(array('project_id' => $this->projectId, 'name' => $this->projectName))); - } - - public function assertEnableDisableProject() - { - $this->assertTrue($this->app->disableProject($this->projectId)); - $this->assertTrue($this->app->enableProject($this->projectId)); - } - - public function assertEnableDisablePublicAccess() - { - $this->assertTrue($this->app->disableProjectPublicAccess($this->projectId)); - $this->assertTrue($this->app->enableProjectPublicAccess($this->projectId)); - } - - public function assertRemoveProject() - { - $this->assertTrue($this->app->removeProject($this->projectId)); - $this->assertNull($this->app->getProjectById($this->projectId)); - } -} diff --git a/tests/integration/SubtaskProcedureTest.php b/tests/integration/SubtaskProcedureTest.php new file mode 100644 index 00000000..7ab4ef0b --- /dev/null +++ b/tests/integration/SubtaskProcedureTest.php @@ -0,0 +1,64 @@ +assertCreateTeamProject(); + $this->assertCreateTask(); + $this->assertCreateSubtask(); + $this->assertGetSubtask(); + $this->assertUpdateSubtask(); + $this->assertGetAllSubtasks(); + $this->assertRemoveSubtask(); + } + + public function assertCreateSubtask() + { + $this->subtaskId = $this->app->createSubtask(array( + 'task_id' => $this->taskId, + 'title' => 'subtask #1', + )); + + $this->assertNotFalse($this->subtaskId); + } + + public function assertGetSubtask() + { + $subtask = $this->app->getSubtask($this->subtaskId); + $this->assertEquals($this->taskId, $subtask['task_id']); + $this->assertEquals('subtask #1', $subtask['title']); + } + + public function assertUpdateSubtask() + { + $this->assertTrue($this->app->execute('updateSubtask', array( + 'id' => $this->subtaskId, + 'task_id' => $this->taskId, + 'title' => 'test', + ))); + + $subtask = $this->app->getSubtask($this->subtaskId); + $this->assertEquals('test', $subtask['title']); + } + + public function assertGetAllSubtasks() + { + $subtasks = $this->app->getAllSubtasks($this->taskId); + $this->assertCount(1, $subtasks); + $this->assertEquals('test', $subtasks[0]['title']); + } + + public function assertRemoveSubtask() + { + $this->assertTrue($this->app->removeSubtask($this->subtaskId)); + + $subtasks = $this->app->getAllSubtasks($this->taskId); + $this->assertCount(0, $subtasks); + } +} diff --git a/tests/integration/SubtaskTest.php b/tests/integration/SubtaskTest.php deleted file mode 100644 index 10082e60..00000000 --- a/tests/integration/SubtaskTest.php +++ /dev/null @@ -1,64 +0,0 @@ -assertCreateTeamProject(); - $this->assertCreateTask(); - $this->assertCreateSubtask(); - $this->assertGetSubtask(); - $this->assertUpdateSubtask(); - $this->assertGetAllSubtasks(); - $this->assertRemoveSubtask(); - } - - public function assertCreateSubtask() - { - $this->subtaskId = $this->app->createSubtask(array( - 'task_id' => $this->taskId, - 'title' => 'subtask #1', - )); - - $this->assertNotFalse($this->subtaskId); - } - - public function assertGetSubtask() - { - $subtask = $this->app->getSubtask($this->subtaskId); - $this->assertEquals($this->taskId, $subtask['task_id']); - $this->assertEquals('subtask #1', $subtask['title']); - } - - public function assertUpdateSubtask() - { - $this->assertTrue($this->app->execute('updateSubtask', array( - 'id' => $this->subtaskId, - 'task_id' => $this->taskId, - 'title' => 'test', - ))); - - $subtask = $this->app->getSubtask($this->subtaskId); - $this->assertEquals('test', $subtask['title']); - } - - public function assertGetAllSubtasks() - { - $subtasks = $this->app->getAllSubtasks($this->taskId); - $this->assertCount(1, $subtasks); - $this->assertEquals('test', $subtasks[0]['title']); - } - - public function assertRemoveSubtask() - { - $this->assertTrue($this->app->removeSubtask($this->subtaskId)); - - $subtasks = $this->app->getAllSubtasks($this->taskId); - $this->assertCount(0, $subtasks); - } -} diff --git a/tests/integration/SwimlaneProcedureTest.php b/tests/integration/SwimlaneProcedureTest.php new file mode 100644 index 00000000..e64342b4 --- /dev/null +++ b/tests/integration/SwimlaneProcedureTest.php @@ -0,0 +1,93 @@ +assertCreateTeamProject(); + } + + public function assertGetDefaultSwimlane() + { + $swimlane = $this->app->getDefaultSwimlane($this->projectId); + $this->assertNotEmpty($swimlane); + $this->assertEquals('Default swimlane', $swimlane['default_swimlane']); + } + + public function assertAddSwimlane() + { + $this->swimlaneId = $this->app->addSwimlane($this->projectId, 'Swimlane 1'); + $this->assertNotFalse($this->swimlaneId); + $this->assertNotFalse($this->app->addSwimlane($this->projectId, 'Swimlane 2')); + } + + public function assertGetSwimlane() + { + $swimlane = $this->app->getSwimlane($this->swimlaneId); + $this->assertInternalType('array', $swimlane); + $this->assertEquals('Swimlane 1', $swimlane['name']); + } + + public function assertUpdateSwimlane() + { + $this->assertTrue($this->app->updateSwimlane($this->swimlaneId, 'Another swimlane')); + + $swimlane = $this->app->getSwimlaneById($this->swimlaneId); + $this->assertEquals('Another swimlane', $swimlane['name']); + } + + public function assertDisableSwimlane() + { + $this->assertTrue($this->app->disableSwimlane($this->projectId, $this->swimlaneId)); + + $swimlane = $this->app->getSwimlaneById($this->swimlaneId); + $this->assertEquals(0, $swimlane['is_active']); + } + + public function assertEnableSwimlane() + { + $this->assertTrue($this->app->enableSwimlane($this->projectId, $this->swimlaneId)); + + $swimlane = $this->app->getSwimlaneById($this->swimlaneId); + $this->assertEquals(1, $swimlane['is_active']); + } + + public function assertGetAllSwimlanes() + { + $swimlanes = $this->app->getAllSwimlanes($this->projectId); + $this->assertCount(2, $swimlanes); + $this->assertEquals('Another swimlane', $swimlanes[0]['name']); + $this->assertEquals('Swimlane 2', $swimlanes[1]['name']); + } + + public function assertGetActiveSwimlane() + { + $this->assertTrue($this->app->disableSwimlane($this->projectId, $this->swimlaneId)); + + $swimlanes = $this->app->getActiveSwimlanes($this->projectId); + $this->assertCount(2, $swimlanes); + $this->assertEquals('Default swimlane', $swimlanes[0]['name']); + $this->assertEquals('Swimlane 2', $swimlanes[1]['name']); + } + + public function assertRemoveSwimlane() + { + $this->assertTrue($this->app->removeSwimlane($this->projectId, $this->swimlaneId)); + } + + public function assertChangePosition() + { + $swimlaneId1 = $this->app->addSwimlane($this->projectId, 'Swimlane A'); + $this->assertNotFalse($this->app->addSwimlane($this->projectId, 'Swimlane B')); + + $swimlanes = $this->app->getAllSwimlanes($this->projectId); + $this->assertCount(3, $swimlanes); + + $this->assertTrue($this->app->changeSwimlanePosition($this->projectId, $swimlaneId1, 3)); + } +} diff --git a/tests/integration/SwimlaneTest.php b/tests/integration/SwimlaneTest.php deleted file mode 100644 index 4f703414..00000000 --- a/tests/integration/SwimlaneTest.php +++ /dev/null @@ -1,93 +0,0 @@ -assertCreateTeamProject(); - } - - public function assertGetDefaultSwimlane() - { - $swimlane = $this->app->getDefaultSwimlane($this->projectId); - $this->assertNotEmpty($swimlane); - $this->assertEquals('Default swimlane', $swimlane['default_swimlane']); - } - - public function assertAddSwimlane() - { - $this->swimlaneId = $this->app->addSwimlane($this->projectId, 'Swimlane 1'); - $this->assertNotFalse($this->swimlaneId); - $this->assertNotFalse($this->app->addSwimlane($this->projectId, 'Swimlane 2')); - } - - public function assertGetSwimlane() - { - $swimlane = $this->app->getSwimlane($this->swimlaneId); - $this->assertInternalType('array', $swimlane); - $this->assertEquals('Swimlane 1', $swimlane['name']); - } - - public function assertUpdateSwimlane() - { - $this->assertTrue($this->app->updateSwimlane($this->swimlaneId, 'Another swimlane')); - - $swimlane = $this->app->getSwimlaneById($this->swimlaneId); - $this->assertEquals('Another swimlane', $swimlane['name']); - } - - public function assertDisableSwimlane() - { - $this->assertTrue($this->app->disableSwimlane($this->projectId, $this->swimlaneId)); - - $swimlane = $this->app->getSwimlaneById($this->swimlaneId); - $this->assertEquals(0, $swimlane['is_active']); - } - - public function assertEnableSwimlane() - { - $this->assertTrue($this->app->enableSwimlane($this->projectId, $this->swimlaneId)); - - $swimlane = $this->app->getSwimlaneById($this->swimlaneId); - $this->assertEquals(1, $swimlane['is_active']); - } - - public function assertGetAllSwimlanes() - { - $swimlanes = $this->app->getAllSwimlanes($this->projectId); - $this->assertCount(2, $swimlanes); - $this->assertEquals('Another swimlane', $swimlanes[0]['name']); - $this->assertEquals('Swimlane 2', $swimlanes[1]['name']); - } - - public function assertGetActiveSwimlane() - { - $this->assertTrue($this->app->disableSwimlane($this->projectId, $this->swimlaneId)); - - $swimlanes = $this->app->getActiveSwimlanes($this->projectId); - $this->assertCount(2, $swimlanes); - $this->assertEquals('Default swimlane', $swimlanes[0]['name']); - $this->assertEquals('Swimlane 2', $swimlanes[1]['name']); - } - - public function assertRemoveSwimlane() - { - $this->assertTrue($this->app->removeSwimlane($this->projectId, $this->swimlaneId)); - } - - public function assertChangePosition() - { - $swimlaneId1 = $this->app->addSwimlane($this->projectId, 'Swimlane A'); - $this->assertNotFalse($this->app->addSwimlane($this->projectId, 'Swimlane B')); - - $swimlanes = $this->app->getAllSwimlanes($this->projectId); - $this->assertCount(3, $swimlanes); - - $this->assertTrue($this->app->changeSwimlanePosition($this->projectId, $swimlaneId1, 3)); - } -} diff --git a/tests/integration/TaskFileProcedureTest.php b/tests/integration/TaskFileProcedureTest.php new file mode 100644 index 00000000..61155555 --- /dev/null +++ b/tests/integration/TaskFileProcedureTest.php @@ -0,0 +1,67 @@ +assertCreateTeamProject(); + $this->assertCreateTask(); + $this->assertCreateTaskFile(); + $this->assertGetTaskFile(); + $this->assertDownloadTaskFile(); + $this->assertGetAllFiles(); + $this->assertRemoveTaskFile(); + $this->assertRemoveAllTaskFiles(); + } + + public function assertCreateTaskFile() + { + $this->fileId = $this->app->createTaskFile(1, $this->taskId, 'My file', base64_encode('plain text file')); + $this->assertNotFalse($this->fileId); + } + + public function assertGetTaskFile() + { + $file = $this->app->getTaskFile($this->fileId); + $this->assertNotEmpty($file); + $this->assertEquals('My file', $file['name']); + } + + public function assertDownloadTaskFile() + { + $content = $this->app->downloadTaskFile($this->fileId); + $this->assertNotEmpty($content); + $this->assertEquals('plain text file', base64_decode($content)); + } + + public function assertGetAllFiles() + { + $files = $this->app->getAllTaskFiles(array('task_id' => $this->taskId)); + $this->assertCount(1, $files); + $this->assertEquals('My file', $files[0]['name']); + } + + public function assertRemoveTaskFile() + { + $this->assertTrue($this->app->removeTaskFile($this->fileId)); + + $files = $this->app->getAllTaskFiles(array('task_id' => $this->taskId)); + $this->assertEmpty($files); + } + + public function assertRemoveAllTaskFiles() + { + $this->assertCreateTaskFile(); + $this->assertCreateTaskFile(); + + $this->assertTrue($this->app->removeAllTaskFiles($this->taskId)); + + $files = $this->app->getAllTaskFiles(array('task_id' => $this->taskId)); + $this->assertEmpty($files); + } +} diff --git a/tests/integration/TaskFileTest.php b/tests/integration/TaskFileTest.php deleted file mode 100644 index 7e9e943b..00000000 --- a/tests/integration/TaskFileTest.php +++ /dev/null @@ -1,67 +0,0 @@ -assertCreateTeamProject(); - $this->assertCreateTask(); - $this->assertCreateTaskFile(); - $this->assertGetTaskFile(); - $this->assertDownloadTaskFile(); - $this->assertGetAllFiles(); - $this->assertRemoveTaskFile(); - $this->assertRemoveAllTaskFiles(); - } - - public function assertCreateTaskFile() - { - $this->fileId = $this->app->createTaskFile(1, $this->taskId, 'My file', base64_encode('plain text file')); - $this->assertNotFalse($this->fileId); - } - - public function assertGetTaskFile() - { - $file = $this->app->getTaskFile($this->fileId); - $this->assertNotEmpty($file); - $this->assertEquals('My file', $file['name']); - } - - public function assertDownloadTaskFile() - { - $content = $this->app->downloadTaskFile($this->fileId); - $this->assertNotEmpty($content); - $this->assertEquals('plain text file', base64_decode($content)); - } - - public function assertGetAllFiles() - { - $files = $this->app->getAllTaskFiles(array('task_id' => $this->taskId)); - $this->assertCount(1, $files); - $this->assertEquals('My file', $files[0]['name']); - } - - public function assertRemoveTaskFile() - { - $this->assertTrue($this->app->removeTaskFile($this->fileId)); - - $files = $this->app->getAllTaskFiles(array('task_id' => $this->taskId)); - $this->assertEmpty($files); - } - - public function assertRemoveAllTaskFiles() - { - $this->assertCreateTaskFile(); - $this->assertCreateTaskFile(); - - $this->assertTrue($this->app->removeAllTaskFiles($this->taskId)); - - $files = $this->app->getAllTaskFiles(array('task_id' => $this->taskId)); - $this->assertEmpty($files); - } -} diff --git a/tests/integration/TaskLinkProcedureTest.php b/tests/integration/TaskLinkProcedureTest.php new file mode 100644 index 00000000..a25fced5 --- /dev/null +++ b/tests/integration/TaskLinkProcedureTest.php @@ -0,0 +1,68 @@ +assertCreateTeamProject(); + + $this->taskId1 = $this->app->createTask(array('project_id' => $this->projectId, 'title' => 'Task 1')); + $this->taskId2 = $this->app->createTask(array('project_id' => $this->projectId, 'title' => 'Task 2')); + + $this->assertNotFalse($this->taskId1); + $this->assertNotFalse($this->taskId2); + + $this->assertCreateTaskLink(); + $this->assertGetTaskLink(); + $this->assertGetAllTaskLinks(); + $this->assertUpdateTaskLink(); + $this->assertRemoveTaskLink(); + } + + public function assertCreateTaskLink() + { + $this->taskLinkId = $this->app->createTaskLink($this->taskId1, $this->taskId2, 1); + $this->assertNotFalse($this->taskLinkId); + } + + public function assertGetTaskLink() + { + $link = $this->app->getTaskLinkById($this->taskLinkId); + $this->assertNotNull($link); + $this->assertEquals($this->taskId1, $link['task_id']); + $this->assertEquals($this->taskId2, $link['opposite_task_id']); + $this->assertEquals(1, $link['link_id']); + } + + public function assertGetAllTaskLinks() + { + $links = $this->app->getAllTaskLinks($this->taskId2); + $this->assertCount(1, $links); + } + + public function assertUpdateTaskLink() + { + $this->assertTrue($this->app->updateTaskLink($this->taskLinkId, $this->taskId1, $this->taskId2, 3)); + + $link = $this->app->getTaskLinkById($this->taskLinkId); + $this->assertNotNull($link); + $this->assertEquals($this->taskId1, $link['task_id']); + $this->assertEquals($this->taskId2, $link['opposite_task_id']); + $this->assertEquals(3, $link['link_id']); + } + + public function assertRemoveTaskLink() + { + $this->assertTrue($this->app->removeTaskLink($this->taskLinkId)); + + $links = $this->app->getAllTaskLinks($this->taskId2); + $this->assertCount(0, $links); + } +} diff --git a/tests/integration/TaskLinkTest.php b/tests/integration/TaskLinkTest.php deleted file mode 100644 index 03bc437b..00000000 --- a/tests/integration/TaskLinkTest.php +++ /dev/null @@ -1,68 +0,0 @@ -assertCreateTeamProject(); - - $this->taskId1 = $this->app->createTask(array('project_id' => $this->projectId, 'title' => 'Task 1')); - $this->taskId2 = $this->app->createTask(array('project_id' => $this->projectId, 'title' => 'Task 2')); - - $this->assertNotFalse($this->taskId1); - $this->assertNotFalse($this->taskId2); - - $this->assertCreateTaskLink(); - $this->assertGetTaskLink(); - $this->assertGetAllTaskLinks(); - $this->assertUpdateTaskLink(); - $this->assertRemoveTaskLink(); - } - - public function assertCreateTaskLink() - { - $this->taskLinkId = $this->app->createTaskLink($this->taskId1, $this->taskId2, 1); - $this->assertNotFalse($this->taskLinkId); - } - - public function assertGetTaskLink() - { - $link = $this->app->getTaskLinkById($this->taskLinkId); - $this->assertNotNull($link); - $this->assertEquals($this->taskId1, $link['task_id']); - $this->assertEquals($this->taskId2, $link['opposite_task_id']); - $this->assertEquals(1, $link['link_id']); - } - - public function assertGetAllTaskLinks() - { - $links = $this->app->getAllTaskLinks($this->taskId2); - $this->assertCount(1, $links); - } - - public function assertUpdateTaskLink() - { - $this->assertTrue($this->app->updateTaskLink($this->taskLinkId, $this->taskId1, $this->taskId2, 3)); - - $link = $this->app->getTaskLinkById($this->taskLinkId); - $this->assertNotNull($link); - $this->assertEquals($this->taskId1, $link['task_id']); - $this->assertEquals($this->taskId2, $link['opposite_task_id']); - $this->assertEquals(3, $link['link_id']); - } - - public function assertRemoveTaskLink() - { - $this->assertTrue($this->app->removeTaskLink($this->taskLinkId)); - - $links = $this->app->getAllTaskLinks($this->taskId2); - $this->assertCount(0, $links); - } -} diff --git a/tests/integration/TaskProcedureTest.php b/tests/integration/TaskProcedureTest.php new file mode 100644 index 00000000..f456ae52 --- /dev/null +++ b/tests/integration/TaskProcedureTest.php @@ -0,0 +1,55 @@ +assertCreateTeamProject(); + $this->assertCreateTask(); + $this->assertUpdateTask(); + $this->assertGetTaskById(); + $this->assertGetTaskByReference(); + $this->assertGetAllTasks(); + $this->assertOpenCloseTask(); + } + + public function assertUpdateTask() + { + $this->assertTrue($this->app->updateTask(array('id' => $this->taskId, 'color_id' => 'red'))); + } + + public function assertGetTaskById() + { + $task = $this->app->getTask($this->taskId); + $this->assertNotNull($task); + $this->assertEquals('red', $task['color_id']); + $this->assertEquals($this->taskTitle, $task['title']); + } + + public function assertGetTaskByReference() + { + $taskId = $this->app->createTask(array('title' => 'task with reference', 'project_id' => $this->projectId, 'reference' => 'test')); + $this->assertNotFalse($taskId); + + $task = $this->app->getTaskByReference($this->projectId, 'test'); + $this->assertNotNull($task); + $this->assertEquals($taskId, $task['id']); + } + + public function assertGetAllTasks() + { + $tasks = $this->app->getAllTasks($this->projectId); + $this->assertInternalType('array', $tasks); + $this->assertNotEmpty($tasks); + } + + public function assertOpenCloseTask() + { + $this->assertTrue($this->app->closeTask($this->taskId)); + $this->assertTrue($this->app->openTask($this->taskId)); + } +} diff --git a/tests/integration/TaskTest.php b/tests/integration/TaskTest.php deleted file mode 100644 index 6f1d9d62..00000000 --- a/tests/integration/TaskTest.php +++ /dev/null @@ -1,55 +0,0 @@ -assertCreateTeamProject(); - $this->assertCreateTask(); - $this->assertUpdateTask(); - $this->assertGetTaskById(); - $this->assertGetTaskByReference(); - $this->assertGetAllTasks(); - $this->assertOpenCloseTask(); - } - - public function assertUpdateTask() - { - $this->assertTrue($this->app->updateTask(array('id' => $this->taskId, 'color_id' => 'red'))); - } - - public function assertGetTaskById() - { - $task = $this->app->getTask($this->taskId); - $this->assertNotNull($task); - $this->assertEquals('red', $task['color_id']); - $this->assertEquals($this->taskTitle, $task['title']); - } - - public function assertGetTaskByReference() - { - $taskId = $this->app->createTask(array('title' => 'task with reference', 'project_id' => $this->projectId, 'reference' => 'test')); - $this->assertNotFalse($taskId); - - $task = $this->app->getTaskByReference($this->projectId, 'test'); - $this->assertNotNull($task); - $this->assertEquals($taskId, $task['id']); - } - - public function assertGetAllTasks() - { - $tasks = $this->app->getAllTasks($this->projectId); - $this->assertInternalType('array', $tasks); - $this->assertNotEmpty($tasks); - } - - public function assertOpenCloseTask() - { - $this->assertTrue($this->app->closeTask($this->taskId)); - $this->assertTrue($this->app->openTask($this->taskId)); - } -} diff --git a/tests/integration/UserProcedureTest.php b/tests/integration/UserProcedureTest.php new file mode 100644 index 00000000..290f87fb --- /dev/null +++ b/tests/integration/UserProcedureTest.php @@ -0,0 +1,63 @@ +assertCreateUser(); + $this->assertGetUserById(); + $this->assertGetUserByName(); + $this->assertGetAllUsers(); + $this->assertEnableDisableUser(); + $this->assertUpdateUser(); + $this->assertRemoveUser(); + } + + public function assertGetUserById() + { + $user = $this->app->getUser($this->userId); + $this->assertNotNull($user); + $this->assertEquals($this->username, $user['username']); + } + + public function assertGetUserByName() + { + $user = $this->app->getUserByName($this->username); + $this->assertNotNull($user); + $this->assertEquals($this->username, $user['username']); + } + + public function assertGetAllUsers() + { + $users = $this->app->getAllUsers(); + $this->assertInternalType('array', $users); + $this->assertNotEmpty($users); + } + + public function assertEnableDisableUser() + { + $this->assertTrue($this->app->disableUser($this->userId)); + $this->assertFalse($this->app->isActiveUser($this->userId)); + $this->assertTrue($this->app->enableUser($this->userId)); + $this->assertTrue($this->app->isActiveUser($this->userId)); + } + + public function assertUpdateUser() + { + $this->assertTrue($this->app->updateUser(array( + 'id' => $this->userId, + 'name' => 'My user', + ))); + + $user = $this->app->getUser($this->userId); + $this->assertNotNull($user); + $this->assertEquals('My user', $user['name']); + } + + public function assertRemoveUser() + { + $this->assertTrue($this->app->removeUser($this->userId)); + } +} diff --git a/tests/integration/UserTest.php b/tests/integration/UserTest.php deleted file mode 100644 index c407c918..00000000 --- a/tests/integration/UserTest.php +++ /dev/null @@ -1,63 +0,0 @@ -assertCreateUser(); - $this->assertGetUserById(); - $this->assertGetUserByName(); - $this->assertGetAllUsers(); - $this->assertEnableDisableUser(); - $this->assertUpdateUser(); - $this->assertRemoveUser(); - } - - public function assertGetUserById() - { - $user = $this->app->getUser($this->userId); - $this->assertNotNull($user); - $this->assertEquals($this->username, $user['username']); - } - - public function assertGetUserByName() - { - $user = $this->app->getUserByName($this->username); - $this->assertNotNull($user); - $this->assertEquals($this->username, $user['username']); - } - - public function assertGetAllUsers() - { - $users = $this->app->getAllUsers(); - $this->assertInternalType('array', $users); - $this->assertNotEmpty($users); - } - - public function assertEnableDisableUser() - { - $this->assertTrue($this->app->disableUser($this->userId)); - $this->assertFalse($this->app->isActiveUser($this->userId)); - $this->assertTrue($this->app->enableUser($this->userId)); - $this->assertTrue($this->app->isActiveUser($this->userId)); - } - - public function assertUpdateUser() - { - $this->assertTrue($this->app->updateUser(array( - 'id' => $this->userId, - 'name' => 'My user', - ))); - - $user = $this->app->getUser($this->userId); - $this->assertNotNull($user); - $this->assertEquals('My user', $user['name']); - } - - public function assertRemoveUser() - { - $this->assertTrue($this->app->removeUser($this->userId)); - } -} diff --git a/tests/units/Model/ActionModelTest.php b/tests/units/Model/ActionModelTest.php new file mode 100644 index 00000000..4e21a999 --- /dev/null +++ b/tests/units/Model/ActionModelTest.php @@ -0,0 +1,527 @@ +container); + $actionModel = new ActionModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => TaskModel::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); + } + + public function testRemove() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => TaskModel::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); + + $this->assertNotEmpty($actionModel->getById(1)); + $this->assertTrue($actionModel->remove(1)); + $this->assertEmpty($actionModel->getById(1)); + } + + public function testGetById() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => TaskModel::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(TaskModel::EVENT_CREATE, $action['event_name']); + $this->assertEquals(array('column_id' => 1, 'color_id' => 'red'), $action['params']); + } + + public function testGetProjectId() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => TaskModel::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); + + $this->assertEquals(1, $actionModel->getProjectId(1)); + $this->assertSame(0, $actionModel->getProjectId(42)); + } + + public function testGetAll() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($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' => TaskModel::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' => TaskModel::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(TaskModel::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(TaskModel::EVENT_MOVE_COLUMN, $actions[1]['event_name']); + $this->assertEquals(array('column_id' => 6, 'color_id' => 'blue'), $actions[1]['params']); + } + + public function testGetAllByProject() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($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' => TaskModel::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' => TaskModel::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(TaskModel::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(TaskModel::EVENT_MOVE_COLUMN, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 6, 'color_id' => 'blue'), $actions[0]['params']); + } + + public function testGetAllByUser() + { + $projectModel = new ProjectModel($this->container); + $projectUserRoleModel = new ProjectUserRoleModel($this->container); + $userModel = new UserModel($this->container); + $actionModel = new ActionModel($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' => 'test4', 'is_active' => 0))); + + $this->assertEquals(2, $userModel->create(array('username' => 'user1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user2'))); + + $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, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => TaskModel::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' => TaskModel::EVENT_MOVE_COLUMN, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 6, 'color_id' => 'blue'), + ))); + + $this->assertEquals(3, $actionModel->create(array( + 'project_id' => 3, + 'event_name' => TaskModel::EVENT_MOVE_COLUMN, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 10, 'color_id' => 'green'), + ))); + + $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(TaskModel::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(TaskModel::EVENT_MOVE_COLUMN, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 6, 'color_id' => 'blue'), $actions[0]['params']); + } + + public function testDuplicateWithColumnAndColorParameter() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($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' => TaskModel::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); + + $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(TaskModel::EVENT_CREATE, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 5, 'color_id' => 'red'), $actions[0]['params']); + } + + public function testDuplicateWithColumnsParameter() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($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' => TaskModel::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('src_column_id' => 1, 'dst_column_id' => 2, 'dest_column_id' => 3), + ))); + + $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(TaskModel::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 testDuplicateWithColumnParameterNotfound() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($this->container); + $columnModel = new ColumnModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertTrue($columnModel->update(2, 'My unique column')); + + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => TaskModel::EVENT_CREATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); + + $this->assertEquals(2, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => TaskModel::EVENT_MOVE_COLUMN, + 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', + 'params' => array('column_id' => 2, 'color_id' => 'green'), + ))); + + $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(TaskModel::EVENT_CREATE, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 5, 'color_id' => 'red'), $actions[0]['params']); + } + + public function testDuplicateWithProjectParameter() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($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(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => TaskModel::EVENT_CLOSE, + 'action_name' => '\Kanboard\Action\TaskDuplicateAnotherProject', + 'params' => array('column_id' => 1, 'project_id' => 3), + ))); + + $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\TaskDuplicateAnotherProject', $actions[0]['action_name']); + $this->assertEquals(TaskModel::EVENT_CLOSE, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 5, 'project_id' => 3), $actions[0]['params']); + } + + public function testDuplicateWithProjectParameterIdenticalToDestination() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($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' => TaskModel::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 testDuplicateWithUserParameter() + { + $projectUserRoleModel = new ProjectUserRoleModel($this->container); + $userModel = new UserModel($this->container); + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($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' => TaskModel::EVENT_MOVE_COLUMN, + 'action_name' => '\Kanboard\Action\TaskAssignSpecificUser', + 'params' => array('column_id' => 1, 'user_id' => 2), + ))); + + $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(TaskModel::EVENT_MOVE_COLUMN, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 5, 'user_id' => 2), $actions[0]['params']); + } + + public function testDuplicateWithUserParameterButNotAssignable() + { + $projectUserRoleModel = new ProjectUserRoleModel($this->container); + $userModel = new UserModel($this->container); + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($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, + 'event_name' => TaskModel::EVENT_MOVE_COLUMN, + 'action_name' => '\Kanboard\Action\TaskAssignSpecificUser', + 'params' => array('column_id' => 1, 'user_id' => 2), + ))); + + $this->assertTrue($actionModel->duplicate(1, 2)); + + $actions = $actionModel->getAllByProject(2); + $this->assertCount(0, $actions); + } + + public function testDuplicateWithUserParameterButNotAvailable() + { + $projectUserRoleModel = new ProjectUserRoleModel($this->container); + $userModel = new UserModel($this->container); + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($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->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => TaskModel::EVENT_MOVE_COLUMN, + 'action_name' => '\Kanboard\Action\TaskAssignSpecificUser', + 'params' => array('column_id' => 1, 'owner_id' => 2), + ))); + + $this->assertTrue($actionModel->duplicate(1, 2)); + + $actions = $actionModel->getAllByProject(2); + $this->assertCount(0, $actions); + } + + public function testDuplicateWithCategoryParameter() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($this->container); + $categoryModel = new CategoryModel($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' => TaskModel::EVENT_CREATE_UPDATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorCategory', + 'params' => array('column_id' => 1, 'category_id' => 1), + ))); + + $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(TaskModel::EVENT_CREATE_UPDATE, $actions[0]['event_name']); + $this->assertEquals(array('column_id' => 5, 'category_id' => 2), $actions[0]['params']); + } + + public function testDuplicateWithCategoryParameterButDifferentName() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($this->container); + $categoryModel = new CategoryModel($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' => TaskModel::EVENT_CREATE_UPDATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorCategory', + 'params' => array('column_id' => 1, 'category_id' => 1), + ))); + + $this->assertTrue($actionModel->duplicate(1, 2)); + + $actions = $actionModel->getAllByProject(2); + $this->assertCount(0, $actions); + } + + public function testDuplicateWithCategoryParameterButNotFound() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($this->container); + $categoryModel = new CategoryModel($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' => TaskModel::EVENT_CREATE_UPDATE, + 'action_name' => '\Kanboard\Action\TaskAssignColorCategory', + 'params' => array('column_id' => 1, 'category_id' => 1), + ))); + + $this->assertTrue($actionModel->duplicate(1, 2)); + + $actions = $actionModel->getAllByProject(2); + $this->assertCount(0, $actions); + } +} diff --git a/tests/units/Model/ActionTest.php b/tests/units/Model/ActionTest.php deleted file mode 100644 index 5db18983..00000000 --- a/tests/units/Model/ActionTest.php +++ /dev/null @@ -1,509 +0,0 @@ -container); - $actionModel = new ActionModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - - $this->assertEquals(1, $actionModel->create(array( - 'project_id' => 1, - 'event_name' => TaskModel::EVENT_CREATE, - 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', - 'params' => array('column_id' => 1, 'color_id' => 'red'), - ))); - } - - public function testRemove() - { - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - - $this->assertEquals(1, $actionModel->create(array( - 'project_id' => 1, - 'event_name' => TaskModel::EVENT_CREATE, - 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', - 'params' => array('column_id' => 1, 'color_id' => 'red'), - ))); - - $this->assertNotEmpty($actionModel->getById(1)); - $this->assertTrue($actionModel->remove(1)); - $this->assertEmpty($actionModel->getById(1)); - } - - public function testGetById() - { - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - - $this->assertEquals(1, $actionModel->create(array( - 'project_id' => 1, - 'event_name' => TaskModel::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(TaskModel::EVENT_CREATE, $action['event_name']); - $this->assertEquals(array('column_id' => 1, 'color_id' => 'red'), $action['params']); - } - - public function testGetAll() - { - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($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' => TaskModel::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' => TaskModel::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(TaskModel::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(TaskModel::EVENT_MOVE_COLUMN, $actions[1]['event_name']); - $this->assertEquals(array('column_id' => 6, 'color_id' => 'blue'), $actions[1]['params']); - } - - public function testGetAllByProject() - { - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($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' => TaskModel::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' => TaskModel::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(TaskModel::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(TaskModel::EVENT_MOVE_COLUMN, $actions[0]['event_name']); - $this->assertEquals(array('column_id' => 6, 'color_id' => 'blue'), $actions[0]['params']); - } - - public function testGetAllByUser() - { - $projectModel = new ProjectModel($this->container); - $projectUserRoleModel = new ProjectUserRoleModel($this->container); - $userModel = new UserModel($this->container); - $actionModel = new ActionModel($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' => 'test4', 'is_active' => 0))); - - $this->assertEquals(2, $userModel->create(array('username' => 'user1'))); - $this->assertEquals(3, $userModel->create(array('username' => 'user2'))); - - $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, $actionModel->create(array( - 'project_id' => 1, - 'event_name' => TaskModel::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' => TaskModel::EVENT_MOVE_COLUMN, - 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', - 'params' => array('column_id' => 6, 'color_id' => 'blue'), - ))); - - $this->assertEquals(3, $actionModel->create(array( - 'project_id' => 3, - 'event_name' => TaskModel::EVENT_MOVE_COLUMN, - 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', - 'params' => array('column_id' => 10, 'color_id' => 'green'), - ))); - - $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(TaskModel::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(TaskModel::EVENT_MOVE_COLUMN, $actions[0]['event_name']); - $this->assertEquals(array('column_id' => 6, 'color_id' => 'blue'), $actions[0]['params']); - } - - public function testDuplicateWithColumnAndColorParameter() - { - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($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' => TaskModel::EVENT_CREATE, - 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', - 'params' => array('column_id' => 1, 'color_id' => 'red'), - ))); - - $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(TaskModel::EVENT_CREATE, $actions[0]['event_name']); - $this->assertEquals(array('column_id' => 5, 'color_id' => 'red'), $actions[0]['params']); - } - - public function testDuplicateWithColumnsParameter() - { - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($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' => TaskModel::EVENT_CREATE, - 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', - 'params' => array('src_column_id' => 1, 'dst_column_id' => 2, 'dest_column_id' => 3), - ))); - - $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(TaskModel::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 testDuplicateWithColumnParameterNotfound() - { - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($this->container); - $columnModel = new ColumnModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - - $this->assertTrue($columnModel->update(2, 'My unique column')); - - $this->assertEquals(1, $actionModel->create(array( - 'project_id' => 1, - 'event_name' => TaskModel::EVENT_CREATE, - 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', - 'params' => array('column_id' => 1, 'color_id' => 'red'), - ))); - - $this->assertEquals(2, $actionModel->create(array( - 'project_id' => 1, - 'event_name' => TaskModel::EVENT_MOVE_COLUMN, - 'action_name' => '\Kanboard\Action\TaskAssignColorColumn', - 'params' => array('column_id' => 2, 'color_id' => 'green'), - ))); - - $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(TaskModel::EVENT_CREATE, $actions[0]['event_name']); - $this->assertEquals(array('column_id' => 5, 'color_id' => 'red'), $actions[0]['params']); - } - - public function testDuplicateWithProjectParameter() - { - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($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(1, $actionModel->create(array( - 'project_id' => 1, - 'event_name' => TaskModel::EVENT_CLOSE, - 'action_name' => '\Kanboard\Action\TaskDuplicateAnotherProject', - 'params' => array('column_id' => 1, 'project_id' => 3), - ))); - - $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\TaskDuplicateAnotherProject', $actions[0]['action_name']); - $this->assertEquals(TaskModel::EVENT_CLOSE, $actions[0]['event_name']); - $this->assertEquals(array('column_id' => 5, 'project_id' => 3), $actions[0]['params']); - } - - public function testDuplicateWithProjectParameterIdenticalToDestination() - { - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($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' => TaskModel::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 testDuplicateWithUserParameter() - { - $projectUserRoleModel = new ProjectUserRoleModel($this->container); - $userModel = new UserModel($this->container); - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($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' => TaskModel::EVENT_MOVE_COLUMN, - 'action_name' => '\Kanboard\Action\TaskAssignSpecificUser', - 'params' => array('column_id' => 1, 'user_id' => 2), - ))); - - $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(TaskModel::EVENT_MOVE_COLUMN, $actions[0]['event_name']); - $this->assertEquals(array('column_id' => 5, 'user_id' => 2), $actions[0]['params']); - } - - public function testDuplicateWithUserParameterButNotAssignable() - { - $projectUserRoleModel = new ProjectUserRoleModel($this->container); - $userModel = new UserModel($this->container); - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($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, - 'event_name' => TaskModel::EVENT_MOVE_COLUMN, - 'action_name' => '\Kanboard\Action\TaskAssignSpecificUser', - 'params' => array('column_id' => 1, 'user_id' => 2), - ))); - - $this->assertTrue($actionModel->duplicate(1, 2)); - - $actions = $actionModel->getAllByProject(2); - $this->assertCount(0, $actions); - } - - public function testDuplicateWithUserParameterButNotAvailable() - { - $projectUserRoleModel = new ProjectUserRoleModel($this->container); - $userModel = new UserModel($this->container); - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($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->assertEquals(1, $actionModel->create(array( - 'project_id' => 1, - 'event_name' => TaskModel::EVENT_MOVE_COLUMN, - 'action_name' => '\Kanboard\Action\TaskAssignSpecificUser', - 'params' => array('column_id' => 1, 'owner_id' => 2), - ))); - - $this->assertTrue($actionModel->duplicate(1, 2)); - - $actions = $actionModel->getAllByProject(2); - $this->assertCount(0, $actions); - } - - public function testDuplicateWithCategoryParameter() - { - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($this->container); - $categoryModel = new CategoryModel($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' => TaskModel::EVENT_CREATE_UPDATE, - 'action_name' => '\Kanboard\Action\TaskAssignColorCategory', - 'params' => array('column_id' => 1, 'category_id' => 1), - ))); - - $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(TaskModel::EVENT_CREATE_UPDATE, $actions[0]['event_name']); - $this->assertEquals(array('column_id' => 5, 'category_id' => 2), $actions[0]['params']); - } - - public function testDuplicateWithCategoryParameterButDifferentName() - { - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($this->container); - $categoryModel = new CategoryModel($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' => TaskModel::EVENT_CREATE_UPDATE, - 'action_name' => '\Kanboard\Action\TaskAssignColorCategory', - 'params' => array('column_id' => 1, 'category_id' => 1), - ))); - - $this->assertTrue($actionModel->duplicate(1, 2)); - - $actions = $actionModel->getAllByProject(2); - $this->assertCount(0, $actions); - } - - public function testDuplicateWithCategoryParameterButNotFound() - { - $projectModel = new ProjectModel($this->container); - $actionModel = new ActionModel($this->container); - $categoryModel = new CategoryModel($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' => TaskModel::EVENT_CREATE_UPDATE, - 'action_name' => '\Kanboard\Action\TaskAssignColorCategory', - 'params' => array('column_id' => 1, 'category_id' => 1), - ))); - - $this->assertTrue($actionModel->duplicate(1, 2)); - - $actions = $actionModel->getAllByProject(2); - $this->assertCount(0, $actions); - } -} diff --git a/tests/units/Model/CategoryModelTest.php b/tests/units/Model/CategoryModelTest.php new file mode 100644 index 00000000..80a20af6 --- /dev/null +++ b/tests/units/Model/CategoryModelTest.php @@ -0,0 +1,229 @@ +container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1))); + $this->assertEquals(2, $categoryModel->create(array('name' => 'Category #2', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'category_id' => 2))); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(2, $task['category_id']); + + $category = $categoryModel->getById(2); + $this->assertEquals(2, $category['id']); + $this->assertEquals('Category #2', $category['name']); + $this->assertEquals(1, $category['project_id']); + } + + public function testExists() + { + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1))); + $this->assertTrue($categoryModel->exists(1)); + $this->assertFalse($categoryModel->exists(2)); + } + + public function testGetById() + { + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test'))); + + $category = $categoryModel->getById(1); + $this->assertEquals(1, $category['id']); + $this->assertEquals('Category #1', $category['name']); + $this->assertEquals(1, $category['project_id']); + $this->assertEquals('test', $category['description']); + } + + public function testGetNameById() + { + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test'))); + + $this->assertEquals('Category #1', $categoryModel->getNameById(1)); + $this->assertEquals('', $categoryModel->getNameById(2)); + } + + public function testGetIdByName() + { + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test'))); + + $this->assertSame(1, $categoryModel->getIdByName(1, 'Category #1')); + $this->assertSame(0, $categoryModel->getIdByName(1, 'Category #2')); + } + + public function testGetProjectId() + { + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test'))); + + $this->assertEquals(1, $categoryModel->getProjectId(1)); + $this->assertSame(0, $categoryModel->getProjectId(2)); + } + + public function testGetList() + { + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test'))); + $this->assertEquals(2, $categoryModel->create(array('name' => 'Category #2', 'project_id' => 1))); + + $categories = $categoryModel->getList(1, false, false); + $this->assertCount(2, $categories); + $this->assertEquals('Category #1', $categories[1]); + $this->assertEquals('Category #2', $categories[2]); + + $categories = $categoryModel->getList(1, true, false); + $this->assertCount(3, $categories); + $this->assertEquals('No category', $categories[0]); + $this->assertEquals('Category #1', $categories[1]); + $this->assertEquals('Category #2', $categories[2]); + + $categories = $categoryModel->getList(1, false, true); + $this->assertCount(3, $categories); + $this->assertEquals('All categories', $categories[-1]); + $this->assertEquals('Category #1', $categories[1]); + $this->assertEquals('Category #2', $categories[2]); + + $categories = $categoryModel->getList(1, true, true); + $this->assertCount(4, $categories); + $this->assertEquals('All categories', $categories[-1]); + $this->assertEquals('No category', $categories[0]); + $this->assertEquals('Category #1', $categories[1]); + $this->assertEquals('Category #2', $categories[2]); + } + + public function testGetAll() + { + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test'))); + $this->assertEquals(2, $categoryModel->create(array('name' => 'Category #2', 'project_id' => 1))); + + $categories = $categoryModel->getAll(1); + $this->assertCount(2, $categories); + + $this->assertEquals('Category #1', $categories[0]['name']); + $this->assertEquals('test', $categories[0]['description']); + $this->assertEquals(1, $categories[0]['project_id']); + $this->assertEquals(1, $categories[0]['id']); + + $this->assertEquals('Category #2', $categories[1]['name']); + $this->assertEquals('', $categories[1]['description']); + $this->assertEquals(1, $categories[1]['project_id']); + $this->assertEquals(2, $categories[1]['id']); + } + + public function testCreateDefaultCategories() + { + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + $configModel = new ConfigModel($this->container); + + $this->assertTrue($configModel->save(array('project_categories' => 'C1, C2, C3'))); + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertTrue($categoryModel->createDefaultCategories(1)); + + $categories = $categoryModel->getAll(1); + $this->assertCount(3, $categories); + $this->assertEquals('C1', $categories[0]['name']); + $this->assertEquals('C2', $categories[1]['name']); + $this->assertEquals('C3', $categories[2]['name']); + } + + public function testUpdate() + { + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1))); + $this->assertTrue($categoryModel->update(array('id' => 1, 'description' => 'test'))); + + $category = $categoryModel->getById(1); + $this->assertEquals('Category #1', $category['name']); + $this->assertEquals(1, $category['project_id']); + $this->assertEquals('test', $category['description']); + } + + public function testRemove() + { + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1))); + $this->assertEquals(2, $categoryModel->create(array('name' => 'Category #2', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'category_id' => 2))); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(2, $task['category_id']); + + $this->assertTrue($categoryModel->remove(1)); + $this->assertTrue($categoryModel->remove(2)); + + // Make sure tasks assigned with that category are reseted + $task = $taskFinderModel->getById(1); + $this->assertEquals(0, $task['category_id']); + } + + public function testDuplicate() + { + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'Project #2'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test'))); + + $this->assertTrue($categoryModel->duplicate(1, 2)); + + $category = $categoryModel->getById(1); + $this->assertEquals('Category #1', $category['name']); + $this->assertEquals(1, $category['project_id']); + $this->assertEquals('test', $category['description']); + + $category = $categoryModel->getById(2); + $this->assertEquals('Category #1', $category['name']); + $this->assertEquals(2, $category['project_id']); + $this->assertEquals('test', $category['description']); + } +} diff --git a/tests/units/Model/CategoryTest.php b/tests/units/Model/CategoryTest.php deleted file mode 100644 index 1fdc51f6..00000000 --- a/tests/units/Model/CategoryTest.php +++ /dev/null @@ -1,217 +0,0 @@ -container); - $taskFinderModel = new TaskFinderModel($this->container); - $projectModel = new ProjectModel($this->container); - $categoryModel = new CategoryModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1))); - $this->assertEquals(2, $categoryModel->create(array('name' => 'Category #2', 'project_id' => 1))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'category_id' => 2))); - - $task = $taskFinderModel->getById(1); - $this->assertEquals(2, $task['category_id']); - - $category = $categoryModel->getById(2); - $this->assertEquals(2, $category['id']); - $this->assertEquals('Category #2', $category['name']); - $this->assertEquals(1, $category['project_id']); - } - - public function testExists() - { - $projectModel = new ProjectModel($this->container); - $categoryModel = new CategoryModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1))); - $this->assertTrue($categoryModel->exists(1)); - $this->assertFalse($categoryModel->exists(2)); - } - - public function testGetById() - { - $projectModel = new ProjectModel($this->container); - $categoryModel = new CategoryModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test'))); - - $category = $categoryModel->getById(1); - $this->assertEquals(1, $category['id']); - $this->assertEquals('Category #1', $category['name']); - $this->assertEquals(1, $category['project_id']); - $this->assertEquals('test', $category['description']); - } - - public function testGetNameById() - { - $projectModel = new ProjectModel($this->container); - $categoryModel = new CategoryModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test'))); - - $this->assertEquals('Category #1', $categoryModel->getNameById(1)); - $this->assertEquals('', $categoryModel->getNameById(2)); - } - - public function testGetIdByName() - { - $projectModel = new ProjectModel($this->container); - $categoryModel = new CategoryModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test'))); - - $this->assertSame(1, $categoryModel->getIdByName(1, 'Category #1')); - $this->assertSame(0, $categoryModel->getIdByName(1, 'Category #2')); - } - - public function testGetList() - { - $projectModel = new ProjectModel($this->container); - $categoryModel = new CategoryModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test'))); - $this->assertEquals(2, $categoryModel->create(array('name' => 'Category #2', 'project_id' => 1))); - - $categories = $categoryModel->getList(1, false, false); - $this->assertCount(2, $categories); - $this->assertEquals('Category #1', $categories[1]); - $this->assertEquals('Category #2', $categories[2]); - - $categories = $categoryModel->getList(1, true, false); - $this->assertCount(3, $categories); - $this->assertEquals('No category', $categories[0]); - $this->assertEquals('Category #1', $categories[1]); - $this->assertEquals('Category #2', $categories[2]); - - $categories = $categoryModel->getList(1, false, true); - $this->assertCount(3, $categories); - $this->assertEquals('All categories', $categories[-1]); - $this->assertEquals('Category #1', $categories[1]); - $this->assertEquals('Category #2', $categories[2]); - - $categories = $categoryModel->getList(1, true, true); - $this->assertCount(4, $categories); - $this->assertEquals('All categories', $categories[-1]); - $this->assertEquals('No category', $categories[0]); - $this->assertEquals('Category #1', $categories[1]); - $this->assertEquals('Category #2', $categories[2]); - } - - public function testGetAll() - { - $projectModel = new ProjectModel($this->container); - $categoryModel = new CategoryModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test'))); - $this->assertEquals(2, $categoryModel->create(array('name' => 'Category #2', 'project_id' => 1))); - - $categories = $categoryModel->getAll(1); - $this->assertCount(2, $categories); - - $this->assertEquals('Category #1', $categories[0]['name']); - $this->assertEquals('test', $categories[0]['description']); - $this->assertEquals(1, $categories[0]['project_id']); - $this->assertEquals(1, $categories[0]['id']); - - $this->assertEquals('Category #2', $categories[1]['name']); - $this->assertEquals('', $categories[1]['description']); - $this->assertEquals(1, $categories[1]['project_id']); - $this->assertEquals(2, $categories[1]['id']); - } - - public function testCreateDefaultCategories() - { - $projectModel = new ProjectModel($this->container); - $categoryModel = new CategoryModel($this->container); - $configModel = new ConfigModel($this->container); - - $this->assertTrue($configModel->save(array('project_categories' => 'C1, C2, C3'))); - $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); - $this->assertTrue($categoryModel->createDefaultCategories(1)); - - $categories = $categoryModel->getAll(1); - $this->assertCount(3, $categories); - $this->assertEquals('C1', $categories[0]['name']); - $this->assertEquals('C2', $categories[1]['name']); - $this->assertEquals('C3', $categories[2]['name']); - } - - public function testUpdate() - { - $projectModel = new ProjectModel($this->container); - $categoryModel = new CategoryModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1))); - $this->assertTrue($categoryModel->update(array('id' => 1, 'description' => 'test'))); - - $category = $categoryModel->getById(1); - $this->assertEquals('Category #1', $category['name']); - $this->assertEquals(1, $category['project_id']); - $this->assertEquals('test', $category['description']); - } - - public function testRemove() - { - $taskCreationModel = new TaskCreationModel($this->container); - $taskFinderModel = new TaskFinderModel($this->container); - $projectModel = new ProjectModel($this->container); - $categoryModel = new CategoryModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1))); - $this->assertEquals(2, $categoryModel->create(array('name' => 'Category #2', 'project_id' => 1))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'category_id' => 2))); - - $task = $taskFinderModel->getById(1); - $this->assertEquals(2, $task['category_id']); - - $this->assertTrue($categoryModel->remove(1)); - $this->assertTrue($categoryModel->remove(2)); - - // Make sure tasks assigned with that category are reseted - $task = $taskFinderModel->getById(1); - $this->assertEquals(0, $task['category_id']); - } - - public function testDuplicate() - { - $projectModel = new ProjectModel($this->container); - $categoryModel = new CategoryModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); - $this->assertEquals(2, $projectModel->create(array('name' => 'Project #2'))); - $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test'))); - - $this->assertTrue($categoryModel->duplicate(1, 2)); - - $category = $categoryModel->getById(1); - $this->assertEquals('Category #1', $category['name']); - $this->assertEquals(1, $category['project_id']); - $this->assertEquals('test', $category['description']); - - $category = $categoryModel->getById(2); - $this->assertEquals('Category #1', $category['name']); - $this->assertEquals(2, $category['project_id']); - $this->assertEquals('test', $category['description']); - } -} diff --git a/tests/units/Model/CommentTest.php b/tests/units/Model/CommentTest.php index 7250ae0b..574b5a87 100644 --- a/tests/units/Model/CommentTest.php +++ b/tests/units/Model/CommentTest.php @@ -10,16 +10,16 @@ class CommentTest extends Base { public function testCreate() { - $c = new CommentModel($this->container); - $tc = new TaskCreationModel($this->container); - $p = new ProjectModel($this->container); + $commentModel = new CommentModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); - $this->assertEquals(1, $c->create(array('task_id' => 1, 'comment' => 'bla bla', 'user_id' => 1))); - $this->assertEquals(2, $c->create(array('task_id' => 1, 'comment' => 'bla bla'))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'bla bla', 'user_id' => 1))); + $this->assertEquals(2, $commentModel->create(array('task_id' => 1, 'comment' => 'bla bla'))); - $comment = $c->getById(1); + $comment = $commentModel->getById(1); $this->assertNotEmpty($comment); $this->assertEquals('bla bla', $comment['comment']); $this->assertEquals(1, $comment['task_id']); @@ -27,7 +27,7 @@ class CommentTest extends Base $this->assertEquals('admin', $comment['username']); $this->assertEquals(time(), $comment['date_creation'], '', 3); - $comment = $c->getById(2); + $comment = $commentModel->getById(2); $this->assertNotEmpty($comment); $this->assertEquals('bla bla', $comment['comment']); $this->assertEquals(1, $comment['task_id']); @@ -38,17 +38,17 @@ class CommentTest extends Base public function testGetAll() { - $c = new CommentModel($this->container); - $tc = new TaskCreationModel($this->container); - $p = new ProjectModel($this->container); + $commentModel = new CommentModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); - $this->assertNotFalse($c->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); - $this->assertNotFalse($c->create(array('task_id' => 1, 'comment' => 'c2', 'user_id' => 1))); - $this->assertNotFalse($c->create(array('task_id' => 1, 'comment' => 'c3', 'user_id' => 1))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); + $this->assertEquals(2, $commentModel->create(array('task_id' => 1, 'comment' => 'c2', 'user_id' => 1))); + $this->assertEquals(3, $commentModel->create(array('task_id' => 1, 'comment' => 'c3', 'user_id' => 1))); - $comments = $c->getAll(1); + $comments = $commentModel->getAll(1); $this->assertNotEmpty($comments); $this->assertEquals(3, count($comments)); @@ -56,37 +56,51 @@ class CommentTest extends Base $this->assertEquals(2, $comments[1]['id']); $this->assertEquals(3, $comments[2]['id']); - $this->assertEquals(3, $c->count(1)); + $this->assertEquals(3, $commentModel->count(1)); } public function testUpdate() { - $c = new CommentModel($this->container); - $tc = new TaskCreationModel($this->container); - $p = new ProjectModel($this->container); + $commentModel = new CommentModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); - $this->assertNotFalse($c->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); - $this->assertTrue($c->update(array('id' => 1, 'comment' => 'bla'))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); + $this->assertTrue($commentModel->update(array('id' => 1, 'comment' => 'bla'))); - $comment = $c->getById(1); + $comment = $commentModel->getById(1); $this->assertNotEmpty($comment); $this->assertEquals('bla', $comment['comment']); } public function validateRemove() { - $c = new CommentModel($this->container); - $tc = new TaskCreationModel($this->container); - $p = new ProjectModel($this->container); + $commentModel = new CommentModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); - $this->assertTrue($c->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); - $this->assertTrue($c->remove(1)); - $this->assertFalse($c->remove(1)); - $this->assertFalse($c->remove(1111)); + $this->assertTrue($commentModel->remove(1)); + $this->assertFalse($commentModel->remove(1)); + $this->assertFalse($commentModel->remove(1111)); + } + + public function testGetProjectId() + { + $commentModel = new CommentModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); + + $this->assertEquals(1, $commentModel->getProjectId(1)); + $this->assertSame(0, $commentModel->getProjectId(2)); } } diff --git a/tests/units/Model/SubtaskModelTest.php b/tests/units/Model/SubtaskModelTest.php new file mode 100644 index 00000000..6451189d --- /dev/null +++ b/tests/units/Model/SubtaskModelTest.php @@ -0,0 +1,400 @@ +assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); + $data = $event->getAll(); + + $this->assertArrayHasKey('id', $data); + $this->assertArrayHasKey('title', $data); + $this->assertArrayHasKey('status', $data); + $this->assertArrayHasKey('time_estimated', $data); + $this->assertArrayHasKey('time_spent', $data); + $this->assertArrayHasKey('status', $data); + $this->assertArrayHasKey('task_id', $data); + $this->assertArrayHasKey('user_id', $data); + $this->assertArrayHasKey('position', $data); + $this->assertNotEmpty($data['task_id']); + $this->assertNotEmpty($data['id']); + } + + public function onSubtaskUpdated($event) + { + $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); + $data = $event->getAll(); + + $this->assertArrayHasKey('id', $data); + $this->assertArrayHasKey('title', $data); + $this->assertArrayHasKey('status', $data); + $this->assertArrayHasKey('time_estimated', $data); + $this->assertArrayHasKey('time_spent', $data); + $this->assertArrayHasKey('status', $data); + $this->assertArrayHasKey('task_id', $data); + $this->assertArrayHasKey('user_id', $data); + $this->assertArrayHasKey('position', $data); + $this->assertArrayHasKey('changes', $data); + $this->assertArrayHasKey('user_id', $data['changes']); + $this->assertArrayHasKey('status', $data['changes']); + + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $data['changes']['status']); + $this->assertEquals(1, $data['changes']['user_id']); + } + + public function onSubtaskDeleted($event) + { + $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); + $data = $event->getAll(); + + $this->assertArrayHasKey('id', $data); + $this->assertArrayHasKey('title', $data); + $this->assertArrayHasKey('status', $data); + $this->assertArrayHasKey('time_estimated', $data); + $this->assertArrayHasKey('time_spent', $data); + $this->assertArrayHasKey('status', $data); + $this->assertArrayHasKey('task_id', $data); + $this->assertArrayHasKey('user_id', $data); + $this->assertArrayHasKey('position', $data); + $this->assertNotEmpty($data['task_id']); + $this->assertNotEmpty($data['id']); + } + + public function testCreation() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->container['dispatcher']->addListener(SubtaskModel::EVENT_CREATE, array($this, 'onSubtaskCreated')); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(1, $subtask['id']); + $this->assertEquals(1, $subtask['task_id']); + $this->assertEquals('subtask #1', $subtask['title']); + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); + $this->assertEquals(0, $subtask['time_estimated']); + $this->assertEquals(0, $subtask['time_spent']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['position']); + } + + public function testModification() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->container['dispatcher']->addListener(SubtaskModel::EVENT_UPDATE, array($this, 'onSubtaskUpdated')); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + $this->assertTrue($subtaskModel->update(array('id' => 1, 'user_id' => 1, 'status' => SubtaskModel::STATUS_INPROGRESS))); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(1, $subtask['id']); + $this->assertEquals(1, $subtask['task_id']); + $this->assertEquals('subtask #1', $subtask['title']); + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); + $this->assertEquals(0, $subtask['time_estimated']); + $this->assertEquals(0, $subtask['time_spent']); + $this->assertEquals(1, $subtask['user_id']); + $this->assertEquals(1, $subtask['position']); + } + + public function testRemove() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + + $this->container['dispatcher']->addListener(SubtaskModel::EVENT_DELETE, array($this, 'onSubtaskDeleted')); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + + $this->assertTrue($subtaskModel->remove(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertEmpty($subtask); + } + + public function testToggleStatusWithoutSession() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtaskModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtaskModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtaskModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + } + + public function testToggleStatusWithSession() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + // Set the current logged user + $this->container['sessionStorage']->user = array('id' => 1); + + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtaskModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); + $this->assertEquals(1, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtaskModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); + $this->assertEquals(1, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtaskModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); + $this->assertEquals(1, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + } + + public function testCloseAll() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1))); + + $this->assertTrue($subtaskModel->closeAll(1)); + + $subtasks = $subtaskModel->getAll(1); + $this->assertNotEmpty($subtasks); + + foreach ($subtasks as $subtask) { + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); + } + } + + public function testDuplicate() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + + // We create a project + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + + // We create 2 tasks + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'test 2', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 0))); + + // We create many subtasks for the first task + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1, 'time_estimated' => 5, 'time_spent' => 3, 'status' => 1, 'another_subtask' => 'on'))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_estimated' => '', 'time_spent' => '', 'status' => 2, 'user_id' => 1))); + + // We duplicate our subtasks + $this->assertTrue($subtaskModel->duplicate(1, 2)); + $subtasks = $subtaskModel->getAll(2); + + $this->assertNotFalse($subtasks); + $this->assertNotEmpty($subtasks); + $this->assertEquals(2, count($subtasks)); + + $this->assertEquals('subtask #1', $subtasks[0]['title']); + $this->assertEquals('subtask #2', $subtasks[1]['title']); + + $this->assertEquals(2, $subtasks[0]['task_id']); + $this->assertEquals(2, $subtasks[1]['task_id']); + + $this->assertEquals(5, $subtasks[0]['time_estimated']); + $this->assertEquals(0, $subtasks[1]['time_estimated']); + + $this->assertEquals(0, $subtasks[0]['time_spent']); + $this->assertEquals(0, $subtasks[1]['time_spent']); + + $this->assertEquals(0, $subtasks[0]['status']); + $this->assertEquals(0, $subtasks[1]['status']); + + $this->assertEquals(0, $subtasks[0]['user_id']); + $this->assertEquals(0, $subtasks[1]['user_id']); + + $this->assertEquals(1, $subtasks[0]['position']); + $this->assertEquals(2, $subtasks[1]['position']); + } + + public function testChangePosition() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1))); + $this->assertEquals(3, $subtaskModel->create(array('title' => 'subtask #3', 'task_id' => 1))); + + $subtasks = $subtaskModel->getAll(1); + $this->assertEquals(1, $subtasks[0]['position']); + $this->assertEquals(1, $subtasks[0]['id']); + $this->assertEquals(2, $subtasks[1]['position']); + $this->assertEquals(2, $subtasks[1]['id']); + $this->assertEquals(3, $subtasks[2]['position']); + $this->assertEquals(3, $subtasks[2]['id']); + + $this->assertTrue($subtaskModel->changePosition(1, 3, 2)); + + $subtasks = $subtaskModel->getAll(1); + $this->assertEquals(1, $subtasks[0]['position']); + $this->assertEquals(1, $subtasks[0]['id']); + $this->assertEquals(2, $subtasks[1]['position']); + $this->assertEquals(3, $subtasks[1]['id']); + $this->assertEquals(3, $subtasks[2]['position']); + $this->assertEquals(2, $subtasks[2]['id']); + + $this->assertTrue($subtaskModel->changePosition(1, 2, 1)); + + $subtasks = $subtaskModel->getAll(1); + $this->assertEquals(1, $subtasks[0]['position']); + $this->assertEquals(2, $subtasks[0]['id']); + $this->assertEquals(2, $subtasks[1]['position']); + $this->assertEquals(1, $subtasks[1]['id']); + $this->assertEquals(3, $subtasks[2]['position']); + $this->assertEquals(3, $subtasks[2]['id']); + + $this->assertTrue($subtaskModel->changePosition(1, 2, 2)); + + $subtasks = $subtaskModel->getAll(1); + $this->assertEquals(1, $subtasks[0]['position']); + $this->assertEquals(1, $subtasks[0]['id']); + $this->assertEquals(2, $subtasks[1]['position']); + $this->assertEquals(2, $subtasks[1]['id']); + $this->assertEquals(3, $subtasks[2]['position']); + $this->assertEquals(3, $subtasks[2]['id']); + + $this->assertTrue($subtaskModel->changePosition(1, 1, 3)); + + $subtasks = $subtaskModel->getAll(1); + $this->assertEquals(1, $subtasks[0]['position']); + $this->assertEquals(2, $subtasks[0]['id']); + $this->assertEquals(2, $subtasks[1]['position']); + $this->assertEquals(3, $subtasks[1]['id']); + $this->assertEquals(3, $subtasks[2]['position']); + $this->assertEquals(1, $subtasks[2]['id']); + + $this->assertFalse($subtaskModel->changePosition(1, 2, 0)); + $this->assertFalse($subtaskModel->changePosition(1, 2, 4)); + } + + public function testConvertToTask() + { + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1, 'user_id' => 1, 'time_spent' => 2, 'time_estimated' => 3))); + $task_id = $subtaskModel->convertToTask(1, 1); + + $this->assertNotFalse($task_id); + $this->assertEmpty($subtaskModel->getById(1)); + + $task = $taskFinderModel->getById($task_id); + $this->assertEquals('subtask #1', $task['title']); + $this->assertEquals(1, $task['project_id']); + $this->assertEquals(1, $task['owner_id']); + $this->assertEquals(2, $task['time_spent']); + $this->assertEquals(3, $task['time_estimated']); + } + + public function testGetProjectId() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + + $this->assertEquals(1, $subtaskModel->getProjectId(1)); + $this->assertEquals(0, $subtaskModel->getProjectId(2)); + } +} diff --git a/tests/units/Model/SubtaskTest.php b/tests/units/Model/SubtaskTest.php deleted file mode 100644 index b65ee609..00000000 --- a/tests/units/Model/SubtaskTest.php +++ /dev/null @@ -1,388 +0,0 @@ -assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); - $data = $event->getAll(); - - $this->assertArrayHasKey('id', $data); - $this->assertArrayHasKey('title', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('time_estimated', $data); - $this->assertArrayHasKey('time_spent', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('task_id', $data); - $this->assertArrayHasKey('user_id', $data); - $this->assertArrayHasKey('position', $data); - $this->assertNotEmpty($data['task_id']); - $this->assertNotEmpty($data['id']); - } - - public function onSubtaskUpdated($event) - { - $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); - $data = $event->getAll(); - - $this->assertArrayHasKey('id', $data); - $this->assertArrayHasKey('title', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('time_estimated', $data); - $this->assertArrayHasKey('time_spent', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('task_id', $data); - $this->assertArrayHasKey('user_id', $data); - $this->assertArrayHasKey('position', $data); - $this->assertArrayHasKey('changes', $data); - $this->assertArrayHasKey('user_id', $data['changes']); - $this->assertArrayHasKey('status', $data['changes']); - - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $data['changes']['status']); - $this->assertEquals(1, $data['changes']['user_id']); - } - - public function onSubtaskDeleted($event) - { - $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); - $data = $event->getAll(); - - $this->assertArrayHasKey('id', $data); - $this->assertArrayHasKey('title', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('time_estimated', $data); - $this->assertArrayHasKey('time_spent', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('task_id', $data); - $this->assertArrayHasKey('user_id', $data); - $this->assertArrayHasKey('position', $data); - $this->assertNotEmpty($data['task_id']); - $this->assertNotEmpty($data['id']); - } - - public function testCreation() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->container['dispatcher']->addListener(SubtaskModel::EVENT_CREATE, array($this, 'onSubtaskCreated')); - - $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1))); - - $subtask = $s->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(1, $subtask['id']); - $this->assertEquals(1, $subtask['task_id']); - $this->assertEquals('subtask #1', $subtask['title']); - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); - $this->assertEquals(0, $subtask['time_estimated']); - $this->assertEquals(0, $subtask['time_spent']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['position']); - } - - public function testModification() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->container['dispatcher']->addListener(SubtaskModel::EVENT_UPDATE, array($this, 'onSubtaskUpdated')); - - $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1))); - $this->assertTrue($s->update(array('id' => 1, 'user_id' => 1, 'status' => SubtaskModel::STATUS_INPROGRESS))); - - $subtask = $s->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(1, $subtask['id']); - $this->assertEquals(1, $subtask['task_id']); - $this->assertEquals('subtask #1', $subtask['title']); - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); - $this->assertEquals(0, $subtask['time_estimated']); - $this->assertEquals(0, $subtask['time_spent']); - $this->assertEquals(1, $subtask['user_id']); - $this->assertEquals(1, $subtask['position']); - } - - public function testRemove() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1))); - - $this->container['dispatcher']->addListener(SubtaskModel::EVENT_DELETE, array($this, 'onSubtaskDeleted')); - - $subtask = $s->getById(1); - $this->assertNotEmpty($subtask); - - $this->assertTrue($s->remove(1)); - - $subtask = $s->getById(1); - $this->assertEmpty($subtask); - } - - public function testToggleStatusWithoutSession() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1))); - - $subtask = $s->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $s->toggleStatus(1)); - - $subtask = $s->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_DONE, $s->toggleStatus(1)); - - $subtask = $s->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_TODO, $s->toggleStatus(1)); - - $subtask = $s->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - } - - public function testToggleStatusWithSession() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $p = new ProjectModel($this->container); - $us = new UserSession($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1))); - - $subtask = $s->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - // Set the current logged user - $this->container['sessionStorage']->user = array('id' => 1); - - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $s->toggleStatus(1)); - - $subtask = $s->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); - $this->assertEquals(1, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_DONE, $s->toggleStatus(1)); - - $subtask = $s->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); - $this->assertEquals(1, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_TODO, $s->toggleStatus(1)); - - $subtask = $s->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); - $this->assertEquals(1, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - } - - public function testCloseAll() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1))); - $this->assertEquals(2, $s->create(array('title' => 'subtask #2', 'task_id' => 1))); - - $this->assertTrue($s->closeAll(1)); - - $subtasks = $s->getAll(1); - $this->assertNotEmpty($subtasks); - - foreach ($subtasks as $subtask) { - $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); - } - } - - public function testDuplicate() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $p = new ProjectModel($this->container); - - // We create a project - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - - // We create 2 tasks - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); - $this->assertEquals(2, $tc->create(array('title' => 'test 2', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 0))); - - // We create many subtasks for the first task - $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1, 'time_estimated' => 5, 'time_spent' => 3, 'status' => 1, 'another_subtask' => 'on'))); - $this->assertEquals(2, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_estimated' => '', 'time_spent' => '', 'status' => 2, 'user_id' => 1))); - - // We duplicate our subtasks - $this->assertTrue($s->duplicate(1, 2)); - $subtasks = $s->getAll(2); - - $this->assertNotFalse($subtasks); - $this->assertNotEmpty($subtasks); - $this->assertEquals(2, count($subtasks)); - - $this->assertEquals('subtask #1', $subtasks[0]['title']); - $this->assertEquals('subtask #2', $subtasks[1]['title']); - - $this->assertEquals(2, $subtasks[0]['task_id']); - $this->assertEquals(2, $subtasks[1]['task_id']); - - $this->assertEquals(5, $subtasks[0]['time_estimated']); - $this->assertEquals(0, $subtasks[1]['time_estimated']); - - $this->assertEquals(0, $subtasks[0]['time_spent']); - $this->assertEquals(0, $subtasks[1]['time_spent']); - - $this->assertEquals(0, $subtasks[0]['status']); - $this->assertEquals(0, $subtasks[1]['status']); - - $this->assertEquals(0, $subtasks[0]['user_id']); - $this->assertEquals(0, $subtasks[1]['user_id']); - - $this->assertEquals(1, $subtasks[0]['position']); - $this->assertEquals(2, $subtasks[1]['position']); - } - - public function testChangePosition() - { - $taskCreationModel = new TaskCreationModel($this->container); - $subtaskModel = new SubtaskModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); - $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1))); - $this->assertEquals(3, $subtaskModel->create(array('title' => 'subtask #3', 'task_id' => 1))); - - $subtasks = $subtaskModel->getAll(1); - $this->assertEquals(1, $subtasks[0]['position']); - $this->assertEquals(1, $subtasks[0]['id']); - $this->assertEquals(2, $subtasks[1]['position']); - $this->assertEquals(2, $subtasks[1]['id']); - $this->assertEquals(3, $subtasks[2]['position']); - $this->assertEquals(3, $subtasks[2]['id']); - - $this->assertTrue($subtaskModel->changePosition(1, 3, 2)); - - $subtasks = $subtaskModel->getAll(1); - $this->assertEquals(1, $subtasks[0]['position']); - $this->assertEquals(1, $subtasks[0]['id']); - $this->assertEquals(2, $subtasks[1]['position']); - $this->assertEquals(3, $subtasks[1]['id']); - $this->assertEquals(3, $subtasks[2]['position']); - $this->assertEquals(2, $subtasks[2]['id']); - - $this->assertTrue($subtaskModel->changePosition(1, 2, 1)); - - $subtasks = $subtaskModel->getAll(1); - $this->assertEquals(1, $subtasks[0]['position']); - $this->assertEquals(2, $subtasks[0]['id']); - $this->assertEquals(2, $subtasks[1]['position']); - $this->assertEquals(1, $subtasks[1]['id']); - $this->assertEquals(3, $subtasks[2]['position']); - $this->assertEquals(3, $subtasks[2]['id']); - - $this->assertTrue($subtaskModel->changePosition(1, 2, 2)); - - $subtasks = $subtaskModel->getAll(1); - $this->assertEquals(1, $subtasks[0]['position']); - $this->assertEquals(1, $subtasks[0]['id']); - $this->assertEquals(2, $subtasks[1]['position']); - $this->assertEquals(2, $subtasks[1]['id']); - $this->assertEquals(3, $subtasks[2]['position']); - $this->assertEquals(3, $subtasks[2]['id']); - - $this->assertTrue($subtaskModel->changePosition(1, 1, 3)); - - $subtasks = $subtaskModel->getAll(1); - $this->assertEquals(1, $subtasks[0]['position']); - $this->assertEquals(2, $subtasks[0]['id']); - $this->assertEquals(2, $subtasks[1]['position']); - $this->assertEquals(3, $subtasks[1]['id']); - $this->assertEquals(3, $subtasks[2]['position']); - $this->assertEquals(1, $subtasks[2]['id']); - - $this->assertFalse($subtaskModel->changePosition(1, 2, 0)); - $this->assertFalse($subtaskModel->changePosition(1, 2, 4)); - } - - public function testConvertToTask() - { - $taskCreationModel = new TaskCreationModel($this->container); - $taskFinderModel = new TaskFinderModel($this->container); - $subtaskModel = new SubtaskModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1, 'user_id' => 1, 'time_spent' => 2, 'time_estimated' => 3))); - $task_id = $subtaskModel->convertToTask(1, 1); - - $this->assertNotFalse($task_id); - $this->assertEmpty($subtaskModel->getById(1)); - - $task = $taskFinderModel->getById($task_id); - $this->assertEquals('subtask #1', $task['title']); - $this->assertEquals(1, $task['project_id']); - $this->assertEquals(1, $task['owner_id']); - $this->assertEquals(2, $task['time_spent']); - $this->assertEquals(3, $task['time_estimated']); - } -} diff --git a/tests/units/Model/TaskFileModelTest.php b/tests/units/Model/TaskFileModelTest.php new file mode 100644 index 00000000..de12553f --- /dev/null +++ b/tests/units/Model/TaskFileModelTest.php @@ -0,0 +1,458 @@ +container); + $fileModel = new TaskFileModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $this->assertEquals(1, $fileModel->create(1, 'test', '/tmp/foo', 10)); + + $file = $fileModel->getById(1); + $this->assertEquals('test', $file['name']); + $this->assertEquals('/tmp/foo', $file['path']); + $this->assertEquals(0, $file['is_image']); + $this->assertEquals(1, $file['task_id']); + $this->assertEquals(time(), $file['date'], '', 2); + $this->assertEquals(0, $file['user_id']); + $this->assertEquals(10, $file['size']); + + $this->assertEquals(2, $fileModel->create(1, 'test2.png', '/tmp/foobar', 10)); + + $file = $fileModel->getById(2); + $this->assertEquals('test2.png', $file['name']); + $this->assertEquals('/tmp/foobar', $file['path']); + $this->assertEquals(1, $file['is_image']); + } + + public function testCreationWithFileNameTooLong() + { + $projectModel = new ProjectModel($this->container); + $fileModel = new TaskFileModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $this->assertNotFalse($fileModel->create(1, 'test', '/tmp/foo', 10)); + $this->assertNotFalse($fileModel->create(1, str_repeat('a', 1000), '/tmp/foo', 10)); + + $files = $fileModel->getAll(1); + $this->assertNotEmpty($files); + $this->assertCount(2, $files); + + $this->assertEquals(str_repeat('a', 255), $files[0]['name']); + $this->assertEquals('test', $files[1]['name']); + } + + public function testCreationWithSessionOpen() + { + $this->container['sessionStorage']->user = array('id' => 1); + + $projectModel = new ProjectModel($this->container); + $fileModel = new TaskFileModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(1, $fileModel->create(1, 'test', '/tmp/foo', 10)); + + $file = $fileModel->getById(1); + $this->assertEquals('test', $file['name']); + $this->assertEquals(1, $file['user_id']); + } + + public function testGetAll() + { + $projectModel = new ProjectModel($this->container); + $fileModel = new TaskFileModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $this->assertEquals(1, $fileModel->create(1, 'B.pdf', '/tmp/foo', 10)); + $this->assertEquals(2, $fileModel->create(1, 'A.png', '/tmp/foo', 10)); + $this->assertEquals(3, $fileModel->create(1, 'D.doc', '/tmp/foo', 10)); + $this->assertEquals(4, $fileModel->create(1, 'C.JPG', '/tmp/foo', 10)); + + $fileModeliles = $fileModel->getAll(1); + $this->assertNotEmpty($fileModeliles); + $this->assertCount(4, $fileModeliles); + $this->assertEquals('A.png', $fileModeliles[0]['name']); + $this->assertEquals('B.pdf', $fileModeliles[1]['name']); + $this->assertEquals('C.JPG', $fileModeliles[2]['name']); + $this->assertEquals('D.doc', $fileModeliles[3]['name']); + + $fileModeliles = $fileModel->getAllImages(1); + $this->assertNotEmpty($fileModeliles); + $this->assertCount(2, $fileModeliles); + $this->assertEquals('A.png', $fileModeliles[0]['name']); + $this->assertEquals('C.JPG', $fileModeliles[1]['name']); + + $fileModeliles = $fileModel->getAllDocuments(1); + $this->assertNotEmpty($fileModeliles); + $this->assertCount(2, $fileModeliles); + $this->assertEquals('B.pdf', $fileModeliles[0]['name']); + $this->assertEquals('D.doc', $fileModeliles[1]['name']); + } + + public function testIsImage() + { + $fileModel = new TaskFileModel($this->container); + + $this->assertTrue($fileModel->isImage('test.png')); + $this->assertTrue($fileModel->isImage('test.jpeg')); + $this->assertTrue($fileModel->isImage('test.gif')); + $this->assertTrue($fileModel->isImage('test.jpg')); + $this->assertTrue($fileModel->isImage('test.JPG')); + + $this->assertFalse($fileModel->isImage('test.bmp')); + $this->assertFalse($fileModel->isImage('test')); + $this->assertFalse($fileModel->isImage('test.pdf')); + } + + public function testGetThumbnailPath() + { + $fileModel = new TaskFileModel($this->container); + $this->assertEquals('thumbnails'.DIRECTORY_SEPARATOR.'test', $fileModel->getThumbnailPath('test')); + } + + public function testGeneratePath() + { + $fileModel = new TaskFileModel($this->container); + + $this->assertStringStartsWith('tasks'.DIRECTORY_SEPARATOR.'34'.DIRECTORY_SEPARATOR, $fileModel->generatePath(34, 'test.png')); + $this->assertNotEquals($fileModel->generatePath(34, 'test1.png'), $fileModel->generatePath(34, 'test2.png')); + } + + public function testUploadFiles() + { + $fileModel = $this + ->getMockBuilder('\Kanboard\Model\TaskFileModel') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('generateThumbnailFromFile')) + ->getMock(); + + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $files = array( + 'name' => array( + 'file1.png', + 'file2.doc', + ), + 'tmp_name' => array( + '/tmp/phpYzdqkD', + '/tmp/phpeEwEWG', + ), + 'error' => array( + UPLOAD_ERR_OK, + UPLOAD_ERR_OK, + ), + 'size' => array( + 123, + 456, + ), + ); + + $fileModel + ->expects($this->once()) + ->method('generateThumbnailFromFile'); + + $this->container['objectStorage'] + ->expects($this->at(0)) + ->method('moveUploadedFile') + ->with($this->equalTo('/tmp/phpYzdqkD'), $this->anything()); + + $this->container['objectStorage'] + ->expects($this->at(1)) + ->method('moveUploadedFile') + ->with($this->equalTo('/tmp/phpeEwEWG'), $this->anything()); + + $this->assertTrue($fileModel->uploadFiles(1, $files)); + + $files = $fileModel->getAll(1); + $this->assertCount(2, $files); + + $this->assertEquals(1, $files[0]['id']); + $this->assertEquals('file1.png', $files[0]['name']); + $this->assertEquals(1, $files[0]['is_image']); + $this->assertEquals(1, $files[0]['task_id']); + $this->assertEquals(0, $files[0]['user_id']); + $this->assertEquals(123, $files[0]['size']); + $this->assertEquals(time(), $files[0]['date'], '', 2); + + $this->assertEquals(2, $files[1]['id']); + $this->assertEquals('file2.doc', $files[1]['name']); + $this->assertEquals(0, $files[1]['is_image']); + $this->assertEquals(1, $files[1]['task_id']); + $this->assertEquals(0, $files[1]['user_id']); + $this->assertEquals(456, $files[1]['size']); + $this->assertEquals(time(), $files[1]['date'], '', 2); + } + + public function testUploadFilesWithEmptyFiles() + { + $fileModel = new TaskFileModel($this->container); + $this->assertFalse($fileModel->uploadFiles(1, array())); + } + + public function testUploadFilesWithUploadError() + { + $files = array( + 'name' => array( + 'file1.png', + 'file2.doc', + ), + 'tmp_name' => array( + '', + '/tmp/phpeEwEWG', + ), + 'error' => array( + UPLOAD_ERR_CANT_WRITE, + UPLOAD_ERR_OK, + ), + 'size' => array( + 123, + 456, + ), + ); + + $fileModel = new TaskFileModel($this->container); + $this->assertFalse($fileModel->uploadFiles(1, $files)); + } + + public function testUploadFilesWithObjectStorageError() + { + $files = array( + 'name' => array( + 'file1.csv', + 'file2.doc', + ), + 'tmp_name' => array( + '/tmp/phpYzdqkD', + '/tmp/phpeEwEWG', + ), + 'error' => array( + UPLOAD_ERR_OK, + UPLOAD_ERR_OK, + ), + 'size' => array( + 123, + 456, + ), + ); + + $this->container['objectStorage'] + ->expects($this->at(0)) + ->method('moveUploadedFile') + ->with($this->equalTo('/tmp/phpYzdqkD'), $this->anything()) + ->will($this->throwException(new \Kanboard\Core\ObjectStorage\ObjectStorageException('test'))); + + $fileModel = new TaskFileModel($this->container); + $this->assertFalse($fileModel->uploadFiles(1, $files)); + } + + public function testUploadFileContent() + { + $fileModel = $this + ->getMockBuilder('\Kanboard\Model\TaskFileModel') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('generateThumbnailFromFile')) + ->getMock(); + + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $data = 'test'; + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $this->container['objectStorage'] + ->expects($this->once()) + ->method('put') + ->with($this->anything(), $this->equalTo($data)); + + $this->assertEquals(1, $fileModel->uploadContent(1, 'test.doc', base64_encode($data))); + + $files = $fileModel->getAll(1); + $this->assertCount(1, $files); + + $this->assertEquals(1, $files[0]['id']); + $this->assertEquals('test.doc', $files[0]['name']); + $this->assertEquals(0, $files[0]['is_image']); + $this->assertEquals(1, $files[0]['task_id']); + $this->assertEquals(0, $files[0]['user_id']); + $this->assertEquals(4, $files[0]['size']); + $this->assertEquals(time(), $files[0]['date'], '', 2); + } + + public function testUploadFileContentWithObjectStorageError() + { + $fileModel = $this + ->getMockBuilder('\Kanboard\Model\TaskFileModel') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('generateThumbnailFromFile')) + ->getMock(); + + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $data = 'test'; + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $this->container['objectStorage'] + ->expects($this->once()) + ->method('put') + ->with($this->anything(), $this->equalTo($data)) + ->will($this->throwException(new \Kanboard\Core\ObjectStorage\ObjectStorageException('test'))); + + $this->assertFalse($fileModel->uploadContent(1, 'test.doc', base64_encode($data))); + } + + public function testUploadScreenshot() + { + $fileModel = $this + ->getMockBuilder('\Kanboard\Model\TaskFileModel') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('generateThumbnailFromData')) + ->getMock(); + + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $data = 'test'; + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + + $fileModel + ->expects($this->once()) + ->method('generateThumbnailFromData'); + + $this->container['objectStorage'] + ->expects($this->once()) + ->method('put') + ->with($this->anything(), $this->equalTo($data)); + + $this->assertEquals(1, $fileModel->uploadScreenshot(1, base64_encode($data))); + + $files = $fileModel->getAll(1); + $this->assertCount(1, $files); + + $this->assertEquals(1, $files[0]['id']); + $this->assertStringStartsWith('Screenshot taken ', $files[0]['name']); + $this->assertEquals(1, $files[0]['is_image']); + $this->assertEquals(1, $files[0]['task_id']); + $this->assertEquals(0, $files[0]['user_id']); + $this->assertEquals(4, $files[0]['size']); + $this->assertEquals(time(), $files[0]['date'], '', 2); + } + + public function testRemove() + { + $fileModel = new TaskFileModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(1, $fileModel->create(1, 'test', 'tmp/foo', 10)); + + $this->container['objectStorage'] + ->expects($this->once()) + ->method('remove') + ->with('tmp/foo'); + + $this->assertTrue($fileModel->remove(1)); + } + + public function testRemoveWithObjectStorageError() + { + $fileModel = new TaskFileModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(1, $fileModel->create(1, 'test', 'tmp/foo', 10)); + + $this->container['objectStorage'] + ->expects($this->once()) + ->method('remove') + ->with('tmp/foo') + ->will($this->throwException(new \Kanboard\Core\ObjectStorage\ObjectStorageException('test'))); + + $this->assertFalse($fileModel->remove(1)); + } + + public function testRemoveImage() + { + $fileModel = new TaskFileModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(1, $fileModel->create(1, 'image.gif', 'tmp/image.gif', 10)); + + $this->container['objectStorage'] + ->expects($this->at(0)) + ->method('remove') + ->with('tmp/image.gif'); + + $this->container['objectStorage'] + ->expects($this->at(1)) + ->method('remove') + ->with('thumbnails'.DIRECTORY_SEPARATOR.'tmp/image.gif'); + + $this->assertTrue($fileModel->remove(1)); + } + + public function testRemoveAll() + { + $fileModel = new TaskFileModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(1, $fileModel->create(1, 'test', 'tmp/foo', 10)); + $this->assertEquals(2, $fileModel->create(1, 'test', 'tmp/foo', 10)); + + $this->container['objectStorage'] + ->expects($this->exactly(2)) + ->method('remove') + ->with('tmp/foo'); + + $this->assertTrue($fileModel->removeAll(1)); + } + + public function testGetProjectId() + { + $projectModel = new ProjectModel($this->container); + $fileModel = new TaskFileModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + $this->assertEquals(1, $fileModel->create(1, 'test', '/tmp/foobar', 10)); + $this->assertEquals(1, $fileModel->getProjectId(1)); + $this->assertEquals(0, $fileModel->getProjectId(2)); + } +} diff --git a/tests/units/Model/TaskFileTest.php b/tests/units/Model/TaskFileTest.php deleted file mode 100644 index 2faee95c..00000000 --- a/tests/units/Model/TaskFileTest.php +++ /dev/null @@ -1,445 +0,0 @@ -container); - $fileModel = new TaskFileModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - - $this->assertEquals(1, $fileModel->create(1, 'test', '/tmp/foo', 10)); - - $file = $fileModel->getById(1); - $this->assertEquals('test', $file['name']); - $this->assertEquals('/tmp/foo', $file['path']); - $this->assertEquals(0, $file['is_image']); - $this->assertEquals(1, $file['task_id']); - $this->assertEquals(time(), $file['date'], '', 2); - $this->assertEquals(0, $file['user_id']); - $this->assertEquals(10, $file['size']); - - $this->assertEquals(2, $fileModel->create(1, 'test2.png', '/tmp/foobar', 10)); - - $file = $fileModel->getById(2); - $this->assertEquals('test2.png', $file['name']); - $this->assertEquals('/tmp/foobar', $file['path']); - $this->assertEquals(1, $file['is_image']); - } - - public function testCreationWithFileNameTooLong() - { - $projectModel = new ProjectModel($this->container); - $fileModel = new TaskFileModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - - $this->assertNotFalse($fileModel->create(1, 'test', '/tmp/foo', 10)); - $this->assertNotFalse($fileModel->create(1, str_repeat('a', 1000), '/tmp/foo', 10)); - - $files = $fileModel->getAll(1); - $this->assertNotEmpty($files); - $this->assertCount(2, $files); - - $this->assertEquals(str_repeat('a', 255), $files[0]['name']); - $this->assertEquals('test', $files[1]['name']); - } - - public function testCreationWithSessionOpen() - { - $this->container['sessionStorage']->user = array('id' => 1); - - $projectModel = new ProjectModel($this->container); - $fileModel = new TaskFileModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $this->assertEquals(1, $fileModel->create(1, 'test', '/tmp/foo', 10)); - - $file = $fileModel->getById(1); - $this->assertEquals('test', $file['name']); - $this->assertEquals(1, $file['user_id']); - } - - public function testGetAll() - { - $projectModel = new ProjectModel($this->container); - $fileModel = new TaskFileModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - - $this->assertEquals(1, $fileModel->create(1, 'B.pdf', '/tmp/foo', 10)); - $this->assertEquals(2, $fileModel->create(1, 'A.png', '/tmp/foo', 10)); - $this->assertEquals(3, $fileModel->create(1, 'D.doc', '/tmp/foo', 10)); - $this->assertEquals(4, $fileModel->create(1, 'C.JPG', '/tmp/foo', 10)); - - $fileModeliles = $fileModel->getAll(1); - $this->assertNotEmpty($fileModeliles); - $this->assertCount(4, $fileModeliles); - $this->assertEquals('A.png', $fileModeliles[0]['name']); - $this->assertEquals('B.pdf', $fileModeliles[1]['name']); - $this->assertEquals('C.JPG', $fileModeliles[2]['name']); - $this->assertEquals('D.doc', $fileModeliles[3]['name']); - - $fileModeliles = $fileModel->getAllImages(1); - $this->assertNotEmpty($fileModeliles); - $this->assertCount(2, $fileModeliles); - $this->assertEquals('A.png', $fileModeliles[0]['name']); - $this->assertEquals('C.JPG', $fileModeliles[1]['name']); - - $fileModeliles = $fileModel->getAllDocuments(1); - $this->assertNotEmpty($fileModeliles); - $this->assertCount(2, $fileModeliles); - $this->assertEquals('B.pdf', $fileModeliles[0]['name']); - $this->assertEquals('D.doc', $fileModeliles[1]['name']); - } - - public function testIsImage() - { - $fileModel = new TaskFileModel($this->container); - - $this->assertTrue($fileModel->isImage('test.png')); - $this->assertTrue($fileModel->isImage('test.jpeg')); - $this->assertTrue($fileModel->isImage('test.gif')); - $this->assertTrue($fileModel->isImage('test.jpg')); - $this->assertTrue($fileModel->isImage('test.JPG')); - - $this->assertFalse($fileModel->isImage('test.bmp')); - $this->assertFalse($fileModel->isImage('test')); - $this->assertFalse($fileModel->isImage('test.pdf')); - } - - public function testGetThumbnailPath() - { - $fileModel = new TaskFileModel($this->container); - $this->assertEquals('thumbnails'.DIRECTORY_SEPARATOR.'test', $fileModel->getThumbnailPath('test')); - } - - public function testGeneratePath() - { - $fileModel = new TaskFileModel($this->container); - - $this->assertStringStartsWith('tasks'.DIRECTORY_SEPARATOR.'34'.DIRECTORY_SEPARATOR, $fileModel->generatePath(34, 'test.png')); - $this->assertNotEquals($fileModel->generatePath(34, 'test1.png'), $fileModel->generatePath(34, 'test2.png')); - } - - public function testUploadFiles() - { - $fileModel = $this - ->getMockBuilder('\Kanboard\Model\TaskFileModel') - ->setConstructorArgs(array($this->container)) - ->setMethods(array('generateThumbnailFromFile')) - ->getMock(); - - $projectModel = new ProjectModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - - $files = array( - 'name' => array( - 'file1.png', - 'file2.doc', - ), - 'tmp_name' => array( - '/tmp/phpYzdqkD', - '/tmp/phpeEwEWG', - ), - 'error' => array( - UPLOAD_ERR_OK, - UPLOAD_ERR_OK, - ), - 'size' => array( - 123, - 456, - ), - ); - - $fileModel - ->expects($this->once()) - ->method('generateThumbnailFromFile'); - - $this->container['objectStorage'] - ->expects($this->at(0)) - ->method('moveUploadedFile') - ->with($this->equalTo('/tmp/phpYzdqkD'), $this->anything()); - - $this->container['objectStorage'] - ->expects($this->at(1)) - ->method('moveUploadedFile') - ->with($this->equalTo('/tmp/phpeEwEWG'), $this->anything()); - - $this->assertTrue($fileModel->uploadFiles(1, $files)); - - $files = $fileModel->getAll(1); - $this->assertCount(2, $files); - - $this->assertEquals(1, $files[0]['id']); - $this->assertEquals('file1.png', $files[0]['name']); - $this->assertEquals(1, $files[0]['is_image']); - $this->assertEquals(1, $files[0]['task_id']); - $this->assertEquals(0, $files[0]['user_id']); - $this->assertEquals(123, $files[0]['size']); - $this->assertEquals(time(), $files[0]['date'], '', 2); - - $this->assertEquals(2, $files[1]['id']); - $this->assertEquals('file2.doc', $files[1]['name']); - $this->assertEquals(0, $files[1]['is_image']); - $this->assertEquals(1, $files[1]['task_id']); - $this->assertEquals(0, $files[1]['user_id']); - $this->assertEquals(456, $files[1]['size']); - $this->assertEquals(time(), $files[1]['date'], '', 2); - } - - public function testUploadFilesWithEmptyFiles() - { - $fileModel = new TaskFileModel($this->container); - $this->assertFalse($fileModel->uploadFiles(1, array())); - } - - public function testUploadFilesWithUploadError() - { - $files = array( - 'name' => array( - 'file1.png', - 'file2.doc', - ), - 'tmp_name' => array( - '', - '/tmp/phpeEwEWG', - ), - 'error' => array( - UPLOAD_ERR_CANT_WRITE, - UPLOAD_ERR_OK, - ), - 'size' => array( - 123, - 456, - ), - ); - - $fileModel = new TaskFileModel($this->container); - $this->assertFalse($fileModel->uploadFiles(1, $files)); - } - - public function testUploadFilesWithObjectStorageError() - { - $files = array( - 'name' => array( - 'file1.csv', - 'file2.doc', - ), - 'tmp_name' => array( - '/tmp/phpYzdqkD', - '/tmp/phpeEwEWG', - ), - 'error' => array( - UPLOAD_ERR_OK, - UPLOAD_ERR_OK, - ), - 'size' => array( - 123, - 456, - ), - ); - - $this->container['objectStorage'] - ->expects($this->at(0)) - ->method('moveUploadedFile') - ->with($this->equalTo('/tmp/phpYzdqkD'), $this->anything()) - ->will($this->throwException(new \Kanboard\Core\ObjectStorage\ObjectStorageException('test'))); - - $fileModel = new TaskFileModel($this->container); - $this->assertFalse($fileModel->uploadFiles(1, $files)); - } - - public function testUploadFileContent() - { - $fileModel = $this - ->getMockBuilder('\Kanboard\Model\TaskFileModel') - ->setConstructorArgs(array($this->container)) - ->setMethods(array('generateThumbnailFromFile')) - ->getMock(); - - $projectModel = new ProjectModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - $data = 'test'; - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - - $this->container['objectStorage'] - ->expects($this->once()) - ->method('put') - ->with($this->anything(), $this->equalTo($data)); - - $this->assertEquals(1, $fileModel->uploadContent(1, 'test.doc', base64_encode($data))); - - $files = $fileModel->getAll(1); - $this->assertCount(1, $files); - - $this->assertEquals(1, $files[0]['id']); - $this->assertEquals('test.doc', $files[0]['name']); - $this->assertEquals(0, $files[0]['is_image']); - $this->assertEquals(1, $files[0]['task_id']); - $this->assertEquals(0, $files[0]['user_id']); - $this->assertEquals(4, $files[0]['size']); - $this->assertEquals(time(), $files[0]['date'], '', 2); - } - - public function testUploadFileContentWithObjectStorageError() - { - $fileModel = $this - ->getMockBuilder('\Kanboard\Model\TaskFileModel') - ->setConstructorArgs(array($this->container)) - ->setMethods(array('generateThumbnailFromFile')) - ->getMock(); - - $projectModel = new ProjectModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - $data = 'test'; - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - - $this->container['objectStorage'] - ->expects($this->once()) - ->method('put') - ->with($this->anything(), $this->equalTo($data)) - ->will($this->throwException(new \Kanboard\Core\ObjectStorage\ObjectStorageException('test'))); - - $this->assertFalse($fileModel->uploadContent(1, 'test.doc', base64_encode($data))); - } - - public function testUploadScreenshot() - { - $fileModel = $this - ->getMockBuilder('\Kanboard\Model\TaskFileModel') - ->setConstructorArgs(array($this->container)) - ->setMethods(array('generateThumbnailFromData')) - ->getMock(); - - $projectModel = new ProjectModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - $data = 'test'; - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - - $fileModel - ->expects($this->once()) - ->method('generateThumbnailFromData'); - - $this->container['objectStorage'] - ->expects($this->once()) - ->method('put') - ->with($this->anything(), $this->equalTo($data)); - - $this->assertEquals(1, $fileModel->uploadScreenshot(1, base64_encode($data))); - - $files = $fileModel->getAll(1); - $this->assertCount(1, $files); - - $this->assertEquals(1, $files[0]['id']); - $this->assertStringStartsWith('Screenshot taken ', $files[0]['name']); - $this->assertEquals(1, $files[0]['is_image']); - $this->assertEquals(1, $files[0]['task_id']); - $this->assertEquals(0, $files[0]['user_id']); - $this->assertEquals(4, $files[0]['size']); - $this->assertEquals(time(), $files[0]['date'], '', 2); - } - - public function testRemove() - { - $fileModel = new TaskFileModel($this->container); - $projectModel = new ProjectModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $this->assertEquals(1, $fileModel->create(1, 'test', 'tmp/foo', 10)); - - $this->container['objectStorage'] - ->expects($this->once()) - ->method('remove') - ->with('tmp/foo'); - - $this->assertTrue($fileModel->remove(1)); - } - - public function testRemoveWithObjectStorageError() - { - $fileModel = new TaskFileModel($this->container); - $projectModel = new ProjectModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $this->assertEquals(1, $fileModel->create(1, 'test', 'tmp/foo', 10)); - - $this->container['objectStorage'] - ->expects($this->once()) - ->method('remove') - ->with('tmp/foo') - ->will($this->throwException(new \Kanboard\Core\ObjectStorage\ObjectStorageException('test'))); - - $this->assertFalse($fileModel->remove(1)); - } - - public function testRemoveImage() - { - $fileModel = new TaskFileModel($this->container); - $projectModel = new ProjectModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $this->assertEquals(1, $fileModel->create(1, 'image.gif', 'tmp/image.gif', 10)); - - $this->container['objectStorage'] - ->expects($this->at(0)) - ->method('remove') - ->with('tmp/image.gif'); - - $this->container['objectStorage'] - ->expects($this->at(1)) - ->method('remove') - ->with('thumbnails'.DIRECTORY_SEPARATOR.'tmp/image.gif'); - - $this->assertTrue($fileModel->remove(1)); - } - - public function testRemoveAll() - { - $fileModel = new TaskFileModel($this->container); - $projectModel = new ProjectModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); - $this->assertEquals(1, $fileModel->create(1, 'test', 'tmp/foo', 10)); - $this->assertEquals(2, $fileModel->create(1, 'test', 'tmp/foo', 10)); - - $this->container['objectStorage'] - ->expects($this->exactly(2)) - ->method('remove') - ->with('tmp/foo'); - - $this->assertTrue($fileModel->removeAll(1)); - } -} diff --git a/tests/units/Model/TaskLinkModelTest.php b/tests/units/Model/TaskLinkModelTest.php new file mode 100644 index 00000000..78590891 --- /dev/null +++ b/tests/units/Model/TaskLinkModelTest.php @@ -0,0 +1,211 @@ +container); + $taskLinkModel = new TaskLinkModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A'))); + $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B'))); + $this->assertEquals(3, $taskCreationModel->create(array('project_id' => 1, 'title' => 'C'))); + + $this->assertNotFalse($taskLinkModel->create(1, 2, 9)); + $this->assertNotFalse($taskLinkModel->create(1, 3, 9)); + + $task = $taskFinderModel->getExtendedQuery()->findOne(); + $this->assertNotEmpty($task); + } + + public function testCreateTaskLinkWithNoOpposite() + { + $taskLinkModel = new TaskLinkModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A'))); + $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B'))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); + + $links = $taskLinkModel->getAll(1); + $this->assertNotEmpty($links); + $this->assertCount(1, $links); + $this->assertEquals('relates to', $links[0]['label']); + $this->assertEquals('B', $links[0]['title']); + $this->assertEquals(2, $links[0]['task_id']); + $this->assertEquals(1, $links[0]['is_active']); + + $links = $taskLinkModel->getAll(2); + $this->assertNotEmpty($links); + $this->assertCount(1, $links); + $this->assertEquals('relates to', $links[0]['label']); + $this->assertEquals('A', $links[0]['title']); + $this->assertEquals(1, $links[0]['task_id']); + $this->assertEquals(1, $links[0]['is_active']); + + $task_link = $taskLinkModel->getById(1); + $this->assertNotEmpty($task_link); + $this->assertEquals(1, $task_link['id']); + $this->assertEquals(1, $task_link['task_id']); + $this->assertEquals(2, $task_link['opposite_task_id']); + $this->assertEquals(1, $task_link['link_id']); + + $opposite_task_link = $taskLinkModel->getOppositeTaskLink($task_link); + $this->assertNotEmpty($opposite_task_link); + $this->assertEquals(2, $opposite_task_link['id']); + $this->assertEquals(2, $opposite_task_link['task_id']); + $this->assertEquals(1, $opposite_task_link['opposite_task_id']); + $this->assertEquals(1, $opposite_task_link['link_id']); + } + + public function testCreateTaskLinkWithOpposite() + { + $taskLinkModel = new TaskLinkModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A'))); + $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B'))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 2)); + + $links = $taskLinkModel->getAll(1); + $this->assertNotEmpty($links); + $this->assertCount(1, $links); + $this->assertEquals('blocks', $links[0]['label']); + $this->assertEquals('B', $links[0]['title']); + $this->assertEquals(2, $links[0]['task_id']); + $this->assertEquals(1, $links[0]['is_active']); + + $links = $taskLinkModel->getAll(2); + $this->assertNotEmpty($links); + $this->assertCount(1, $links); + $this->assertEquals('is blocked by', $links[0]['label']); + $this->assertEquals('A', $links[0]['title']); + $this->assertEquals(1, $links[0]['task_id']); + $this->assertEquals(1, $links[0]['is_active']); + + $task_link = $taskLinkModel->getById(1); + $this->assertNotEmpty($task_link); + $this->assertEquals(1, $task_link['id']); + $this->assertEquals(1, $task_link['task_id']); + $this->assertEquals(2, $task_link['opposite_task_id']); + $this->assertEquals(2, $task_link['link_id']); + + $opposite_task_link = $taskLinkModel->getOppositeTaskLink($task_link); + $this->assertNotEmpty($opposite_task_link); + $this->assertEquals(2, $opposite_task_link['id']); + $this->assertEquals(2, $opposite_task_link['task_id']); + $this->assertEquals(1, $opposite_task_link['opposite_task_id']); + $this->assertEquals(3, $opposite_task_link['link_id']); + } + + public function testGroupByLabel() + { + $taskLinkModel = new TaskLinkModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A'))); + $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B'))); + $this->assertEquals(3, $taskCreationModel->create(array('project_id' => 1, 'title' => 'C'))); + + $this->assertNotFalse($taskLinkModel->create(1, 2, 2)); + $this->assertNotFalse($taskLinkModel->create(1, 3, 2)); + + $links = $taskLinkModel->getAllGroupedByLabel(1); + $this->assertCount(1, $links); + $this->assertArrayHasKey('blocks', $links); + $this->assertCount(2, $links['blocks']); + $this->assertEquals('test', $links['blocks'][0]['project_name']); + $this->assertEquals('Backlog', $links['blocks'][0]['column_title']); + $this->assertEquals('blocks', $links['blocks'][0]['label']); + } + + public function testUpdate() + { + $taskLinkModel = new TaskLinkModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($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' => 'A'))); + $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 2, 'title' => 'B'))); + $this->assertEquals(3, $taskCreationModel->create(array('project_id' => 1, 'title' => 'C'))); + + $this->assertEquals(1, $taskLinkModel->create(1, 2, 5)); + $this->assertTrue($taskLinkModel->update(1, 1, 3, 11)); + + $links = $taskLinkModel->getAll(1); + $this->assertNotEmpty($links); + $this->assertCount(1, $links); + $this->assertEquals('is fixed by', $links[0]['label']); + $this->assertEquals('C', $links[0]['title']); + $this->assertEquals(3, $links[0]['task_id']); + + $links = $taskLinkModel->getAll(2); + $this->assertEmpty($links); + + $links = $taskLinkModel->getAll(3); + $this->assertNotEmpty($links); + $this->assertCount(1, $links); + $this->assertEquals('fixes', $links[0]['label']); + $this->assertEquals('A', $links[0]['title']); + $this->assertEquals(1, $links[0]['task_id']); + } + + public function testRemove() + { + $taskLinkModel = new TaskLinkModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A'))); + $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B'))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 2)); + + $links = $taskLinkModel->getAll(1); + $this->assertNotEmpty($links); + $links = $taskLinkModel->getAll(2); + $this->assertNotEmpty($links); + + $this->assertTrue($taskLinkModel->remove($links[0]['id'])); + + $links = $taskLinkModel->getAll(1); + $this->assertEmpty($links); + $links = $taskLinkModel->getAll(2); + $this->assertEmpty($links); + } + + public function testGetProjectId() + { + $taskLinkModel = new TaskLinkModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A'))); + $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B'))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 2)); + + $this->assertEquals(1, $taskLinkModel->getProjectId(1)); + $this->assertEquals(0, $taskLinkModel->getProjectId(42)); + } +} diff --git a/tests/units/Model/TaskLinkTest.php b/tests/units/Model/TaskLinkTest.php deleted file mode 100644 index bc574731..00000000 --- a/tests/units/Model/TaskLinkTest.php +++ /dev/null @@ -1,196 +0,0 @@ -container); - $tl = new TaskLinkModel($this->container); - $p = new ProjectModel($this->container); - $tc = new TaskCreationModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'A'))); - $this->assertEquals(2, $tc->create(array('project_id' => 1, 'title' => 'B'))); - $this->assertEquals(3, $tc->create(array('project_id' => 1, 'title' => 'C'))); - - $this->assertNotFalse($tl->create(1, 2, 9)); - $this->assertNotFalse($tl->create(1, 3, 9)); - - $task = $tf->getExtendedQuery()->findOne(); - $this->assertNotEmpty($task); - } - - public function testCreateTaskLinkWithNoOpposite() - { - $tl = new TaskLinkModel($this->container); - $p = new ProjectModel($this->container); - $tc = new TaskCreationModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'A'))); - $this->assertEquals(2, $tc->create(array('project_id' => 1, 'title' => 'B'))); - $this->assertEquals(1, $tl->create(1, 2, 1)); - - $links = $tl->getAll(1); - $this->assertNotEmpty($links); - $this->assertCount(1, $links); - $this->assertEquals('relates to', $links[0]['label']); - $this->assertEquals('B', $links[0]['title']); - $this->assertEquals(2, $links[0]['task_id']); - $this->assertEquals(1, $links[0]['is_active']); - - $links = $tl->getAll(2); - $this->assertNotEmpty($links); - $this->assertCount(1, $links); - $this->assertEquals('relates to', $links[0]['label']); - $this->assertEquals('A', $links[0]['title']); - $this->assertEquals(1, $links[0]['task_id']); - $this->assertEquals(1, $links[0]['is_active']); - - $task_link = $tl->getById(1); - $this->assertNotEmpty($task_link); - $this->assertEquals(1, $task_link['id']); - $this->assertEquals(1, $task_link['task_id']); - $this->assertEquals(2, $task_link['opposite_task_id']); - $this->assertEquals(1, $task_link['link_id']); - - $opposite_task_link = $tl->getOppositeTaskLink($task_link); - $this->assertNotEmpty($opposite_task_link); - $this->assertEquals(2, $opposite_task_link['id']); - $this->assertEquals(2, $opposite_task_link['task_id']); - $this->assertEquals(1, $opposite_task_link['opposite_task_id']); - $this->assertEquals(1, $opposite_task_link['link_id']); - } - - public function testCreateTaskLinkWithOpposite() - { - $tl = new TaskLinkModel($this->container); - $p = new ProjectModel($this->container); - $tc = new TaskCreationModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'A'))); - $this->assertEquals(2, $tc->create(array('project_id' => 1, 'title' => 'B'))); - $this->assertEquals(1, $tl->create(1, 2, 2)); - - $links = $tl->getAll(1); - $this->assertNotEmpty($links); - $this->assertCount(1, $links); - $this->assertEquals('blocks', $links[0]['label']); - $this->assertEquals('B', $links[0]['title']); - $this->assertEquals(2, $links[0]['task_id']); - $this->assertEquals(1, $links[0]['is_active']); - - $links = $tl->getAll(2); - $this->assertNotEmpty($links); - $this->assertCount(1, $links); - $this->assertEquals('is blocked by', $links[0]['label']); - $this->assertEquals('A', $links[0]['title']); - $this->assertEquals(1, $links[0]['task_id']); - $this->assertEquals(1, $links[0]['is_active']); - - $task_link = $tl->getById(1); - $this->assertNotEmpty($task_link); - $this->assertEquals(1, $task_link['id']); - $this->assertEquals(1, $task_link['task_id']); - $this->assertEquals(2, $task_link['opposite_task_id']); - $this->assertEquals(2, $task_link['link_id']); - - $opposite_task_link = $tl->getOppositeTaskLink($task_link); - $this->assertNotEmpty($opposite_task_link); - $this->assertEquals(2, $opposite_task_link['id']); - $this->assertEquals(2, $opposite_task_link['task_id']); - $this->assertEquals(1, $opposite_task_link['opposite_task_id']); - $this->assertEquals(3, $opposite_task_link['link_id']); - } - - public function testGroupByLabel() - { - $tl = new TaskLinkModel($this->container); - $p = new ProjectModel($this->container); - $tc = new TaskCreationModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - - $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'A'))); - $this->assertEquals(2, $tc->create(array('project_id' => 1, 'title' => 'B'))); - $this->assertEquals(3, $tc->create(array('project_id' => 1, 'title' => 'C'))); - - $this->assertNotFalse($tl->create(1, 2, 2)); - $this->assertNotFalse($tl->create(1, 3, 2)); - - $links = $tl->getAllGroupedByLabel(1); - $this->assertCount(1, $links); - $this->assertArrayHasKey('blocks', $links); - $this->assertCount(2, $links['blocks']); - $this->assertEquals('test', $links['blocks'][0]['project_name']); - $this->assertEquals('Backlog', $links['blocks'][0]['column_title']); - $this->assertEquals('blocks', $links['blocks'][0]['label']); - } - - public function testUpdate() - { - $tl = new TaskLinkModel($this->container); - $p = new ProjectModel($this->container); - $tc = new TaskCreationModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'A'))); - $this->assertEquals(2, $tc->create(array('project_id' => 2, 'title' => 'B'))); - $this->assertEquals(3, $tc->create(array('project_id' => 1, 'title' => 'C'))); - - $this->assertEquals(1, $tl->create(1, 2, 5)); - $this->assertTrue($tl->update(1, 1, 3, 11)); - - $links = $tl->getAll(1); - $this->assertNotEmpty($links); - $this->assertCount(1, $links); - $this->assertEquals('is fixed by', $links[0]['label']); - $this->assertEquals('C', $links[0]['title']); - $this->assertEquals(3, $links[0]['task_id']); - - $links = $tl->getAll(2); - $this->assertEmpty($links); - - $links = $tl->getAll(3); - $this->assertNotEmpty($links); - $this->assertCount(1, $links); - $this->assertEquals('fixes', $links[0]['label']); - $this->assertEquals('A', $links[0]['title']); - $this->assertEquals(1, $links[0]['task_id']); - } - - public function testRemove() - { - $tl = new TaskLinkModel($this->container); - $p = new ProjectModel($this->container); - $tc = new TaskCreationModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'A'))); - $this->assertEquals(2, $tc->create(array('project_id' => 1, 'title' => 'B'))); - $this->assertEquals(1, $tl->create(1, 2, 2)); - - $links = $tl->getAll(1); - $this->assertNotEmpty($links); - $links = $tl->getAll(2); - $this->assertNotEmpty($links); - - $this->assertTrue($tl->remove($links[0]['id'])); - - $links = $tl->getAll(1); - $this->assertEmpty($links); - $links = $tl->getAll(2); - $this->assertEmpty($links); - } -} -- cgit v1.2.3 From 3d34681610854474cb9dbdd93886dbcf0e208a99 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 26 Jun 2016 14:33:53 -0400 Subject: Added new API calls for external task links --- ChangeLog | 1 + app/Api/Procedure/TaskExternalLinkProcedure.php | 106 ++++++++++ app/Core/ExternalLink/ExternalLinkManager.php | 24 +++ app/ServiceProvider/ApiProvider.php | 2 + app/ServiceProvider/AuthenticationProvider.php | 1 + doc/api-external-task-link-procedures.markdown | 221 +++++++++++++++++++++ doc/api-internal-task-link-procedures.markdown | 187 +++++++++++++++++ doc/api-json-rpc.markdown | 2 + doc/api-link-procedures.markdown | 185 ----------------- .../integration/TaskExternalLinkProcedureTest.php | 98 +++++++++ 10 files changed, 642 insertions(+), 185 deletions(-) create mode 100644 app/Api/Procedure/TaskExternalLinkProcedure.php create mode 100644 doc/api-external-task-link-procedures.markdown create mode 100644 doc/api-internal-task-link-procedures.markdown create mode 100644 tests/integration/TaskExternalLinkProcedureTest.php (limited to 'app/Core') diff --git a/ChangeLog b/ChangeLog index 883cc6cf..85966ed8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ New features: * Added application and project roles validation for API procedure calls * Added new API call: "getProjectByIdentifier" +* Added new API calls for external task links Improvements: diff --git a/app/Api/Procedure/TaskExternalLinkProcedure.php b/app/Api/Procedure/TaskExternalLinkProcedure.php new file mode 100644 index 00000000..05ec6906 --- /dev/null +++ b/app/Api/Procedure/TaskExternalLinkProcedure.php @@ -0,0 +1,106 @@ +externalLinkManager->getTypes(); + } + + public function getExternalTaskLinkProviderDependencies($providerName) + { + try { + return $this->externalLinkManager->getProvider($providerName)->getDependencies(); + } catch (ExternalLinkProviderNotFound $e) { + $this->logger->error(__METHOD__.': '.$e->getMessage()); + return false; + } + } + + public function getExternalTaskLinkById($task_id, $link_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getExternalTaskLink', $task_id); + return $this->taskExternalLinkModel->getById($link_id); + } + + public function getAllExternalTaskLinks($task_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getExternalTaskLinks', $task_id); + return $this->taskExternalLinkModel->getAll($task_id); + } + + public function createExternalTaskLink($task_id, $url, $dependency, $type = ExternalLinkManager::TYPE_AUTO, $title = '') + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createExternalTaskLink', $task_id); + + try { + $provider = $this->externalLinkManager + ->setUserInputText($url) + ->setUserInputType($type) + ->find(); + + $link = $provider->getLink(); + + $values = array( + 'task_id' => $task_id, + 'title' => $title ?: $link->getTitle(), + 'url' => $link->getUrl(), + 'link_type' => $provider->getType(), + 'dependency' => $dependency, + ); + + list($valid, $errors) = $this->externalLinkValidator->validateCreation($values); + + if (! $valid) { + $this->logger->error(__METHOD__.': '.var_export($errors)); + return false; + } + + return $this->taskExternalLinkModel->create($values); + } catch (ExternalLinkProviderNotFound $e) { + $this->logger->error(__METHOD__.': '.$e->getMessage()); + } + + return false; + } + + public function updateExternalTaskLink($task_id, $link_id, $title = null, $url = null, $dependency = null) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateExternalTaskLink', $task_id); + + $link = $this->taskExternalLinkModel->getById($link_id); + $values = $this->filterValues(array( + 'title' => $title, + 'url' => $url, + 'dependency' => $dependency, + )); + + $values = array_merge($link, $values); + list($valid, $errors) = $this->externalLinkValidator->validateModification($values); + + if (! $valid) { + $this->logger->error(__METHOD__.': '.var_export($errors)); + return false; + } + + return $this->taskExternalLinkModel->update($values); + } + + public function removeExternalTaskLink($task_id, $link_id) + { + TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeExternalTaskLink', $task_id); + return $this->taskExternalLinkModel->remove($link_id); + } +} diff --git a/app/Core/ExternalLink/ExternalLinkManager.php b/app/Core/ExternalLink/ExternalLinkManager.php index 804e6b34..5a037999 100644 --- a/app/Core/ExternalLink/ExternalLinkManager.php +++ b/app/Core/ExternalLink/ExternalLinkManager.php @@ -152,6 +152,30 @@ class ExternalLinkManager extends Base return $this; } + /** + * Set provider type + * + * @access public + * @param string $userInputType + * @return ExternalLinkManager + */ + public function setUserInputType($userInputType) + { + $this->userInputType = $userInputType; + return $this; + } + + /** + * Set external link + * @param string $userInputText + * @return ExternalLinkManager + */ + public function setUserInputText($userInputText) + { + $this->userInputText = $userInputText; + return $this; + } + /** * Find a provider that user input * diff --git a/app/ServiceProvider/ApiProvider.php b/app/ServiceProvider/ApiProvider.php index f88d9b4f..194bee5b 100644 --- a/app/ServiceProvider/ApiProvider.php +++ b/app/ServiceProvider/ApiProvider.php @@ -9,6 +9,7 @@ use Kanboard\Api\Procedure\BoardProcedure; use Kanboard\Api\Procedure\CategoryProcedure; use Kanboard\Api\Procedure\ColumnProcedure; use Kanboard\Api\Procedure\CommentProcedure; +use Kanboard\Api\Procedure\TaskExternalLinkProcedure; use Kanboard\Api\Procedure\TaskFileProcedure; use Kanboard\Api\Procedure\GroupProcedure; use Kanboard\Api\Procedure\GroupMemberProcedure; @@ -65,6 +66,7 @@ class ApiProvider implements ServiceProviderInterface ->withObject(new SwimlaneProcedure($container)) ->withObject(new TaskProcedure($container)) ->withObject(new TaskLinkProcedure($container)) + ->withObject(new TaskExternalLinkProcedure($container)) ->withObject(new UserProcedure($container)) ->withObject(new GroupProcedure($container)) ->withObject(new GroupMemberProcedure($container)) diff --git a/app/ServiceProvider/AuthenticationProvider.php b/app/ServiceProvider/AuthenticationProvider.php index 751fe514..34b81b9d 100644 --- a/app/ServiceProvider/AuthenticationProvider.php +++ b/app/ServiceProvider/AuthenticationProvider.php @@ -204,6 +204,7 @@ class AuthenticationProvider implements ServiceProviderInterface $acl->add('SwimlaneProcedure', '*', Role::PROJECT_MANAGER); $acl->add('TaskFileProcedure', '*', Role::PROJECT_MEMBER); $acl->add('TaskLinkProcedure', '*', Role::PROJECT_MEMBER); + $acl->add('TaskExternalLinkProcedure', array('createExternalTaskLink', 'updateExternalTaskLink', 'removeExternalTaskLink'), Role::PROJECT_MEMBER); $acl->add('TaskProcedure', '*', Role::PROJECT_MEMBER); return $acl; diff --git a/doc/api-external-task-link-procedures.markdown b/doc/api-external-task-link-procedures.markdown new file mode 100644 index 00000000..2858be86 --- /dev/null +++ b/doc/api-external-task-link-procedures.markdown @@ -0,0 +1,221 @@ +Internal Task Links API Procedures +================================== + +## getExternalTaskLinkTypes + +- Purpose: **Get all registered external link providers** +- Parameters: **none** +- Result on success: **dict** +- Result on failure: **false** + +Request example: + +```json +{"jsonrpc":"2.0","method":"getExternalTaskLinkTypes","id":477370568} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "result": { + "auto": "Auto", + "attachment": "Attachment", + "file": "Local File", + "weblink": "Web Link" + }, + "id": 477370568 +} +``` + +## getExternalTaskLinkProviderDependencies + +- Purpose: **Get available dependencies for a given provider** +- Parameters: + - **providerName** (string, required) +- Result on success: **dict** +- Result on failure: **false** + +Request example: + +```json +{"jsonrpc":"2.0","method":"getExternalTaskLinkProviderDependencies","id":124790226,"params":["weblink"]} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "result": { + "related": "Related" + }, + "id": 124790226 +} +``` + +## createExternalTaskLink + +- Purpose: **Create a new external link** +- Parameters: + - **task_id** (integer, required) + - **url** (string, required) + - **dependency** (string, required) + - **type** (string, optional) + - **title** (string, optional) +- Result on success: **link_id** +- Result on failure: **false** + +Request example: + +```json +{"jsonrpc":"2.0","method":"createExternalTaskLink","id":924217495,"params":[9,"http:\/\/localhost\/document.pdf","related","attachment"]} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "result": 1, + "id": 924217495 +} +``` + +## updateExternalTaskLink + +- Purpose: **Update external task link** +- Parameters: + - **task_id** (integer, required) + - **link_id** (integer, required) + - **title** (string, required) + - **url** (string, required) + - **dependency** (string, required) +- Result on success: **true** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc":"2.0", + "method":"updateExternalTaskLink", + "id":1123562620, + "params": { + "task_id":9, + "link_id":1, + "title":"New title" + } +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "result": true, + "id": 1123562620 +} +``` + +## getExternalTaskLinkById + +- Purpose: **Get an external task link** +- Parameters: + - **task_id** (integer, required) + - **link_id** (integer, required) +- Result on success: **dict** +- Result on failure: **false** + +Request example: + +```json +{"jsonrpc":"2.0","method":"getExternalTaskLinkById","id":2107066744,"params":[9,1]} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "result": { + "id": "1", + "link_type": "attachment", + "dependency": "related", + "title": "document.pdf", + "url": "http:\/\/localhost\/document.pdf", + "date_creation": "1466965256", + "date_modification": "1466965256", + "task_id": "9", + "creator_id": "0" + }, + "id": 2107066744 +} +``` + +## getAllExternalTaskLinks + +- Purpose: **Get all external links attached to a task** +- Parameters: + - **task_id** (integer, required) +- Result on success: **list of external links** +- Result on failure: **false** + +Request example: + +```json +{"jsonrpc":"2.0","method":"getAllExternalTaskLinks","id":2069307223,"params":[9]} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "result": [ + { + "id": "1", + "link_type": "attachment", + "dependency": "related", + "title": "New title", + "url": "http:\/\/localhost\/document.pdf", + "date_creation": "1466965256", + "date_modification": "1466965256", + "task_id": "9", + "creator_id": "0", + "creator_name": null, + "creator_username": null, + "dependency_label": "Related", + "type": "Attachment" + } + ], + "id": 2069307223 +} +``` + +## removeExternalTaskLink + +- Purpose: **Remove an external link** +- Parameters: + - **task_id** (integer, required) + - **link_id** (integer, required) +- Result on success: **true** +- Result on failure: **false** + +Request example: + +```json +{"jsonrpc":"2.0","method":"removeExternalTaskLink","id":552055660,"params":[9,1]} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "result": true, + "id": 552055660 +} +``` diff --git a/doc/api-internal-task-link-procedures.markdown b/doc/api-internal-task-link-procedures.markdown new file mode 100644 index 00000000..859228de --- /dev/null +++ b/doc/api-internal-task-link-procedures.markdown @@ -0,0 +1,187 @@ +Internal Task Links API Procedures +================================== + +## createTaskLink + +- Purpose: **Create a link between two tasks** +- Parameters: + - **task_id** (integer, required) + - **opposite_task_id** (integer, required) + - **link_id** (integer, required) +- Result on success: **task_link_id** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "createTaskLink", + "id": 509742912, + "params": [ + 2, + 3, + 1 + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 509742912, + "result": 1 +} +``` + +## updateTaskLink + +- Purpose: **Update task link** +- Parameters: + - **task_link_id** (integer, required) + - **task_id** (integer, required) + - **opposite_task_id** (integer, required) + - **link_id** (integer, required) +- Result on success: **true** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "updateTaskLink", + "id": 669037109, + "params": [ + 1, + 2, + 4, + 2 + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 669037109, + "result": true +} +``` + +## getTaskLinkById + +- Purpose: **Get a task link** +- Parameters: + - **task_link_id** (integer, required) +- Result on success: **task link properties** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "getTaskLinkById", + "id": 809885202, + "params": [ + 1 + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 809885202, + "result": { + "id": "1", + "link_id": "1", + "task_id": "2", + "opposite_task_id": "3" + } +} +``` + +## getAllTaskLinks + +- Purpose: **Get all links related to a task** +- Parameters: + - **task_id** (integer, required) +- Result on success: **list of task link** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "getAllTaskLinks", + "id": 810848359, + "params": [ + 2 + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 810848359, + "result": [ + { + "id": "1", + "task_id": "3", + "label": "relates to", + "title": "B", + "is_active": "1", + "project_id": "1", + "task_time_spent": "0", + "task_time_estimated": "0", + "task_assignee_id": "0", + "task_assignee_username": null, + "task_assignee_name": null, + "column_title": "Backlog" + } + ] +} +``` + +## removeTaskLink + +- Purpose: **Remove a link between two tasks** +- Parameters: + - **task_link_id** (integer, required) +- Result on success: **true** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "removeTaskLink", + "id": 473028226, + "params": [ + 1 + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 473028226, + "result": true +} +``` diff --git a/doc/api-json-rpc.markdown b/doc/api-json-rpc.markdown index 0f922a7c..8e783e71 100644 --- a/doc/api-json-rpc.markdown +++ b/doc/api-json-rpc.markdown @@ -60,6 +60,8 @@ Usage - [Subtasks](api-subtask-procedures.markdown) - [Files](api-file-procedures.markdown) - [Links](api-link-procedures.markdown) +- [Internal Task Links](api-internal-task-link-procedures.markdown) +- [External Task Links](api-external-task-link-procedures.markdown) - [Comments](api-comment-procedures.markdown) - [Users](api-user-procedures.markdown) - [Groups](api-group-procedures.markdown) diff --git a/doc/api-link-procedures.markdown b/doc/api-link-procedures.markdown index 6113316f..44e78a2a 100644 --- a/doc/api-link-procedures.markdown +++ b/doc/api-link-procedures.markdown @@ -283,188 +283,3 @@ Response example: "result": true } ``` - -## createTaskLink - -- Purpose: **Create a link between two tasks** -- Parameters: - - **task_id** (integer, required) - - **opposite_task_id** (integer, required) - - **link_id** (integer, required) -- Result on success: **task_link_id** -- Result on failure: **false** - -Request example: - -```json -{ - "jsonrpc": "2.0", - "method": "createTaskLink", - "id": 509742912, - "params": [ - 2, - 3, - 1 - ] -} -``` - -Response example: - -```json -{ - "jsonrpc": "2.0", - "id": 509742912, - "result": 1 -} -``` - -## updateTaskLink - -- Purpose: **Update task link** -- Parameters: - - **task_link_id** (integer, required) - - **task_id** (integer, required) - - **opposite_task_id** (integer, required) - - **link_id** (integer, required) -- Result on success: **true** -- Result on failure: **false** - -Request example: - -```json -{ - "jsonrpc": "2.0", - "method": "updateTaskLink", - "id": 669037109, - "params": [ - 1, - 2, - 4, - 2 - ] -} -``` - -Response example: - -```json -{ - "jsonrpc": "2.0", - "id": 669037109, - "result": true -} -``` - -## getTaskLinkById - -- Purpose: **Get a task link** -- Parameters: - - **task_link_id** (integer, required) -- Result on success: **task link properties** -- Result on failure: **false** - -Request example: - -```json -{ - "jsonrpc": "2.0", - "method": "getTaskLinkById", - "id": 809885202, - "params": [ - 1 - ] -} -``` - -Response example: - -```json -{ - "jsonrpc": "2.0", - "id": 809885202, - "result": { - "id": "1", - "link_id": "1", - "task_id": "2", - "opposite_task_id": "3" - } -} -``` - -## getAllTaskLinks - -- Purpose: **Get all links related to a task** -- Parameters: - - **task_id** (integer, required) -- Result on success: **list of task link** -- Result on failure: **false** - -Request example: - -```json -{ - "jsonrpc": "2.0", - "method": "getAllTaskLinks", - "id": 810848359, - "params": [ - 2 - ] -} -``` - -Response example: - -```json -{ - "jsonrpc": "2.0", - "id": 810848359, - "result": [ - { - "id": "1", - "task_id": "3", - "label": "relates to", - "title": "B", - "is_active": "1", - "project_id": "1", - "task_time_spent": "0", - "task_time_estimated": "0", - "task_assignee_id": "0", - "task_assignee_username": null, - "task_assignee_name": null, - "column_title": "Backlog" - } - ] -} -``` - -## removeTaskLink - -- Purpose: **Remove a link between two tasks** -- Parameters: - - **task_link_id** (integer, required) -- Result on success: **true** -- Result on failure: **false** - -Request example: - -```json -{ - "jsonrpc": "2.0", - "method": "removeTaskLink", - "id": 473028226, - "params": [ - 1 - ] -} -``` - -Response example: - -```json -{ - "jsonrpc": "2.0", - "id": 473028226, - "result": true -} -``` diff --git a/tests/integration/TaskExternalLinkProcedureTest.php b/tests/integration/TaskExternalLinkProcedureTest.php new file mode 100644 index 00000000..47ff53ad --- /dev/null +++ b/tests/integration/TaskExternalLinkProcedureTest.php @@ -0,0 +1,98 @@ +assertCreateTeamProject(); + $this->assertCreateTask(); + $this->assertGetExternalTaskLinkTypes(); + $this->assertGetExternalTaskLinkProviderDependencies(); + $this->assertGetExternalTaskLinkProviderDependenciesWithProviderNotFound(); + $this->assertCreateExternalTaskLink(); + $this->assertUpdateExternalTaskLink(); + $this->assertGetAllExternalTaskLinks(); + $this->assertRemoveExternalTaskLink(); + } + + public function assertGetExternalTaskLinkTypes() + { + $expected = array( + 'auto' => 'Auto', + 'attachment' => 'Attachment', + 'file' => 'Local File', + 'weblink' => 'Web Link', + ); + + $types = $this->app->getExternalTaskLinkTypes(); + $this->assertEquals($expected, $types); + } + + public function assertGetExternalTaskLinkProviderDependencies() + { + $expected = array( + 'related' => 'Related', + ); + + $dependencies = $this->app->getExternalTaskLinkProviderDependencies('weblink'); + + $this->assertEquals($expected, $dependencies); + } + + public function assertGetExternalTaskLinkProviderDependenciesWithProviderNotFound() + { + $this->assertFalse($this->app->getExternalTaskLinkProviderDependencies('foobar')); + } + + public function assertCreateExternalTaskLink() + { + $url = 'http://localhost/document.pdf'; + $this->linkId = $this->app->createExternalTaskLink($this->taskId, $url, 'related', 'attachment'); + $this->assertNotFalse($this->linkId); + + $link = $this->app->getExternalTaskLinkById($this->taskId, $this->linkId); + $this->assertEquals($this->linkId, $link['id']); + $this->assertEquals($this->taskId, $link['task_id']); + $this->assertEquals('document.pdf', $link['title']); + $this->assertEquals($url, $link['url']); + $this->assertEquals('related', $link['dependency']); + $this->assertEquals(0, $link['creator_id']); + } + + public function assertUpdateExternalTaskLink() + { + $this->assertTrue($this->app->updateExternalTaskLink(array( + 'task_id' => $this->taskId, + 'link_id' => $this->linkId, + 'title' => 'New title', + ))); + + $link = $this->app->getExternalTaskLinkById($this->taskId, $this->linkId); + $this->assertEquals($this->linkId, $link['id']); + $this->assertEquals($this->taskId, $link['task_id']); + $this->assertEquals('New title', $link['title']); + $this->assertEquals('related', $link['dependency']); + $this->assertEquals(0, $link['creator_id']); + } + + public function assertGetAllExternalTaskLinks() + { + $links = $this->app->getAllExternalTaskLinks($this->taskId); + $this->assertCount(1, $links); + $this->assertEquals($this->linkId, $links[0]['id']); + $this->assertEquals($this->taskId, $links[0]['task_id']); + $this->assertEquals('New title', $links[0]['title']); + $this->assertEquals('related', $links[0]['dependency']); + $this->assertEquals(0, $links[0]['creator_id']); + } + + public function assertRemoveExternalTaskLink() + { + $this->assertTrue($this->app->removeExternalTaskLink($this->taskId, $this->linkId)); + } +} -- cgit v1.2.3 From a089cd72de82acb95986a630b862a4c3090e3e2a Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Fri, 1 Jul 2016 09:47:10 -0400 Subject: Fixed lexer issue with non word characters --- ChangeLog | 1 + app/Core/Filter/Lexer.php | 2 +- tests/units/Core/Filter/LexerTest.php | 44 +++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) (limited to 'app/Core') diff --git a/ChangeLog b/ChangeLog index 3ea3f2c6..12754948 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,7 @@ Bug fixes: * Fixed broken CSV exports * Fixed identical background color for LetterAvatar on 32bits platforms (Hash greater than PHP_MAX_INT) +* Fixed lexer issue with non word characters Version 1.0.30 -------------- diff --git a/app/Core/Filter/Lexer.php b/app/Core/Filter/Lexer.php index fa5b8d2d..3ff57641 100644 --- a/app/Core/Filter/Lexer.php +++ b/app/Core/Filter/Lexer.php @@ -30,7 +30,7 @@ class Lexer '/^([<=>]{1,2}\w+)/u' => 'T_STRING', '/^([<=>]{1,2}".+")/' => 'T_STRING', '/^("(.+)")/' => 'T_STRING', - '/^(\w+)/u' => 'T_STRING', + '/^(\S+)/u' => 'T_STRING', '/^(#\d+)/' => 'T_STRING', ); diff --git a/tests/units/Core/Filter/LexerTest.php b/tests/units/Core/Filter/LexerTest.php index b777531d..d57a7953 100644 --- a/tests/units/Core/Filter/LexerTest.php +++ b/tests/units/Core/Filter/LexerTest.php @@ -214,4 +214,48 @@ class LexerTest extends Base $this->assertSame($expected, $lexer->tokenize('tag:"tag 1" tag:tag2')); } + + public function testTokenizeWithDash() + { + $lexer = new Lexer(); + $lexer->addToken("/^(test:)/", 'T_TEST'); + + $expected = array( + 'T_TEST' => array('PO-123'), + ); + + $this->assertSame($expected, $lexer->tokenize('test:PO-123')); + + $lexer = new Lexer(); + $lexer->setDefaultToken('myDefaultToken'); + + $expected = array( + 'myDefaultToken' => array('PO-123'), + ); + + $this->assertSame($expected, $lexer->tokenize('PO-123')); + } + + public function testTokenizeWithUnderscore() + { + $lexer = new Lexer(); + $lexer->addToken("/^(test:)/", 'T_TEST'); + + $expected = array( + 'T_TEST' => array('PO_123'), + ); + + $this->assertSame($expected, $lexer->tokenize('test:PO_123')); + + $lexer = new Lexer(); + $lexer->addToken("/^(test:)/", 'T_TEST'); + $lexer->setDefaultToken('myDefaultToken'); + + $expected = array( + 'T_TEST' => array('ABC-123'), + 'myDefaultToken' => array('PO_123'), + ); + + $this->assertSame($expected, $lexer->tokenize('test:ABC-123 PO_123')); + } } -- cgit v1.2.3 From 662506941f6ad00be535c3d854f3500bc12676de Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Fri, 1 Jul 2016 11:34:14 -0400 Subject: Flush memory cache in worker to get latest config values --- ChangeLog | 1 + app/Core/Queue/JobHandler.php | 1 + 2 files changed, 2 insertions(+) (limited to 'app/Core') diff --git a/ChangeLog b/ChangeLog index 12754948..2117c0cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,7 @@ Bug fixes: * Fixed broken CSV exports * Fixed identical background color for LetterAvatar on 32bits platforms (Hash greater than PHP_MAX_INT) * Fixed lexer issue with non word characters +* Flush memory cache in worker to get latest config values Version 1.0.30 -------------- diff --git a/app/Core/Queue/JobHandler.php b/app/Core/Queue/JobHandler.php index f8736cce..4fb673d5 100644 --- a/app/Core/Queue/JobHandler.php +++ b/app/Core/Queue/JobHandler.php @@ -48,6 +48,7 @@ class JobHandler extends Base $worker = new $className($this->container); call_user_func_array(array($worker, 'execute'), $payload['params']); + $this->memoryCache->flush(); } /** -- cgit v1.2.3 From 6db72521eab77ebcb5f8bb196fe72e8f4f8a8c34 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Fri, 1 Jul 2016 13:44:14 -0400 Subject: Memory cache have to be flushed before job processing --- app/Core/Queue/JobHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/Core') diff --git a/app/Core/Queue/JobHandler.php b/app/Core/Queue/JobHandler.php index 4fb673d5..7ca36328 100644 --- a/app/Core/Queue/JobHandler.php +++ b/app/Core/Queue/JobHandler.php @@ -40,6 +40,7 @@ class JobHandler extends Base { $payload = $job->getBody(); $className = $payload['class']; + $this->memoryCache->flush(); $this->prepareJobSession($payload['user_id']); if (DEBUG) { @@ -48,7 +49,6 @@ class JobHandler extends Base $worker = new $className($this->container); call_user_func_array(array($worker, 'execute'), $payload['params']); - $this->memoryCache->flush(); } /** -- cgit v1.2.3 From 3fcc0cb9183f9ff32ce7a3c615258bcf53c385ed Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 2 Jul 2016 14:44:26 -0400 Subject: Handle tags and tasks move/duplication to another project --- app/Action/TaskDuplicateAnotherProject.php | 2 +- app/Action/TaskMoveAnotherProject.php | 2 +- app/Api/Procedure/TaskProcedure.php | 4 +- app/Controller/TaskDuplicationController.php | 4 +- app/Core/Base.php | 4 + app/Model/TagDuplicationModel.php | 67 +++ app/Model/TaskDuplicationModel.php | 156 +---- app/Model/TaskModel.php | 2 +- app/Model/TaskProjectDuplicationModel.php | 60 ++ app/Model/TaskProjectMoveModel.php | 67 +++ app/Model/TaskRecurrenceModel.php | 87 +++ app/Model/TaskTagModel.php | 17 + app/ServiceProvider/ClassProvider.php | 4 + app/Subscriber/RecurringTaskSubscriber.php | 6 +- tests/units/Model/TaskDuplicationTest.php | 667 ++------------------- .../Model/TaskProjectDuplicationModelTest.php | 369 ++++++++++++ tests/units/Model/TaskProjectMoveModelTest.php | 269 +++++++++ tests/units/Model/TaskRecurrenceModelTest.php | 90 +++ tests/units/Model/TaskTagModelTest.php | 21 + 19 files changed, 1121 insertions(+), 777 deletions(-) create mode 100644 app/Model/TagDuplicationModel.php create mode 100644 app/Model/TaskProjectDuplicationModel.php create mode 100644 app/Model/TaskProjectMoveModel.php create mode 100644 app/Model/TaskRecurrenceModel.php create mode 100644 tests/units/Model/TaskProjectDuplicationModelTest.php create mode 100644 tests/units/Model/TaskProjectMoveModelTest.php create mode 100644 tests/units/Model/TaskRecurrenceModelTest.php (limited to 'app/Core') diff --git a/app/Action/TaskDuplicateAnotherProject.php b/app/Action/TaskDuplicateAnotherProject.php index 1d4a2f13..d70d2ee8 100644 --- a/app/Action/TaskDuplicateAnotherProject.php +++ b/app/Action/TaskDuplicateAnotherProject.php @@ -76,7 +76,7 @@ class TaskDuplicateAnotherProject extends Base public function doAction(array $data) { $destination_column_id = $this->columnModel->getFirstColumnId($this->getParam('project_id')); - return (bool) $this->taskDuplicationModel->duplicateToProject($data['task_id'], $this->getParam('project_id'), null, $destination_column_id); + return (bool) $this->taskProjectDuplicationModel->duplicateToProject($data['task_id'], $this->getParam('project_id'), null, $destination_column_id); } /** diff --git a/app/Action/TaskMoveAnotherProject.php b/app/Action/TaskMoveAnotherProject.php index 73ad4b69..66635a63 100644 --- a/app/Action/TaskMoveAnotherProject.php +++ b/app/Action/TaskMoveAnotherProject.php @@ -75,7 +75,7 @@ class TaskMoveAnotherProject extends Base */ public function doAction(array $data) { - return $this->taskDuplicationModel->moveToProject($data['task_id'], $this->getParam('project_id')); + return $this->taskProjectMoveModel->moveToProject($data['task_id'], $this->getParam('project_id')); } /** diff --git a/app/Api/Procedure/TaskProcedure.php b/app/Api/Procedure/TaskProcedure.php index 2d29a4ef..8661deef 100644 --- a/app/Api/Procedure/TaskProcedure.php +++ b/app/Api/Procedure/TaskProcedure.php @@ -77,13 +77,13 @@ class TaskProcedure extends BaseProcedure public function moveTaskToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null) { ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'moveTaskToProject', $project_id); - return $this->taskDuplicationModel->moveToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id); + return $this->taskProjectMoveModel->moveToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id); } public function duplicateTaskToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null) { ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'duplicateTaskToProject', $project_id); - return $this->taskDuplicationModel->duplicateToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id); + return $this->taskProjectDuplicationModel->duplicateToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id); } public function createTask($title, $project_id, $color_id = '', $column_id = 0, $owner_id = 0, $creator_id = 0, diff --git a/app/Controller/TaskDuplicationController.php b/app/Controller/TaskDuplicationController.php index 6a475374..915bf8f8 100644 --- a/app/Controller/TaskDuplicationController.php +++ b/app/Controller/TaskDuplicationController.php @@ -50,7 +50,7 @@ class TaskDuplicationController extends BaseController $values = $this->request->getValues(); list($valid, ) = $this->taskValidator->validateProjectModification($values); - if ($valid && $this->taskDuplicationModel->moveToProject($task['id'], + if ($valid && $this->taskProjectMoveModel->moveToProject($task['id'], $values['project_id'], $values['swimlane_id'], $values['column_id'], @@ -80,7 +80,7 @@ class TaskDuplicationController extends BaseController list($valid, ) = $this->taskValidator->validateProjectModification($values); if ($valid) { - $task_id = $this->taskDuplicationModel->duplicateToProject( + $task_id = $this->taskProjectDuplicationModel->duplicateToProject( $task['id'], $values['project_id'], $values['swimlane_id'], $values['column_id'], $values['category_id'], $values['owner_id'] ); diff --git a/app/Core/Base.php b/app/Core/Base.php index eacca65d..a8274152 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -90,11 +90,15 @@ use Pimple\Container; * @property \Kanboard\Model\SubtaskModel $subtaskModel * @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel * @property \Kanboard\Model\SwimlaneModel $swimlaneModel + * @property \Kanboard\Model\TagDuplicationModel $tagDuplicationModel * @property \Kanboard\Model\TagModel $tagModel * @property \Kanboard\Model\TaskModel $taskModel * @property \Kanboard\Model\TaskAnalyticModel $taskAnalyticModel * @property \Kanboard\Model\TaskCreationModel $taskCreationModel * @property \Kanboard\Model\TaskDuplicationModel $taskDuplicationModel + * @property \Kanboard\Model\TaskProjectDuplicationModel $taskProjectDuplicationModel + * @property \Kanboard\Model\TaskProjectMoveModel $taskProjectMoveModel + * @property \Kanboard\Model\TaskRecurrenceModel $taskRecurrenceModel * @property \Kanboard\Model\TaskExternalLinkModel $taskExternalLinkModel * @property \Kanboard\Model\TaskFinderModel $taskFinderModel * @property \Kanboard\Model\TaskLinkModel $taskLinkModel diff --git a/app/Model/TagDuplicationModel.php b/app/Model/TagDuplicationModel.php new file mode 100644 index 00000000..1876391d --- /dev/null +++ b/app/Model/TagDuplicationModel.php @@ -0,0 +1,67 @@ +taskTagModel->getTagsByTask($src_task_id); + + foreach ($tags as $tag) { + $tag_id = $this->tagModel->getIdByName($dst_project_id, $tag['name']); + + if ($tag_id) { + $this->taskTagModel->associateTag($dst_task_id, $tag_id); + } + } + } + + /** + * Duplicate tags to the new task + * + * @access public + * @param integer $src_task_id + * @param integer $dst_task_id + */ + public function duplicateTaskTags($src_task_id, $dst_task_id) + { + $tags = $this->taskTagModel->getTagsByTask($src_task_id); + + foreach ($tags as $tag) { + $this->taskTagModel->associateTag($dst_task_id, $tag['id']); + } + } + + /** + * Remove tags that are not available in destination project + * + * @access public + * @param integer $task_id + * @param integer $dst_project_id + */ + public function syncTaskTagsToAnotherProject($task_id, $dst_project_id) + { + $tag_ids = $this->taskTagModel->getTagIdsByTaskNotAvailableInProject($task_id, $dst_project_id); + + foreach ($tag_ids as $tag_id) { + $this->taskTagModel->dissociateTag($task_id, $tag_id); + } + } +} diff --git a/app/Model/TaskDuplicationModel.php b/app/Model/TaskDuplicationModel.php index 9a4613e2..0dce891f 100644 --- a/app/Model/TaskDuplicationModel.php +++ b/app/Model/TaskDuplicationModel.php @@ -2,10 +2,7 @@ namespace Kanboard\Model; -use DateTime; -use DateInterval; use Kanboard\Core\Base; -use Kanboard\Event\TaskEvent; /** * Task Duplication @@ -18,10 +15,10 @@ class TaskDuplicationModel extends Base /** * Fields to copy when duplicating a task * - * @access private - * @var array + * @access protected + * @var string[] */ - private $fields_to_duplicate = array( + protected $fields_to_duplicate = array( 'title', 'description', 'date_due', @@ -49,106 +46,13 @@ class TaskDuplicationModel extends Base */ public function duplicate($task_id) { - return $this->save($task_id, $this->copyFields($task_id)); - } - - /** - * Duplicate recurring task - * - * @access public - * @param integer $task_id Task id - * @return boolean|integer Recurrence task id - */ - public function duplicateRecurringTask($task_id) - { - $values = $this->copyFields($task_id); - - if ($values['recurrence_status'] == TaskModel::RECURRING_STATUS_PENDING) { - $values['recurrence_parent'] = $task_id; - $values['column_id'] = $this->columnModel->getFirstColumnId($values['project_id']); - $this->calculateRecurringTaskDueDate($values); - - $recurring_task_id = $this->save($task_id, $values); - - if ($recurring_task_id > 0) { - $parent_update = $this->db - ->table(TaskModel::TABLE) - ->eq('id', $task_id) - ->update(array( - 'recurrence_status' => TaskModel::RECURRING_STATUS_PROCESSED, - 'recurrence_child' => $recurring_task_id, - )); - - if ($parent_update) { - return $recurring_task_id; - } - } - } - - return false; - } - - /** - * Duplicate a task to another project - * - * @access public - * @param integer $task_id - * @param integer $project_id - * @param integer $swimlane_id - * @param integer $column_id - * @param integer $category_id - * @param integer $owner_id - * @return boolean|integer - */ - public function duplicateToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null) - { - $values = $this->copyFields($task_id); - $values['project_id'] = $project_id; - $values['column_id'] = $column_id !== null ? $column_id : $values['column_id']; - $values['swimlane_id'] = $swimlane_id !== null ? $swimlane_id : $values['swimlane_id']; - $values['category_id'] = $category_id !== null ? $category_id : $values['category_id']; - $values['owner_id'] = $owner_id !== null ? $owner_id : $values['owner_id']; - - $this->checkDestinationProjectValues($values); - - return $this->save($task_id, $values); - } + $new_task_id = $this->save($task_id, $this->copyFields($task_id)); - /** - * Move a task to another project - * - * @access public - * @param integer $task_id - * @param integer $project_id - * @param integer $swimlane_id - * @param integer $column_id - * @param integer $category_id - * @param integer $owner_id - * @return boolean - */ - public function moveToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null) - { - $task = $this->taskFinderModel->getById($task_id); - - $values = array(); - $values['is_active'] = 1; - $values['project_id'] = $project_id; - $values['column_id'] = $column_id !== null ? $column_id : $task['column_id']; - $values['position'] = $this->taskFinderModel->countByColumnId($project_id, $values['column_id']) + 1; - $values['swimlane_id'] = $swimlane_id !== null ? $swimlane_id : $task['swimlane_id']; - $values['category_id'] = $category_id !== null ? $category_id : $task['category_id']; - $values['owner_id'] = $owner_id !== null ? $owner_id : $task['owner_id']; - - $this->checkDestinationProjectValues($values); - - if ($this->db->table(TaskModel::TABLE)->eq('id', $task['id'])->update($values)) { - $this->container['dispatcher']->dispatch( - TaskModel::EVENT_MOVE_PROJECT, - new TaskEvent(array_merge($task, $values, array('task_id' => $task['id']))) - ); + if ($new_task_id !== false) { + $this->tagDuplicationModel->duplicateTaskTags($task_id, $new_task_id); } - return true; + return $new_task_id; } /** @@ -194,50 +98,14 @@ class TaskDuplicationModel extends Base return $values; } - /** - * Calculate new due date for new recurrence task - * - * @access public - * @param array $values Task fields - */ - public function calculateRecurringTaskDueDate(array &$values) - { - if (! empty($values['date_due']) && $values['recurrence_factor'] != 0) { - if ($values['recurrence_basedate'] == TaskModel::RECURRING_BASEDATE_TRIGGERDATE) { - $values['date_due'] = time(); - } - - $factor = abs($values['recurrence_factor']); - $subtract = $values['recurrence_factor'] < 0; - - switch ($values['recurrence_timeframe']) { - case TaskModel::RECURRING_TIMEFRAME_MONTHS: - $interval = 'P' . $factor . 'M'; - break; - case TaskModel::RECURRING_TIMEFRAME_YEARS: - $interval = 'P' . $factor . 'Y'; - break; - default: - $interval = 'P' . $factor . 'D'; - } - - $date_due = new DateTime(); - $date_due->setTimestamp($values['date_due']); - - $subtract ? $date_due->sub(new DateInterval($interval)) : $date_due->add(new DateInterval($interval)); - - $values['date_due'] = $date_due->getTimestamp(); - } - } - /** * Duplicate fields for the new task * - * @access private + * @access protected * @param integer $task_id Task id * @return array */ - private function copyFields($task_id) + protected function copyFields($task_id) { $task = $this->taskFinderModel->getById($task_id); $values = array(); @@ -252,16 +120,16 @@ class TaskDuplicationModel extends Base /** * Create the new task and duplicate subtasks * - * @access private + * @access protected * @param integer $task_id Task id * @param array $values Form values * @return boolean|integer */ - private function save($task_id, array $values) + protected function save($task_id, array $values) { $new_task_id = $this->taskCreationModel->create($values); - if ($new_task_id) { + if ($new_task_id !== false) { $this->subtaskModel->duplicate($task_id, $new_task_id); } diff --git a/app/Model/TaskModel.php b/app/Model/TaskModel.php index b0e7772a..b945ee44 100644 --- a/app/Model/TaskModel.php +++ b/app/Model/TaskModel.php @@ -215,7 +215,7 @@ class TaskModel extends Base $task_ids = $this->taskFinderModel->getAllIds($src_project_id, array(TaskModel::STATUS_OPEN, TaskModel::STATUS_CLOSED)); foreach ($task_ids as $task_id) { - if (! $this->taskDuplicationModel->duplicateToProject($task_id, $dst_project_id)) { + if (! $this->taskProjectDuplicationModel->duplicateToProject($task_id, $dst_project_id)) { return false; } } diff --git a/app/Model/TaskProjectDuplicationModel.php b/app/Model/TaskProjectDuplicationModel.php new file mode 100644 index 00000000..8ebed255 --- /dev/null +++ b/app/Model/TaskProjectDuplicationModel.php @@ -0,0 +1,60 @@ +prepare($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id); + $this->checkDestinationProjectValues($values); + $new_task_id = $this->save($task_id, $values); + + if ($new_task_id !== false) { + $this->tagDuplicationModel->duplicateTaskTagsToAnotherProject($task_id, $new_task_id, $project_id); + } + + return $new_task_id; + } + + /** + * Prepare values before duplication + * + * @access protected + * @param integer $task_id + * @param integer $project_id + * @param integer $swimlane_id + * @param integer $column_id + * @param integer $category_id + * @param integer $owner_id + * @return array + */ + protected function prepare($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id) + { + $values = $this->copyFields($task_id); + $values['project_id'] = $project_id; + $values['column_id'] = $column_id !== null ? $column_id : $values['column_id']; + $values['swimlane_id'] = $swimlane_id !== null ? $swimlane_id : $values['swimlane_id']; + $values['category_id'] = $category_id !== null ? $category_id : $values['category_id']; + $values['owner_id'] = $owner_id !== null ? $owner_id : $values['owner_id']; + return $values; + } +} diff --git a/app/Model/TaskProjectMoveModel.php b/app/Model/TaskProjectMoveModel.php new file mode 100644 index 00000000..7e9714d6 --- /dev/null +++ b/app/Model/TaskProjectMoveModel.php @@ -0,0 +1,67 @@ +taskFinderModel->getById($task_id); + $values = $this->prepare($project_id, $swimlane_id, $column_id, $category_id, $owner_id, $task); + + $this->checkDestinationProjectValues($values); + $this->tagDuplicationModel->syncTaskTagsToAnotherProject($task_id, $project_id); + + if ($this->db->table(TaskModel::TABLE)->eq('id', $task['id'])->update($values)) { + $event = new TaskEvent(array_merge($task, $values, array('task_id' => $task['id']))); + $this->dispatcher->dispatch(TaskModel::EVENT_MOVE_PROJECT, $event); + } + + return true; + } + + /** + * Prepare new task values + * + * @access protected + * @param integer $project_id + * @param integer $swimlane_id + * @param integer $column_id + * @param integer $category_id + * @param integer $owner_id + * @param array $task + * @return array + */ + protected function prepare($project_id, $swimlane_id, $column_id, $category_id, $owner_id, array $task) + { + $values = array(); + $values['is_active'] = 1; + $values['project_id'] = $project_id; + $values['column_id'] = $column_id !== null ? $column_id : $task['column_id']; + $values['position'] = $this->taskFinderModel->countByColumnId($project_id, $values['column_id']) + 1; + $values['swimlane_id'] = $swimlane_id !== null ? $swimlane_id : $task['swimlane_id']; + $values['category_id'] = $category_id !== null ? $category_id : $task['category_id']; + $values['owner_id'] = $owner_id !== null ? $owner_id : $task['owner_id']; + return $values; + } +} diff --git a/app/Model/TaskRecurrenceModel.php b/app/Model/TaskRecurrenceModel.php new file mode 100644 index 00000000..a5f2ab90 --- /dev/null +++ b/app/Model/TaskRecurrenceModel.php @@ -0,0 +1,87 @@ +copyFields($task_id); + + if ($values['recurrence_status'] == TaskModel::RECURRING_STATUS_PENDING) { + $values['recurrence_parent'] = $task_id; + $values['column_id'] = $this->columnModel->getFirstColumnId($values['project_id']); + $this->calculateRecurringTaskDueDate($values); + + $recurring_task_id = $this->save($task_id, $values); + + if ($recurring_task_id > 0) { + $parent_update = $this->db + ->table(TaskModel::TABLE) + ->eq('id', $task_id) + ->update(array( + 'recurrence_status' => TaskModel::RECURRING_STATUS_PROCESSED, + 'recurrence_child' => $recurring_task_id, + )); + + if ($parent_update) { + return $recurring_task_id; + } + } + } + + return false; + } + + /** + * Calculate new due date for new recurrence task + * + * @access public + * @param array $values Task fields + */ + public function calculateRecurringTaskDueDate(array &$values) + { + if (! empty($values['date_due']) && $values['recurrence_factor'] != 0) { + if ($values['recurrence_basedate'] == TaskModel::RECURRING_BASEDATE_TRIGGERDATE) { + $values['date_due'] = time(); + } + + $factor = abs($values['recurrence_factor']); + $subtract = $values['recurrence_factor'] < 0; + + switch ($values['recurrence_timeframe']) { + case TaskModel::RECURRING_TIMEFRAME_MONTHS: + $interval = 'P' . $factor . 'M'; + break; + case TaskModel::RECURRING_TIMEFRAME_YEARS: + $interval = 'P' . $factor . 'Y'; + break; + default: + $interval = 'P' . $factor . 'D'; + } + + $date_due = new DateTime(); + $date_due->setTimestamp($values['date_due']); + + $subtract ? $date_due->sub(new DateInterval($interval)) : $date_due->add(new DateInterval($interval)); + + $values['date_due'] = $date_due->getTimestamp(); + } + } +} diff --git a/app/Model/TaskTagModel.php b/app/Model/TaskTagModel.php index 2a08e867..0553cc6c 100644 --- a/app/Model/TaskTagModel.php +++ b/app/Model/TaskTagModel.php @@ -19,6 +19,23 @@ class TaskTagModel extends Base */ const TABLE = 'task_has_tags'; + /** + * Get all tags not available in a project + * + * @access public + * @param integer $task_id + * @param integer $project_id + * @return array + */ + public function getTagIdsByTaskNotAvailableInProject($task_id, $project_id) + { + return $this->db->table(TagModel::TABLE) + ->eq(self::TABLE.'.task_id', $task_id) + ->notIn(TagModel::TABLE.'.project_id', array(0, $project_id)) + ->join(self::TABLE, 'tag_id', 'id') + ->findAllByColumn(TagModel::TABLE.'.id'); + } + /** * Get all tags associated to a task * diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index c0fb93bd..1f584fca 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -60,11 +60,15 @@ class ClassProvider implements ServiceProviderInterface 'SubtaskModel', 'SubtaskTimeTrackingModel', 'SwimlaneModel', + 'TagDuplicationModel', 'TagModel', 'TaskModel', 'TaskAnalyticModel', 'TaskCreationModel', 'TaskDuplicationModel', + 'TaskProjectDuplicationModel', + 'TaskProjectMoveModel', + 'TaskRecurrenceModel', 'TaskExternalLinkModel', 'TaskFinderModel', 'TaskFileModel', diff --git a/app/Subscriber/RecurringTaskSubscriber.php b/app/Subscriber/RecurringTaskSubscriber.php index 75b7ff76..21cd3996 100644 --- a/app/Subscriber/RecurringTaskSubscriber.php +++ b/app/Subscriber/RecurringTaskSubscriber.php @@ -22,9 +22,9 @@ class RecurringTaskSubscriber extends BaseSubscriber implements EventSubscriberI if ($event['recurrence_status'] == TaskModel::RECURRING_STATUS_PENDING) { if ($event['recurrence_trigger'] == TaskModel::RECURRING_TRIGGER_FIRST_COLUMN && $this->columnModel->getFirstColumnId($event['project_id']) == $event['src_column_id']) { - $this->taskDuplicationModel->duplicateRecurringTask($event['task_id']); + $this->taskRecurrenceModel->duplicateRecurringTask($event['task_id']); } elseif ($event['recurrence_trigger'] == TaskModel::RECURRING_TRIGGER_LAST_COLUMN && $this->columnModel->getLastColumnId($event['project_id']) == $event['dst_column_id']) { - $this->taskDuplicationModel->duplicateRecurringTask($event['task_id']); + $this->taskRecurrenceModel->duplicateRecurringTask($event['task_id']); } } } @@ -34,7 +34,7 @@ class RecurringTaskSubscriber extends BaseSubscriber implements EventSubscriberI $this->logger->debug('Subscriber executed: '.__METHOD__); if ($event['recurrence_status'] == TaskModel::RECURRING_STATUS_PENDING && $event['recurrence_trigger'] == TaskModel::RECURRING_TRIGGER_CLOSE) { - $this->taskDuplicationModel->duplicateRecurringTask($event['task_id']); + $this->taskRecurrenceModel->duplicateRecurringTask($event['task_id']); } } } diff --git a/tests/units/Model/TaskDuplicationTest.php b/tests/units/Model/TaskDuplicationTest.php index 79b75e54..7ce851d0 100644 --- a/tests/units/Model/TaskDuplicationTest.php +++ b/tests/units/Model/TaskDuplicationTest.php @@ -2,31 +2,27 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Core\DateParser; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskDuplicationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; -use Kanboard\Model\ProjectUserRoleModel; use Kanboard\Model\CategoryModel; -use Kanboard\Model\UserModel; -use Kanboard\Model\SwimlaneModel; -use Kanboard\Core\Security\Role; +use Kanboard\Model\TaskTagModel; class TaskDuplicationTest extends Base { public function testThatDuplicateDefineCreator() { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); + $taskDuplicationModel = new TaskDuplicationModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); - $task = $tf->getById(1); + $task = $taskFinderModel->getById(1); $this->assertNotEmpty($task); $this->assertEquals(1, $task['position']); $this->assertEquals(1, $task['project_id']); @@ -35,37 +31,41 @@ class TaskDuplicationTest extends Base $this->container['sessionStorage']->user = array('id' => 1); // We duplicate our task - $this->assertEquals(2, $td->duplicate(1)); + $this->assertEquals(2, $taskDuplicationModel->duplicate(1)); // Check the values of the duplicated task - $task = $tf->getById(2); + $task = $taskFinderModel->getById(2); $this->assertNotEmpty($task); $this->assertEquals(1, $task['creator_id']); } public function testDuplicateSameProject() { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $c = new CategoryModel($this->container); + $taskDuplicationModel = new TaskDuplicationModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); // We create a task and a project - $this->assertEquals(1, $p->create(array('name' => 'test1'))); + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); // Some categories - $this->assertNotFalse($c->create(array('name' => 'Category #1', 'project_id' => 1))); - $this->assertNotFalse($c->create(array('name' => 'Category #2', 'project_id' => 1))); - $this->assertTrue($c->exists(1)); - $this->assertTrue($c->exists(2)); + $this->assertNotFalse($categoryModel->create(array('name' => 'Category #1', 'project_id' => 1))); + $this->assertNotFalse($categoryModel->create(array('name' => 'Category #2', 'project_id' => 1))); + $this->assertTrue($categoryModel->exists(1)); + $this->assertTrue($categoryModel->exists(2)); - $this->assertEquals( - 1, - $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1, 'category_id' => 2, 'time_spent' => 4.4) - )); + $this->assertEquals(1, $taskCreationModel->create(array( + 'title' => 'test', + 'project_id' => 1, + 'column_id' => 3, + 'owner_id' => 1, + 'category_id' => 2, + 'time_spent' => 4.4 + ))); - $task = $tf->getById(1); + $task = $taskFinderModel->getById(1); $this->assertNotEmpty($task); $this->assertEquals(1, $task['position']); $this->assertEquals(1, $task['project_id']); @@ -77,14 +77,14 @@ class TaskDuplicationTest extends Base $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE, function () {}); // We duplicate our task - $this->assertEquals(2, $td->duplicate(1)); + $this->assertEquals(2, $taskDuplicationModel->duplicate(1)); $called = $this->container['dispatcher']->getCalledListeners(); $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.closure', $called); $this->assertArrayHasKey(TaskModel::EVENT_CREATE.'.closure', $called); // Check the values of the duplicated task - $task = $tf->getById(2); + $task = $taskFinderModel->getById(2); $this->assertNotEmpty($task); $this->assertEquals(TaskModel::STATUS_OPEN, $task['is_active']); $this->assertEquals(1, $task['project_id']); @@ -97,604 +97,25 @@ class TaskDuplicationTest extends Base $this->assertEquals(0, $task['time_spent']); } - public function testDuplicateAnotherProject() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $c = new CategoryModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - $this->assertNotFalse($c->create(array('name' => 'Category #1', 'project_id' => 1))); - $this->assertTrue($c->exists(1)); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 1, 'category_id' => 1))); - - $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE_UPDATE, function () {}); - $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE, function () {}); - - // We duplicate our task to the 2nd project - $this->assertEquals(2, $td->duplicateToProject(1, 2)); - - $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.closure', $called); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE.'.closure', $called); - - // Check the values of the duplicated task - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['owner_id']); - $this->assertEquals(0, $task['category_id']); - $this->assertEquals(0, $task['swimlane_id']); - $this->assertEquals(6, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(2, $task['project_id']); - $this->assertEquals('test', $task['title']); - } - - public function testDuplicateAnotherProjectWithCategory() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $c = new CategoryModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - $this->assertNotFalse($c->create(array('name' => 'Category #1', 'project_id' => 1))); - $this->assertNotFalse($c->create(array('name' => 'Category #1', 'project_id' => 2))); - $this->assertTrue($c->exists(1)); - $this->assertTrue($c->exists(2)); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'category_id' => 1))); - - // We duplicate our task to the 2nd project - $this->assertEquals(2, $td->duplicateToProject(1, 2)); - - // Check the values of the duplicated task - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['owner_id']); - $this->assertEquals(2, $task['category_id']); - $this->assertEquals(0, $task['swimlane_id']); - $this->assertEquals(6, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(2, $task['project_id']); - $this->assertEquals('test', $task['title']); - } - - public function testDuplicateAnotherProjectWithPredefinedCategory() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $c = new CategoryModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - $this->assertNotFalse($c->create(array('name' => 'Category #1', 'project_id' => 1))); - $this->assertNotFalse($c->create(array('name' => 'Category #1', 'project_id' => 2))); - $this->assertNotFalse($c->create(array('name' => 'Category #2', 'project_id' => 2))); - $this->assertTrue($c->exists(1)); - $this->assertTrue($c->exists(2)); - $this->assertTrue($c->exists(3)); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'category_id' => 1))); - - // We duplicate our task to the 2nd project with no category - $this->assertEquals(2, $td->duplicateToProject(1, 2, null, null, 0)); - - // Check the values of the duplicated task - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['category_id']); - - // We duplicate our task to the 2nd project with a different category - $this->assertEquals(3, $td->duplicateToProject(1, 2, null, null, 3)); - - // Check the values of the duplicated task - $task = $tf->getById(3); - $this->assertNotEmpty($task); - $this->assertEquals(3, $task['category_id']); - } - - public function testDuplicateAnotherProjectWithSwimlane() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $s = new SwimlaneModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - $this->assertNotFalse($s->create(array('project_id' => 1, 'name' => 'Swimlane #1'))); - $this->assertNotFalse($s->create(array('project_id' => 2, 'name' => 'Swimlane #1'))); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'swimlane_id' => 1))); - - // We duplicate our task to the 2nd project - $this->assertEquals(2, $td->duplicateToProject(1, 2)); - - // Check the values of the duplicated task - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['owner_id']); - $this->assertEquals(0, $task['category_id']); - $this->assertEquals(2, $task['swimlane_id']); - $this->assertEquals(6, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(2, $task['project_id']); - $this->assertEquals('test', $task['title']); - } - - public function testDuplicateAnotherProjectWithoutSwimlane() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $s = new SwimlaneModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - $this->assertNotFalse($s->create(array('project_id' => 1, 'name' => 'Swimlane #1'))); - $this->assertNotFalse($s->create(array('project_id' => 2, 'name' => 'Swimlane #2'))); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'swimlane_id' => 1))); - - // We duplicate our task to the 2nd project - $this->assertEquals(2, $td->duplicateToProject(1, 2)); - - // Check the values of the duplicated task - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['owner_id']); - $this->assertEquals(0, $task['category_id']); - $this->assertEquals(0, $task['swimlane_id']); - $this->assertEquals(6, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(2, $task['project_id']); - $this->assertEquals('test', $task['title']); - } - - public function testDuplicateAnotherProjectWithPredefinedSwimlane() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $s = new SwimlaneModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - $this->assertNotFalse($s->create(array('project_id' => 1, 'name' => 'Swimlane #1'))); - $this->assertNotFalse($s->create(array('project_id' => 2, 'name' => 'Swimlane #1'))); - $this->assertNotFalse($s->create(array('project_id' => 2, 'name' => 'Swimlane #2'))); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'swimlane_id' => 1))); - - // We duplicate our task to the 2nd project - $this->assertEquals(2, $td->duplicateToProject(1, 2, 3)); - - // Check the values of the duplicated task - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(3, $task['swimlane_id']); - } - - public function testDuplicateAnotherProjectWithPredefinedColumn() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2))); - - // We duplicate our task to the 2nd project with a different column - $this->assertEquals(2, $td->duplicateToProject(1, 2, null, 7)); - - // Check the values of the duplicated task - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(7, $task['column_id']); - } - - public function testDuplicateAnotherProjectWithUser() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $pp = new ProjectUserRoleModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 2))); - - // We duplicate our task to the 2nd project - $this->assertEquals(2, $td->duplicateToProject(1, 2)); - - // Check the values of the duplicated task - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['owner_id']); - $this->assertEquals(6, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(2, $task['project_id']); - $this->assertEquals('test', $task['title']); - - // We create a new user for our project - $user = new UserModel($this->container); - $this->assertNotFalse($user->create(array('username' => 'unittest#1', 'password' => 'unittest'))); - $this->assertTrue($pp->addUser(1, 2, Role::PROJECT_MEMBER)); - $this->assertTrue($pp->addUser(2, 2, Role::PROJECT_MEMBER)); - - // We duplicate our task to the 2nd project - $this->assertEquals(3, $td->duplicateToProject(1, 2)); - - // Check the values of the duplicated task - $task = $tf->getById(3); - $this->assertNotEmpty($task); - $this->assertEquals(2, $task['position']); - $this->assertEquals(6, $task['column_id']); - $this->assertEquals(2, $task['owner_id']); - $this->assertEquals(2, $task['project_id']); - - // We duplicate a task with a not allowed user - $this->assertEquals(4, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 3))); - $this->assertEquals(5, $td->duplicateToProject(4, 2)); - - $task = $tf->getById(5); - $this->assertNotEmpty($task); - $this->assertEquals(1, $task['position']); - $this->assertEquals(0, $task['owner_id']); - $this->assertEquals(2, $task['project_id']); - $this->assertEquals(5, $task['column_id']); - } - - public function testDuplicateAnotherProjectWithPredefinedUser() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $pr = new ProjectUserRoleModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 2))); - $this->assertTrue($pr->addUser(2, 1, Role::PROJECT_MEMBER)); - - // We duplicate our task to the 2nd project - $this->assertEquals(2, $td->duplicateToProject(1, 2, null, null, null, 1)); - - // Check the values of the duplicated task - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(1, $task['owner_id']); - } - - public function onMoveProject($event) - { - $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); - - $event_data = $event->getAll(); - $this->assertNotEmpty($event_data); - $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals('test', $event_data['title']); - } - - public function testMoveAnotherProject() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $user = new UserModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'owner_id' => 1, 'category_id' => 10, 'position' => 333))); - - $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_PROJECT, array($this, 'onMoveProject')); - - // We duplicate our task to the 2nd project - $this->assertTrue($td->moveToProject(1, 2)); - - $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_PROJECT.'.TaskDuplicationTest::onMoveProject', $called); - - // Check the values of the moved task - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['owner_id']); - $this->assertEquals(0, $task['category_id']); - $this->assertEquals(0, $task['swimlane_id']); - $this->assertEquals(2, $task['project_id']); - $this->assertEquals(5, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals('test', $task['title']); - } - - public function testMoveAnotherProjectWithCategory() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $c = new CategoryModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - $this->assertNotFalse($c->create(array('name' => 'Category #1', 'project_id' => 1))); - $this->assertNotFalse($c->create(array('name' => 'Category #1', 'project_id' => 2))); - $this->assertTrue($c->exists(1)); - $this->assertTrue($c->exists(2)); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'category_id' => 1))); - - // We move our task to the 2nd project - $this->assertTrue($td->moveToProject(1, 2)); - - // Check the values of the duplicated task - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['owner_id']); - $this->assertEquals(2, $task['category_id']); - $this->assertEquals(0, $task['swimlane_id']); - $this->assertEquals(6, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(2, $task['project_id']); - $this->assertEquals('test', $task['title']); - } - - public function testMoveAnotherProjectWithUser() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $pp = new ProjectUserRoleModel($this->container); - $user = new UserModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - // We create a new user for our project - $this->assertNotFalse($user->create(array('username' => 'unittest#1', 'password' => 'unittest'))); - $this->assertTrue($pp->addUser(1, 2, Role::PROJECT_MEMBER)); - $this->assertTrue($pp->addUser(2, 2, Role::PROJECT_MEMBER)); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 2))); - - // We move our task to the 2nd project - $this->assertTrue($td->moveToProject(1, 2)); - - // Check the values of the moved task - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(1, $task['position']); - $this->assertEquals(2, $task['owner_id']); - $this->assertEquals(2, $task['project_id']); - $this->assertEquals(6, $task['column_id']); - } - - public function testMoveAnotherProjectWithForbiddenUser() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $pp = new ProjectUserRoleModel($this->container); - $user = new UserModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - // We create a new user for our project - $this->assertNotFalse($user->create(array('username' => 'unittest#1', 'password' => 'unittest'))); - $this->assertTrue($pp->addUser(1, 2, Role::PROJECT_MEMBER)); - $this->assertTrue($pp->addUser(2, 2, Role::PROJECT_MEMBER)); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 3))); - - // We move our task to the 2nd project - $this->assertTrue($td->moveToProject(1, 2)); - - // Check the values of the moved task - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(1, $task['position']); - $this->assertEquals(0, $task['owner_id']); - $this->assertEquals(2, $task['project_id']); - $this->assertEquals(6, $task['column_id']); - } - - public function testMoveAnotherProjectWithSwimlane() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $s = new SwimlaneModel($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - $this->assertNotFalse($s->create(array('project_id' => 1, 'name' => 'Swimlane #1'))); - $this->assertNotFalse($s->create(array('project_id' => 2, 'name' => 'Swimlane #1'))); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'swimlane_id' => 1))); - - // We move our task to the 2nd project - $this->assertTrue($td->moveToProject(1, 2)); - - // Check the values of the moved task - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['owner_id']); - $this->assertEquals(0, $task['category_id']); - $this->assertEquals(2, $task['swimlane_id']); - $this->assertEquals(6, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(2, $task['project_id']); - $this->assertEquals('test', $task['title']); - } - - public function testMoveAnotherProjectWithoutSwimlane() + public function testDuplicateSameProjectWitTags() { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $s = new SwimlaneModel($this->container); + $taskDuplicationModel = new TaskDuplicationModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskTagModel = new TaskTagModel($this->container); - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'test2'))); - - $this->assertNotFalse($s->create(array('project_id' => 1, 'name' => 'Swimlane #1'))); - $this->assertNotFalse($s->create(array('project_id' => 2, 'name' => 'Swimlane #2'))); - - // We create a task - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'swimlane_id' => 1))); - - // We move our task to the 2nd project - $this->assertTrue($td->moveToProject(1, 2)); - - // Check the values of the moved task - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['owner_id']); - $this->assertEquals(0, $task['category_id']); - $this->assertEquals(0, $task['swimlane_id']); - $this->assertEquals(6, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(2, $task['project_id']); - $this->assertEquals('test', $task['title']); - } - - public function testCalculateRecurringTaskDueDate() - { - $td = new TaskDuplicationModel($this->container); - - $values = array('date_due' => 0); - $td->calculateRecurringTaskDueDate($values); - $this->assertEquals(0, $values['date_due']); - - $values = array('date_due' => 0, 'recurrence_factor' => 0, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_TRIGGERDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_DAYS); - $td->calculateRecurringTaskDueDate($values); - $this->assertEquals(0, $values['date_due']); - - $values = array('date_due' => 1431291376, 'recurrence_factor' => 1, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_TRIGGERDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_DAYS); - $td->calculateRecurringTaskDueDate($values); - $this->assertEquals(time() + 86400, $values['date_due'], '', 1); - - $values = array('date_due' => 1431291376, 'recurrence_factor' => -2, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_TRIGGERDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_DAYS); - $td->calculateRecurringTaskDueDate($values); - $this->assertEquals(time() - 2 * 86400, $values['date_due'], '', 1); - - $values = array('date_due' => 1431291376, 'recurrence_factor' => 1, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_DUEDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_DAYS); - $td->calculateRecurringTaskDueDate($values); - $this->assertEquals(1431291376 + 86400, $values['date_due'], '', 1); - - $values = array('date_due' => 1431291376, 'recurrence_factor' => -1, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_DUEDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_DAYS); - $td->calculateRecurringTaskDueDate($values); - $this->assertEquals(1431291376 - 86400, $values['date_due'], '', 1); - - $values = array('date_due' => 1431291376, 'recurrence_factor' => 2, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_DUEDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_MONTHS); - $td->calculateRecurringTaskDueDate($values); - $this->assertEquals(1436561776, $values['date_due'], '', 1); - - $values = array('date_due' => 1431291376, 'recurrence_factor' => 2, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_DUEDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_YEARS); - $td->calculateRecurringTaskDueDate($values); - $this->assertEquals(1494449776, $values['date_due'], '', 1); - } - - public function testDuplicateRecurringTask() - { - $td = new TaskDuplicationModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $dp = new DateParser($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - - $this->assertEquals(1, $tc->create(array( + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array( 'title' => 'test', 'project_id' => 1, - 'date_due' => 1436561776, - 'recurrence_status' => TaskModel::RECURRING_STATUS_PENDING, - 'recurrence_trigger' => TaskModel::RECURRING_TRIGGER_CLOSE, - 'recurrence_factor' => 2, - 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_DAYS, - 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_TRIGGERDATE, + 'tags' => array('T1', 'T2') ))); - $this->assertEquals(2, $td->duplicateRecurringTask(1)); + $this->assertEquals(2, $taskDuplicationModel->duplicate(1)); - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(TaskModel::RECURRING_STATUS_PROCESSED, $task['recurrence_status']); - $this->assertEquals(2, $task['recurrence_child']); - $this->assertEquals(1436486400, $task['date_due'], '', 2); - - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(TaskModel::RECURRING_STATUS_PENDING, $task['recurrence_status']); - $this->assertEquals(TaskModel::RECURRING_TRIGGER_CLOSE, $task['recurrence_trigger']); - $this->assertEquals(TaskModel::RECURRING_TIMEFRAME_DAYS, $task['recurrence_timeframe']); - $this->assertEquals(TaskModel::RECURRING_BASEDATE_TRIGGERDATE, $task['recurrence_basedate']); - $this->assertEquals(1, $task['recurrence_parent']); - $this->assertEquals(2, $task['recurrence_factor']); - $this->assertEquals($dp->removeTimeFromTimestamp(strtotime('+2 days')), $task['date_due'], '', 2); + $tags = $taskTagModel->getList(2); + $this->assertCount(2, $tags); + $this->assertArrayHasKey(1, $tags); + $this->assertArrayHasKey(2, $tags); } } diff --git a/tests/units/Model/TaskProjectDuplicationModelTest.php b/tests/units/Model/TaskProjectDuplicationModelTest.php new file mode 100644 index 00000000..798257ba --- /dev/null +++ b/tests/units/Model/TaskProjectDuplicationModelTest.php @@ -0,0 +1,369 @@ +container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertNotFalse($categoryModel->create(array('name' => 'Category #1', 'project_id' => 1))); + $this->assertTrue($categoryModel->exists(1)); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 1, 'category_id' => 1))); + + $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE_UPDATE, function () {}); + $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE, function () {}); + + // We duplicate our task to the 2nd project + $this->assertEquals(2, $taskProjectDuplicationModel->duplicateToProject(1, 2)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.closure', $called); + $this->assertArrayHasKey(TaskModel::EVENT_CREATE.'.closure', $called); + + // Check the values of the duplicated task + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['owner_id']); + $this->assertEquals(0, $task['category_id']); + $this->assertEquals(0, $task['swimlane_id']); + $this->assertEquals(6, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(2, $task['project_id']); + $this->assertEquals('test', $task['title']); + } + + public function testDuplicateAnotherProjectWithCategory() + { + $taskProjectDuplicationModel = new TaskProjectDuplicationModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertNotFalse($categoryModel->create(array('name' => 'Category #1', 'project_id' => 1))); + $this->assertNotFalse($categoryModel->create(array('name' => 'Category #1', 'project_id' => 2))); + $this->assertTrue($categoryModel->exists(1)); + $this->assertTrue($categoryModel->exists(2)); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'category_id' => 1))); + + // We duplicate our task to the 2nd project + $this->assertEquals(2, $taskProjectDuplicationModel->duplicateToProject(1, 2)); + + // Check the values of the duplicated task + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['owner_id']); + $this->assertEquals(2, $task['category_id']); + $this->assertEquals(0, $task['swimlane_id']); + $this->assertEquals(6, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(2, $task['project_id']); + $this->assertEquals('test', $task['title']); + } + + public function testDuplicateAnotherProjectWithPredefinedCategory() + { + $taskProjectDuplicationModel = new TaskProjectDuplicationModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertNotFalse($categoryModel->create(array('name' => 'Category #1', 'project_id' => 1))); + $this->assertNotFalse($categoryModel->create(array('name' => 'Category #1', 'project_id' => 2))); + $this->assertNotFalse($categoryModel->create(array('name' => 'Category #2', 'project_id' => 2))); + $this->assertTrue($categoryModel->exists(1)); + $this->assertTrue($categoryModel->exists(2)); + $this->assertTrue($categoryModel->exists(3)); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'category_id' => 1))); + + // We duplicate our task to the 2nd project with no category + $this->assertEquals(2, $taskProjectDuplicationModel->duplicateToProject(1, 2, null, null, 0)); + + // Check the values of the duplicated task + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['category_id']); + + // We duplicate our task to the 2nd project with a different category + $this->assertEquals(3, $taskProjectDuplicationModel->duplicateToProject(1, 2, null, null, 3)); + + // Check the values of the duplicated task + $task = $taskFinderModel->getById(3); + $this->assertNotEmpty($task); + $this->assertEquals(3, $task['category_id']); + } + + public function testDuplicateAnotherProjectWithSwimlane() + { + $taskProjectDuplicationModel = new TaskProjectDuplicationModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $swimlaneModel = new SwimlaneModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertNotFalse($swimlaneModel->create(array('project_id' => 1, 'name' => 'Swimlane #1'))); + $this->assertNotFalse($swimlaneModel->create(array('project_id' => 2, 'name' => 'Swimlane #1'))); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'swimlane_id' => 1))); + + // We duplicate our task to the 2nd project + $this->assertEquals(2, $taskProjectDuplicationModel->duplicateToProject(1, 2)); + + // Check the values of the duplicated task + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['owner_id']); + $this->assertEquals(0, $task['category_id']); + $this->assertEquals(2, $task['swimlane_id']); + $this->assertEquals(6, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(2, $task['project_id']); + $this->assertEquals('test', $task['title']); + } + + public function testDuplicateAnotherProjectWithoutSwimlane() + { + $taskProjectDuplicationModel = new TaskProjectDuplicationModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $swimlaneModel = new SwimlaneModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertNotFalse($swimlaneModel->create(array('project_id' => 1, 'name' => 'Swimlane #1'))); + $this->assertNotFalse($swimlaneModel->create(array('project_id' => 2, 'name' => 'Swimlane #2'))); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'swimlane_id' => 1))); + + // We duplicate our task to the 2nd project + $this->assertEquals(2, $taskProjectDuplicationModel->duplicateToProject(1, 2)); + + // Check the values of the duplicated task + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['owner_id']); + $this->assertEquals(0, $task['category_id']); + $this->assertEquals(0, $task['swimlane_id']); + $this->assertEquals(6, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(2, $task['project_id']); + $this->assertEquals('test', $task['title']); + } + + public function testDuplicateAnotherProjectWithPredefinedSwimlane() + { + $taskProjectDuplicationModel = new TaskProjectDuplicationModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $swimlaneModel = new SwimlaneModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertNotFalse($swimlaneModel->create(array('project_id' => 1, 'name' => 'Swimlane #1'))); + $this->assertNotFalse($swimlaneModel->create(array('project_id' => 2, 'name' => 'Swimlane #1'))); + $this->assertNotFalse($swimlaneModel->create(array('project_id' => 2, 'name' => 'Swimlane #2'))); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'swimlane_id' => 1))); + + // We duplicate our task to the 2nd project + $this->assertEquals(2, $taskProjectDuplicationModel->duplicateToProject(1, 2, 3)); + + // Check the values of the duplicated task + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(3, $task['swimlane_id']); + } + + public function testDuplicateAnotherProjectWithPredefinedColumn() + { + $taskProjectDuplicationModel = new TaskProjectDuplicationModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2))); + + // We duplicate our task to the 2nd project with a different column + $this->assertEquals(2, $taskProjectDuplicationModel->duplicateToProject(1, 2, null, 7)); + + // Check the values of the duplicated task + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(7, $task['column_id']); + } + + public function testDuplicateAnotherProjectWithUser() + { + $taskProjectDuplicationModel = new TaskProjectDuplicationModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $projectUserRoleModel = new ProjectUserRoleModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 2))); + + // We duplicate our task to the 2nd project + $this->assertEquals(2, $taskProjectDuplicationModel->duplicateToProject(1, 2)); + + // Check the values of the duplicated task + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['owner_id']); + $this->assertEquals(6, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(2, $task['project_id']); + $this->assertEquals('test', $task['title']); + + // We create a new user for our project + $user = new UserModel($this->container); + $this->assertNotFalse($user->create(array('username' => 'unittest#1', 'password' => 'unittest'))); + $this->assertTrue($projectUserRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($projectUserRoleModel->addUser(2, 2, Role::PROJECT_MEMBER)); + + // We duplicate our task to the 2nd project + $this->assertEquals(3, $taskProjectDuplicationModel->duplicateToProject(1, 2)); + + // Check the values of the duplicated task + $task = $taskFinderModel->getById(3); + $this->assertNotEmpty($task); + $this->assertEquals(2, $task['position']); + $this->assertEquals(6, $task['column_id']); + $this->assertEquals(2, $task['owner_id']); + $this->assertEquals(2, $task['project_id']); + + // We duplicate a task with a not allowed user + $this->assertEquals(4, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 3))); + $this->assertEquals(5, $taskProjectDuplicationModel->duplicateToProject(4, 2)); + + $task = $taskFinderModel->getById(5); + $this->assertNotEmpty($task); + $this->assertEquals(1, $task['position']); + $this->assertEquals(0, $task['owner_id']); + $this->assertEquals(2, $task['project_id']); + $this->assertEquals(5, $task['column_id']); + } + + public function testDuplicateAnotherProjectWithPredefinedUser() + { + $taskProjectDuplicationModel = new TaskProjectDuplicationModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $projectUserRoleModel = new ProjectUserRoleModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 2))); + $this->assertTrue($projectUserRoleModel->addUser(2, 1, Role::PROJECT_MEMBER)); + + // We duplicate our task to the 2nd project + $this->assertEquals(2, $taskProjectDuplicationModel->duplicateToProject(1, 2, null, null, null, 1)); + + // Check the values of the duplicated task + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(1, $task['owner_id']); + } + + public function testDuplicateAnotherProjectWithDifferentTags() + { + $taskProjectMoveModel = new TaskProjectDuplicationModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $tagModel = new TagModel($this->container); + $taskTagModel = new TaskTagModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + // We create our tags for each projects + $this->assertEquals(1, $tagModel->create(1, 'T1')); + $this->assertEquals(2, $tagModel->create(1, 'T2')); + $this->assertEquals(3, $tagModel->create(2, 'T2')); + $this->assertEquals(4, $tagModel->create(2, 'T3')); + $this->assertEquals(5, $tagModel->create(0, 'T4')); + $this->assertEquals(6, $tagModel->create(0, 'T5')); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'tags' => array('T1', 'T2', 'T5')))); + + // We move our task to the 2nd project + $this->assertEquals(2, $taskProjectMoveModel->duplicateToProject(1, 2)); + + // Check the values of the moved task + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(2, $task['id']); + $this->assertEquals(2, $task['project_id']); + + // Check tags + $tags = $taskTagModel->getList(2); + $this->assertCount(2, $tags); + $this->assertArrayHasKey(3, $tags); + $this->assertArrayHasKey(6, $tags); + } +} diff --git a/tests/units/Model/TaskProjectMoveModelTest.php b/tests/units/Model/TaskProjectMoveModelTest.php new file mode 100644 index 00000000..ed6c0c3c --- /dev/null +++ b/tests/units/Model/TaskProjectMoveModelTest.php @@ -0,0 +1,269 @@ +assertInstanceOf('Kanboard\Event\TaskEvent', $event); + + $event_data = $event->getAll(); + $this->assertNotEmpty($event_data); + $this->assertEquals(1, $event_data['task_id']); + $this->assertEquals('test', $event_data['title']); + } + + public function testMoveAnotherProject() + { + $taskProjectMoveModel = new TaskProjectMoveModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'owner_id' => 1, 'category_id' => 10, 'position' => 333))); + + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_PROJECT, array($this, 'onMoveProject')); + + // We duplicate our task to the 2nd project + $this->assertTrue($taskProjectMoveModel->moveToProject(1, 2)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_PROJECT.'.TaskProjectMoveModelTest::onMoveProject', $called); + + // Check the values of the moved task + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['owner_id']); + $this->assertEquals(0, $task['category_id']); + $this->assertEquals(0, $task['swimlane_id']); + $this->assertEquals(2, $task['project_id']); + $this->assertEquals(5, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals('test', $task['title']); + } + + public function testMoveAnotherProjectWithCategory() + { + $taskProjectMoveModel = new TaskProjectMoveModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertNotFalse($categoryModel->create(array('name' => 'Category #1', 'project_id' => 1))); + $this->assertNotFalse($categoryModel->create(array('name' => 'Category #1', 'project_id' => 2))); + $this->assertTrue($categoryModel->exists(1)); + $this->assertTrue($categoryModel->exists(2)); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'category_id' => 1))); + + // We move our task to the 2nd project + $this->assertTrue($taskProjectMoveModel->moveToProject(1, 2)); + + // Check the values of the duplicated task + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['owner_id']); + $this->assertEquals(2, $task['category_id']); + $this->assertEquals(0, $task['swimlane_id']); + $this->assertEquals(6, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(2, $task['project_id']); + $this->assertEquals('test', $task['title']); + } + + public function testMoveAnotherProjectWithUser() + { + $taskProjectMoveModel = new TaskProjectMoveModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $projectUserRoleModel = new ProjectUserRoleModel($this->container); + $userModel = new UserModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + // We create a new user for our project + $this->assertNotFalse($userModel->create(array('username' => 'unittest#1', 'password' => 'unittest'))); + $this->assertTrue($projectUserRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($projectUserRoleModel->addUser(2, 2, Role::PROJECT_MEMBER)); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 2))); + + // We move our task to the 2nd project + $this->assertTrue($taskProjectMoveModel->moveToProject(1, 2)); + + // Check the values of the moved task + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(1, $task['position']); + $this->assertEquals(2, $task['owner_id']); + $this->assertEquals(2, $task['project_id']); + $this->assertEquals(6, $task['column_id']); + } + + public function testMoveAnotherProjectWithForbiddenUser() + { + $taskProjectMoveModel = new TaskProjectMoveModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $projectUserRoleModel = new ProjectUserRoleModel($this->container); + $userModel = new UserModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + // We create a new user for our project + $this->assertNotFalse($userModel->create(array('username' => 'unittest#1', 'password' => 'unittest'))); + $this->assertTrue($projectUserRoleModel->addUser(1, 2, Role::PROJECT_MEMBER)); + $this->assertTrue($projectUserRoleModel->addUser(2, 2, Role::PROJECT_MEMBER)); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 3))); + + // We move our task to the 2nd project + $this->assertTrue($taskProjectMoveModel->moveToProject(1, 2)); + + // Check the values of the moved task + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(1, $task['position']); + $this->assertEquals(0, $task['owner_id']); + $this->assertEquals(2, $task['project_id']); + $this->assertEquals(6, $task['column_id']); + } + + public function testMoveAnotherProjectWithSwimlane() + { + $taskProjectMoveModel = new TaskProjectMoveModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $swimlaneModel = new SwimlaneModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertNotFalse($swimlaneModel->create(array('project_id' => 1, 'name' => 'Swimlane #1'))); + $this->assertNotFalse($swimlaneModel->create(array('project_id' => 2, 'name' => 'Swimlane #1'))); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'swimlane_id' => 1))); + + // We move our task to the 2nd project + $this->assertTrue($taskProjectMoveModel->moveToProject(1, 2)); + + // Check the values of the moved task + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['owner_id']); + $this->assertEquals(0, $task['category_id']); + $this->assertEquals(2, $task['swimlane_id']); + $this->assertEquals(6, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(2, $task['project_id']); + $this->assertEquals('test', $task['title']); + } + + public function testMoveAnotherProjectWithoutSwimlane() + { + $taskProjectMoveModel = new TaskProjectMoveModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $swimlaneModel = new SwimlaneModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + $this->assertNotFalse($swimlaneModel->create(array('project_id' => 1, 'name' => 'Swimlane #1'))); + $this->assertNotFalse($swimlaneModel->create(array('project_id' => 2, 'name' => 'Swimlane #2'))); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 2, 'swimlane_id' => 1))); + + // We move our task to the 2nd project + $this->assertTrue($taskProjectMoveModel->moveToProject(1, 2)); + + // Check the values of the moved task + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['owner_id']); + $this->assertEquals(0, $task['category_id']); + $this->assertEquals(0, $task['swimlane_id']); + $this->assertEquals(6, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(2, $task['project_id']); + $this->assertEquals('test', $task['title']); + } + + public function testMoveAnotherProjectWithDifferentTags() + { + $taskProjectMoveModel = new TaskProjectMoveModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $tagModel = new TagModel($this->container); + $taskTagModel = new TaskTagModel($this->container); + + // We create 2 projects + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + + // We create our tags for each projects + $this->assertEquals(1, $tagModel->create(1, 'T1')); + $this->assertEquals(2, $tagModel->create(1, 'T2')); + $this->assertEquals(3, $tagModel->create(2, 'T3')); + $this->assertEquals(4, $tagModel->create(2, 'T4')); + $this->assertEquals(5, $tagModel->create(0, 'T5')); + $this->assertEquals(6, $tagModel->create(0, 'T6')); + + // We create a task + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'tags' => array('T1', 'T5', 'T6')))); + + // We move our task to the 2nd project + $this->assertTrue($taskProjectMoveModel->moveToProject(1, 2)); + + // Check the values of the moved task + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(2, $task['project_id']); + + // Check tags + $tags = $taskTagModel->getList(1); + $this->assertCount(2, $tags); + $this->assertArrayHasKey(5, $tags); + $this->assertArrayHasKey(6, $tags); + } +} diff --git a/tests/units/Model/TaskRecurrenceModelTest.php b/tests/units/Model/TaskRecurrenceModelTest.php new file mode 100644 index 00000000..6970e30f --- /dev/null +++ b/tests/units/Model/TaskRecurrenceModelTest.php @@ -0,0 +1,90 @@ +container); + + $values = array('date_due' => 0); + $taskRecurrenceModel->calculateRecurringTaskDueDate($values); + $this->assertEquals(0, $values['date_due']); + + $values = array('date_due' => 0, 'recurrence_factor' => 0, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_TRIGGERDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_DAYS); + $taskRecurrenceModel->calculateRecurringTaskDueDate($values); + $this->assertEquals(0, $values['date_due']); + + $values = array('date_due' => 1431291376, 'recurrence_factor' => 1, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_TRIGGERDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_DAYS); + $taskRecurrenceModel->calculateRecurringTaskDueDate($values); + $this->assertEquals(time() + 86400, $values['date_due'], '', 1); + + $values = array('date_due' => 1431291376, 'recurrence_factor' => -2, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_TRIGGERDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_DAYS); + $taskRecurrenceModel->calculateRecurringTaskDueDate($values); + $this->assertEquals(time() - 2 * 86400, $values['date_due'], '', 1); + + $values = array('date_due' => 1431291376, 'recurrence_factor' => 1, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_DUEDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_DAYS); + $taskRecurrenceModel->calculateRecurringTaskDueDate($values); + $this->assertEquals(1431291376 + 86400, $values['date_due'], '', 1); + + $values = array('date_due' => 1431291376, 'recurrence_factor' => -1, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_DUEDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_DAYS); + $taskRecurrenceModel->calculateRecurringTaskDueDate($values); + $this->assertEquals(1431291376 - 86400, $values['date_due'], '', 1); + + $values = array('date_due' => 1431291376, 'recurrence_factor' => 2, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_DUEDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_MONTHS); + $taskRecurrenceModel->calculateRecurringTaskDueDate($values); + $this->assertEquals(1436561776, $values['date_due'], '', 1); + + $values = array('date_due' => 1431291376, 'recurrence_factor' => 2, 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_DUEDATE, 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_YEARS); + $taskRecurrenceModel->calculateRecurringTaskDueDate($values); + $this->assertEquals(1494449776, $values['date_due'], '', 1); + } + + public function testDuplicateRecurringTask() + { + $taskRecurrenceModel = new TaskRecurrenceModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $dateParser = new DateParser($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + + $this->assertEquals(1, $taskCreationModel->create(array( + 'title' => 'test', + 'project_id' => 1, + 'date_due' => 1436561776, + 'recurrence_status' => TaskModel::RECURRING_STATUS_PENDING, + 'recurrence_trigger' => TaskModel::RECURRING_TRIGGER_CLOSE, + 'recurrence_factor' => 2, + 'recurrence_timeframe' => TaskModel::RECURRING_TIMEFRAME_DAYS, + 'recurrence_basedate' => TaskModel::RECURRING_BASEDATE_TRIGGERDATE, + ))); + + $this->assertEquals(2, $taskRecurrenceModel->duplicateRecurringTask(1)); + + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(TaskModel::RECURRING_STATUS_PROCESSED, $task['recurrence_status']); + $this->assertEquals(2, $task['recurrence_child']); + $this->assertEquals(1436486400, $task['date_due'], '', 2); + + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(TaskModel::RECURRING_STATUS_PENDING, $task['recurrence_status']); + $this->assertEquals(TaskModel::RECURRING_TRIGGER_CLOSE, $task['recurrence_trigger']); + $this->assertEquals(TaskModel::RECURRING_TIMEFRAME_DAYS, $task['recurrence_timeframe']); + $this->assertEquals(TaskModel::RECURRING_BASEDATE_TRIGGERDATE, $task['recurrence_basedate']); + $this->assertEquals(1, $task['recurrence_parent']); + $this->assertEquals(2, $task['recurrence_factor']); + $this->assertEquals($dateParser->removeTimeFromTimestamp(strtotime('+2 days')), $task['date_due'], '', 2); + } +} diff --git a/tests/units/Model/TaskTagModelTest.php b/tests/units/Model/TaskTagModelTest.php index 88055d5f..3485368e 100644 --- a/tests/units/Model/TaskTagModelTest.php +++ b/tests/units/Model/TaskTagModelTest.php @@ -124,4 +124,25 @@ class TaskTagModelTest extends Base $tags = $taskTagModel->getTagsByTasks(array()); $this->assertEquals(array(), $tags); } + + public function testGetTagIdNotAvailableInDestinationProject() + { + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskTagModel = new TaskTagModel($this->container); + $tagModel = new TagModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'P2'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test1'))); + + $this->assertEquals(1, $tagModel->create(0, 'T0')); + $this->assertEquals(2, $tagModel->create(2, 'T1')); + $this->assertEquals(3, $tagModel->create(2, 'T3')); + $this->assertEquals(4, $tagModel->create(1, 'T2')); + $this->assertEquals(5, $tagModel->create(1, 'T3')); + $this->assertTrue($taskTagModel->save(1, 1, array('T0', 'T2', 'T3'))); + + $this->assertEquals(array(4, 5), $taskTagModel->getTagIdsByTaskNotAvailableInProject(1, 2)); + } } -- cgit v1.2.3 From b7ac354e83af122e94cec1f9306aca6355a02a39 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 2 Jul 2016 15:29:48 -0400 Subject: Move Task::duplicate() to class ProjectTaskDuplicationModel --- app/Core/Base.php | 1 + app/Model/ProjectDuplicationModel.php | 4 +- app/Model/ProjectTaskDuplicationModel.php | 35 ++++++++++ app/Model/TaskModel.php | 83 +++++++++-------------- app/ServiceProvider/ClassProvider.php | 1 + app/Template/project_creation/create.php | 2 +- app/Template/project_view/duplicate.php | 2 +- tests/units/Model/ProjectDuplicationModelTest.php | 6 +- 8 files changed, 75 insertions(+), 59 deletions(-) create mode 100644 app/Model/ProjectTaskDuplicationModel.php (limited to 'app/Core') diff --git a/app/Core/Base.php b/app/Core/Base.php index a8274152..7320aebf 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -86,6 +86,7 @@ use Pimple\Container; * @property \Kanboard\Model\ProjectGroupRoleModel $projectGroupRoleModel * @property \Kanboard\Model\ProjectNotificationModel $projectNotificationModel * @property \Kanboard\Model\ProjectNotificationTypeModel $projectNotificationTypeModel + * @property \Kanboard\Model\ProjectTaskDuplicationModel $projectTaskDuplicationModel * @property \Kanboard\Model\RememberMeSessionModel $rememberMeSessionModel * @property \Kanboard\Model\SubtaskModel $subtaskModel * @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel diff --git a/app/Model/ProjectDuplicationModel.php b/app/Model/ProjectDuplicationModel.php index 4db8f767..f6b9683e 100644 --- a/app/Model/ProjectDuplicationModel.php +++ b/app/Model/ProjectDuplicationModel.php @@ -29,7 +29,7 @@ class ProjectDuplicationModel extends Base 'swimlaneModel', 'tagDuplicationModel', 'projectMetadataModel', - 'taskModel', + 'projectTaskDuplicationModel', ); } @@ -49,7 +49,7 @@ class ProjectDuplicationModel extends Base 'swimlaneModel', 'tagDuplicationModel', 'projectMetadataModel', - 'taskModel', + 'projectTaskDuplicationModel', ); } diff --git a/app/Model/ProjectTaskDuplicationModel.php b/app/Model/ProjectTaskDuplicationModel.php new file mode 100644 index 00000000..5d2e1322 --- /dev/null +++ b/app/Model/ProjectTaskDuplicationModel.php @@ -0,0 +1,35 @@ +taskFinderModel->getAllIds($src_project_id, array(TaskModel::STATUS_OPEN, TaskModel::STATUS_CLOSED)); + + foreach ($task_ids as $task_id) { + if (! $this->taskProjectDuplicationModel->duplicateToProject($task_id, $dst_project_id)) { + return false; + } + } + + return true; + } +} diff --git a/app/Model/TaskModel.php b/app/Model/TaskModel.php index b945ee44..5df41f3c 100644 --- a/app/Model/TaskModel.php +++ b/app/Model/TaskModel.php @@ -17,80 +17,80 @@ class TaskModel extends Base * * @var string */ - const TABLE = 'tasks'; + const TABLE = 'tasks'; /** * Task status * * @var integer */ - const STATUS_OPEN = 1; - const STATUS_CLOSED = 0; + const STATUS_OPEN = 1; + const STATUS_CLOSED = 0; /** * Events * * @var string */ - const EVENT_MOVE_PROJECT = 'task.move.project'; - const EVENT_MOVE_COLUMN = 'task.move.column'; - const EVENT_MOVE_POSITION = 'task.move.position'; - const EVENT_MOVE_SWIMLANE = 'task.move.swimlane'; - const EVENT_UPDATE = 'task.update'; - const EVENT_CREATE = 'task.create'; - const EVENT_CLOSE = 'task.close'; - const EVENT_OPEN = 'task.open'; - const EVENT_CREATE_UPDATE = 'task.create_update'; + const EVENT_MOVE_PROJECT = 'task.move.project'; + const EVENT_MOVE_COLUMN = 'task.move.column'; + const EVENT_MOVE_POSITION = 'task.move.position'; + const EVENT_MOVE_SWIMLANE = 'task.move.swimlane'; + const EVENT_UPDATE = 'task.update'; + const EVENT_CREATE = 'task.create'; + const EVENT_CLOSE = 'task.close'; + const EVENT_OPEN = 'task.open'; + const EVENT_CREATE_UPDATE = 'task.create_update'; const EVENT_ASSIGNEE_CHANGE = 'task.assignee_change'; - const EVENT_OVERDUE = 'task.overdue'; - const EVENT_USER_MENTION = 'task.user.mention'; - const EVENT_DAILY_CRONJOB = 'task.cronjob.daily'; + const EVENT_OVERDUE = 'task.overdue'; + const EVENT_USER_MENTION = 'task.user.mention'; + const EVENT_DAILY_CRONJOB = 'task.cronjob.daily'; /** * Recurrence: status * * @var integer */ - const RECURRING_STATUS_NONE = 0; - const RECURRING_STATUS_PENDING = 1; - const RECURRING_STATUS_PROCESSED = 2; + const RECURRING_STATUS_NONE = 0; + const RECURRING_STATUS_PENDING = 1; + const RECURRING_STATUS_PROCESSED = 2; /** * Recurrence: trigger * * @var integer */ - const RECURRING_TRIGGER_FIRST_COLUMN = 0; - const RECURRING_TRIGGER_LAST_COLUMN = 1; - const RECURRING_TRIGGER_CLOSE = 2; + const RECURRING_TRIGGER_FIRST_COLUMN = 0; + const RECURRING_TRIGGER_LAST_COLUMN = 1; + const RECURRING_TRIGGER_CLOSE = 2; /** * Recurrence: timeframe * * @var integer */ - const RECURRING_TIMEFRAME_DAYS = 0; - const RECURRING_TIMEFRAME_MONTHS = 1; - const RECURRING_TIMEFRAME_YEARS = 2; + const RECURRING_TIMEFRAME_DAYS = 0; + const RECURRING_TIMEFRAME_MONTHS = 1; + const RECURRING_TIMEFRAME_YEARS = 2; /** * Recurrence: base date used to calculate new due date * * @var integer */ - const RECURRING_BASEDATE_DUEDATE = 0; - const RECURRING_BASEDATE_TRIGGERDATE = 1; + const RECURRING_BASEDATE_DUEDATE = 0; + const RECURRING_BASEDATE_TRIGGERDATE = 1; /** * Remove a task * * @access public - * @param integer $task_id Task id + * @param integer $task_id Task id * @return boolean */ public function remove($task_id) { - if (! $this->taskFinderModel->exists($task_id)) { + if (!$this->taskFinderModel->exists($task_id)) { return false; } @@ -105,7 +105,7 @@ class TaskModel extends Base * Example: "Fix bug #1234" will return 1234 * * @access public - * @param string $message Text + * @param string $message Text * @return integer */ public function getTaskIdFromText($message) @@ -179,8 +179,8 @@ class TaskModel extends Base * Get task progress based on the column position * * @access public - * @param array $task - * @param array $columns + * @param array $task + * @param array $columns * @return integer */ public function getProgress(array $task, array $columns) @@ -201,25 +201,4 @@ class TaskModel extends Base return round(($position * 100) / count($columns), 1); } - - /** - * Helper method to duplicate all tasks to another project - * - * @access public - * @param integer $src_project_id - * @param integer $dst_project_id - * @return boolean - */ - public function duplicate($src_project_id, $dst_project_id) - { - $task_ids = $this->taskFinderModel->getAllIds($src_project_id, array(TaskModel::STATUS_OPEN, TaskModel::STATUS_CLOSED)); - - foreach ($task_ids as $task_id) { - if (! $this->taskProjectDuplicationModel->duplicateToProject($task_id, $dst_project_id)) { - return false; - } - } - - return true; - } } diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 1f584fca..2d485e22 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -55,6 +55,7 @@ class ClassProvider implements ServiceProviderInterface 'ProjectNotificationModel', 'ProjectMetadataModel', 'ProjectGroupRoleModel', + 'ProjectTaskDuplicationModel', 'ProjectUserRoleModel', 'RememberMeSessionModel', 'SubtaskModel', diff --git a/app/Template/project_creation/create.php b/app/Template/project_creation/create.php index dc1bc370..d00883ba 100644 --- a/app/Template/project_creation/create.php +++ b/app/Template/project_creation/create.php @@ -26,7 +26,7 @@ form->checkbox('tagDuplicationModel', t('Tags'), 1, true) ?> form->checkbox('actionModel', t('Actions'), 1, true) ?> form->checkbox('swimlaneModel', t('Swimlanes'), 1, true) ?> - form->checkbox('taskModel', t('Tasks'), 1, false) ?> + form->checkbox('projectTaskDuplicationModel', t('Tasks'), 1, false) ?>
    diff --git a/app/Template/project_view/duplicate.php b/app/Template/project_view/duplicate.php index a9680016..d66ff591 100644 --- a/app/Template/project_view/duplicate.php +++ b/app/Template/project_view/duplicate.php @@ -19,7 +19,7 @@ form->checkbox('actionModel', t('Actions'), 1, true) ?> form->checkbox('swimlaneModel', t('Swimlanes'), 1, false) ?> form->checkbox('projectMetadataModel', t('Metadata'), 1, false) ?> - form->checkbox('taskModel', t('Tasks'), 1, false) ?> + form->checkbox('projectTaskDuplicationModel', t('Tasks'), 1, false) ?>
    diff --git a/tests/units/Model/ProjectDuplicationModelTest.php b/tests/units/Model/ProjectDuplicationModelTest.php index de7b0d79..41e59c9c 100644 --- a/tests/units/Model/ProjectDuplicationModelTest.php +++ b/tests/units/Model/ProjectDuplicationModelTest.php @@ -428,7 +428,7 @@ class ProjectDuplicationModelTest extends Base $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1, 'column_id' => 2))); $this->assertEquals(3, $taskCreationModel->create(array('title' => 'T3', 'project_id' => 1, 'column_id' => 3))); - $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('categoryModel', 'actionModel', 'taskModel'))); + $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('categoryModel', 'actionModel', 'projectTaskDuplicationModel'))); // Check if Tasks have been duplicated $tasks = $taskFinderModel->getAll(2); @@ -458,7 +458,7 @@ class ProjectDuplicationModelTest extends Base $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 1))); $this->assertEquals(3, $taskCreationModel->create(array('title' => 'T3', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); - $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('projectPermissionModel', 'swimlaneModel', 'taskModel'))); + $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('projectPermissionModel', 'swimlaneModel', 'projectTaskDuplicationModel'))); // Check if Swimlanes have been duplicated $swimlanes = $swimlaneModel->getAll(2); @@ -496,7 +496,7 @@ class ProjectDuplicationModelTest extends Base $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1, 'column_id' => 2, 'tags' => array('A', 'B')))); $this->assertEquals(3, $taskCreationModel->create(array('title' => 'T3', 'project_id' => 1, 'column_id' => 3, 'tags' => array('C')))); - $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('categoryModel', 'actionModel', 'tagDuplicationModel', 'taskModel'))); + $this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('categoryModel', 'actionModel', 'tagDuplicationModel', 'projectTaskDuplicationModel'))); $tasks = $taskFinderModel->getAll(2); $this->assertCount(3, $tasks); -- cgit v1.2.3 From 10d577ad9d1b2976cdb080a7d7df3944e0db170f Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 2 Jul 2016 16:36:10 -0400 Subject: Handle priority for task and project duplication --- ChangeLog | 1 + app/Controller/ActionCreationController.php | 2 +- app/Core/Base.php | 1 + app/Model/ProjectDuplicationModel.php | 3 + app/Model/ProjectModel.php | 13 - app/Model/ProjectTaskPriorityModel.php | 74 +++++ app/Model/TaskDuplicationModel.php | 11 +- app/ServiceProvider/ClassProvider.php | 1 + tests/units/Model/ProjectDuplicationModelTest.php | 22 ++ tests/units/Model/ProjectModelTest.php | 306 +++++++++++++++++++ tests/units/Model/ProjectTaskPriorityModelTest.php | 84 ++++++ tests/units/Model/ProjectTest.php | 336 --------------------- 12 files changed, 502 insertions(+), 352 deletions(-) create mode 100644 app/Model/ProjectTaskPriorityModel.php create mode 100644 tests/units/Model/ProjectModelTest.php create mode 100644 tests/units/Model/ProjectTaskPriorityModelTest.php delete mode 100644 tests/units/Model/ProjectTest.php (limited to 'app/Core') diff --git a/ChangeLog b/ChangeLog index 7c04ba43..000400ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,7 @@ New features: Improvements: +* Handle priority for task and project duplication * Expose task reference field to the user interface * Improve ICal export * Added argument owner_id and identifier to project API calls diff --git a/app/Controller/ActionCreationController.php b/app/Controller/ActionCreationController.php index abd8abd3..9b228f28 100644 --- a/app/Controller/ActionCreationController.php +++ b/app/Controller/ActionCreationController.php @@ -81,7 +81,7 @@ class ActionCreationController extends BaseController 'colors_list' => $this->colorModel->getList(), 'categories_list' => $this->categoryModel->getList($project['id']), 'links_list' => $this->linkModel->getList(0, false), - 'priorities_list' => $this->projectModel->getPriorities($project), + 'priorities_list' => $this->projectTaskPriorityModel->getPriorities($project), 'project' => $project, 'available_actions' => $this->actionManager->getAvailableActions(), 'events' => $this->actionManager->getCompatibleEvents($values['action_name']), diff --git a/app/Core/Base.php b/app/Core/Base.php index 7320aebf..8103ec14 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -87,6 +87,7 @@ use Pimple\Container; * @property \Kanboard\Model\ProjectNotificationModel $projectNotificationModel * @property \Kanboard\Model\ProjectNotificationTypeModel $projectNotificationTypeModel * @property \Kanboard\Model\ProjectTaskDuplicationModel $projectTaskDuplicationModel + * @property \Kanboard\Model\ProjectTaskPriorityModel $projectTaskPriorityModel * @property \Kanboard\Model\RememberMeSessionModel $rememberMeSessionModel * @property \Kanboard\Model\SubtaskModel $subtaskModel * @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel diff --git a/app/Model/ProjectDuplicationModel.php b/app/Model/ProjectDuplicationModel.php index f6b9683e..94b83c80 100644 --- a/app/Model/ProjectDuplicationModel.php +++ b/app/Model/ProjectDuplicationModel.php @@ -146,6 +146,9 @@ class ProjectDuplicationModel extends Base 'is_public' => 0, 'is_private' => $private ? 1 : $is_private, 'owner_id' => $owner_id, + 'priority_default' => $project['priority_default'], + 'priority_start' => $project['priority_start'], + 'priority_end' => $project['priority_end'], ); if (! $this->db->table(ProjectModel::TABLE)->save($values)) { diff --git a/app/Model/ProjectModel.php b/app/Model/ProjectModel.php index 7382537e..850531c9 100644 --- a/app/Model/ProjectModel.php +++ b/app/Model/ProjectModel.php @@ -245,19 +245,6 @@ class ProjectModel extends Base ->count(); } - /** - * Get Priority range from a project - * - * @access public - * @param array $project - * @return array - */ - public function getPriorities(array $project) - { - $range = range($project['priority_start'], $project['priority_end']); - return array_combine($range, $range); - } - /** * Gather some task metrics for a given project * diff --git a/app/Model/ProjectTaskPriorityModel.php b/app/Model/ProjectTaskPriorityModel.php new file mode 100644 index 00000000..c1a0257a --- /dev/null +++ b/app/Model/ProjectTaskPriorityModel.php @@ -0,0 +1,74 @@ +db + ->table(ProjectModel::TABLE) + ->columns('priority_default', 'priority_start', 'priority_end') + ->eq('id', $project_id) + ->findOne(); + } + + /** + * Get default task priority + * + * @access public + * @param int $project_id + * @return int + */ + public function getDefaultPriority($project_id) + { + return $this->db->table(ProjectModel::TABLE)->eq('id', $project_id)->findOneColumn('priority_default') ?: 0; + } + + /** + * Get priority for a destination project + * + * @access public + * @param integer $dst_project_id + * @param integer $priority + * @return integer + */ + public function getPriorityForProject($dst_project_id, $priority) + { + $settings = $this->getPrioritySettings($dst_project_id); + + if ($priority >= $settings['priority_start'] && $priority <= $settings['priority_end']) { + return $priority; + } + + return $settings['priority_default']; + } +} diff --git a/app/Model/TaskDuplicationModel.php b/app/Model/TaskDuplicationModel.php index 0dce891f..c9079653 100644 --- a/app/Model/TaskDuplicationModel.php +++ b/app/Model/TaskDuplicationModel.php @@ -18,7 +18,7 @@ class TaskDuplicationModel extends Base * @access protected * @var string[] */ - protected $fields_to_duplicate = array( + protected $fieldsToDuplicate = array( 'title', 'description', 'date_due', @@ -27,6 +27,7 @@ class TaskDuplicationModel extends Base 'column_id', 'owner_id', 'score', + 'priority', 'category_id', 'time_estimated', 'swimlane_id', @@ -95,6 +96,12 @@ class TaskDuplicationModel extends Base $values['column_id'] = $values['column_id'] ?: $this->columnModel->getFirstColumnId($values['project_id']); } + // Check if priority exists for destination project + $values['priority'] = $this->projectTaskPriorityModel->getPriorityForProject( + $values['project_id'], + empty($values['priority']) ? 0 : $values['priority'] + ); + return $values; } @@ -110,7 +117,7 @@ class TaskDuplicationModel extends Base $task = $this->taskFinderModel->getById($task_id); $values = array(); - foreach ($this->fields_to_duplicate as $field) { + foreach ($this->fieldsToDuplicate as $field) { $values[$field] = $task[$field]; } diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 2d485e22..e32c0d43 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -56,6 +56,7 @@ class ClassProvider implements ServiceProviderInterface 'ProjectMetadataModel', 'ProjectGroupRoleModel', 'ProjectTaskDuplicationModel', + 'ProjectTaskPriorityModel', 'ProjectUserRoleModel', 'RememberMeSessionModel', 'SubtaskModel', diff --git a/tests/units/Model/ProjectDuplicationModelTest.php b/tests/units/Model/ProjectDuplicationModelTest.php index 41e59c9c..54261728 100644 --- a/tests/units/Model/ProjectDuplicationModelTest.php +++ b/tests/units/Model/ProjectDuplicationModelTest.php @@ -141,6 +141,28 @@ class ProjectDuplicationModelTest extends Base $this->assertEquals(Role::PROJECT_MANAGER, $projectUserRoleModel->getUserRole(2, 1)); } + public function testCloneProjectWithDifferentPriorities() + { + $projectModel = new ProjectModel($this->container); + $projectDuplicationModel = new ProjectDuplicationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array( + 'name' => 'My project', + 'priority_default' => 2, + 'priority_start' => -2, + 'priority_end' => 8, + ))); + + $this->assertEquals(2, $projectDuplicationModel->duplicate(1)); + + $project = $projectModel->getById(2); + $this->assertNotEmpty($project); + $this->assertEquals('My project (Clone)', $project['name']); + $this->assertEquals(2, $project['priority_default']); + $this->assertEquals(-2, $project['priority_start']); + $this->assertEquals(8, $project['priority_end']); + } + public function testCloneProjectWithDifferentName() { $projectModel = new ProjectModel($this->container); diff --git a/tests/units/Model/ProjectModelTest.php b/tests/units/Model/ProjectModelTest.php new file mode 100644 index 00000000..81e0dd57 --- /dev/null +++ b/tests/units/Model/ProjectModelTest.php @@ -0,0 +1,306 @@ +container); + + foreach ($this->container['languageModel']->getLanguages() as $locale => $language) { + Translator::unload(); + Translator::load($locale); + $this->assertNotFalse($projectModel->create(array('name' => 'UnitTest '.$locale)), 'Unable to create project with '.$locale.':'.$language); + } + + Translator::unload(); + } + + public function testCreation() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(1, $project['is_active']); + $this->assertEquals(0, $project['is_public']); + $this->assertEquals(0, $project['is_private']); + $this->assertEquals(time(), $project['last_modified'], '', 1); + $this->assertEmpty($project['token']); + } + + public function testCreationWithDuplicateName() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'UnitTest'))); + } + + public function testCreationWithStartAndDate() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest', 'start_date' => '2015-01-01', 'end_date' => '2015-12-31'))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals('2015-01-01', $project['start_date']); + $this->assertEquals('2015-12-31', $project['end_date']); + } + + public function testCreationWithDefaultCategories() + { + $projectModel = new ProjectModel($this->container); + $configModel = new ConfigModel($this->container); + $categoryModel = new CategoryModel($this->container); + + // Multiple categories correctly formatted + + $this->assertTrue($configModel->save(array('project_categories' => 'Test1, Test2'))); + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest1'))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + + $categories = $categoryModel->getAll(1); + $this->assertNotEmpty($categories); + $this->assertEquals(2, count($categories)); + $this->assertEquals('Test1', $categories[0]['name']); + $this->assertEquals('Test2', $categories[1]['name']); + + // Single category + + $this->assertTrue($configModel->save(array('project_categories' => 'Test1'))); + $this->container['memoryCache']->flush(); + $this->assertEquals(2, $projectModel->create(array('name' => 'UnitTest2'))); + + $project = $projectModel->getById(2); + $this->assertNotEmpty($project); + + $categories = $categoryModel->getAll(2); + $this->assertNotEmpty($categories); + $this->assertEquals(1, count($categories)); + $this->assertEquals('Test1', $categories[0]['name']); + + // Multiple categories badly formatted + + $this->assertTrue($configModel->save(array('project_categories' => 'ABC, , DEF 3, '))); + $this->container['memoryCache']->flush(); + $this->assertEquals(3, $projectModel->create(array('name' => 'UnitTest3'))); + + $project = $projectModel->getById(3); + $this->assertNotEmpty($project); + + $categories = $categoryModel->getAll(3); + $this->assertNotEmpty($categories); + $this->assertEquals(2, count($categories)); + $this->assertEquals('ABC', $categories[0]['name']); + $this->assertEquals('DEF 3', $categories[1]['name']); + + // No default categories + $this->assertTrue($configModel->save(array('project_categories' => ' '))); + $this->container['memoryCache']->flush(); + $this->assertEquals(4, $projectModel->create(array('name' => 'UnitTest4'))); + + $project = $projectModel->getById(4); + $this->assertNotEmpty($project); + + $categories = $categoryModel->getAll(4); + $this->assertEmpty($categories); + } + + public function testUpdateLastModifiedDate() + { + $projectModel = new ProjectModel($this->container); + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + + $now = time(); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals($now, $project['last_modified'], 'Wrong Timestamp', 1); + + sleep(1); + $this->assertTrue($projectModel->updateModificationDate(1)); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertGreaterThan($now, $project['last_modified']); + } + + public function testGetAllIds() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + + $this->assertEmpty($projectModel->getAllByIds(array())); + $this->assertNotEmpty($projectModel->getAllByIds(array(1, 2))); + $this->assertCount(1, $projectModel->getAllByIds(array(1))); + } + + public function testIsLastModified() + { + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $now = time(); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals($now, $project['last_modified']); + + sleep(1); + + $listener = new ProjectModificationDateSubscriber($this->container); + $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE_UPDATE, array($listener, 'execute')); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1))); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.Kanboard\Subscriber\ProjectModificationDateSubscriber::execute', $called); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertTrue($projectModel->isModifiedSince(1, $now)); + } + + public function testRemove() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertTrue($projectModel->remove(1)); + $this->assertFalse($projectModel->remove(1234)); + } + + public function testEnable() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertTrue($projectModel->disable(1)); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(0, $project['is_active']); + + $this->assertFalse($projectModel->disable(1111)); + } + + public function testDisable() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertTrue($projectModel->disable(1)); + $this->assertTrue($projectModel->enable(1)); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(1, $project['is_active']); + + $this->assertFalse($projectModel->enable(1234567)); + } + + public function testEnablePublicAccess() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertTrue($projectModel->enablePublicAccess(1)); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(1, $project['is_public']); + $this->assertNotEmpty($project['token']); + + $this->assertFalse($projectModel->enablePublicAccess(123)); + } + + public function testDisablePublicAccess() + { + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertTrue($projectModel->enablePublicAccess(1)); + $this->assertTrue($projectModel->disablePublicAccess(1)); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(0, $project['is_public']); + $this->assertEmpty($project['token']); + + $this->assertFalse($projectModel->disablePublicAccess(123)); + } + + public function testIdentifier() + { + $projectModel = new ProjectModel($this->container); + + // Creation + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest1', 'identifier' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'UnitTest2'))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals('TEST1', $project['identifier']); + + $project = $projectModel->getById(2); + $this->assertNotEmpty($project); + $this->assertEquals('', $project['identifier']); + + // Update + $this->assertTrue($projectModel->update(array('id' => '2', 'identifier' => 'test2'))); + + $project = $projectModel->getById(2); + $this->assertNotEmpty($project); + $this->assertEquals('TEST2', $project['identifier']); + + $project = $projectModel->getByIdentifier('test1'); + $this->assertNotEmpty($project); + $this->assertEquals('TEST1', $project['identifier']); + + $project = $projectModel->getByIdentifier(''); + $this->assertFalse($project); + } + + public function testThatProjectCreatorAreAlsoOwner() + { + $projectModel = new ProjectModel($this->container); + $userModel = new UserModel($this->container); + + $this->assertEquals(2, $userModel->create(array('username' => 'user1', 'name' => 'Me'))); + $this->assertEquals(1, $projectModel->create(array('name' => 'My project 1'), 2)); + $this->assertEquals(2, $projectModel->create(array('name' => 'My project 2'))); + + $project = $projectModel->getByIdWithOwner(1); + $this->assertNotEmpty($project); + $this->assertSame('My project 1', $project['name']); + $this->assertSame('Me', $project['owner_name']); + $this->assertSame('user1', $project['owner_username']); + $this->assertEquals(2, $project['owner_id']); + + $project = $projectModel->getByIdWithOwner(2); + $this->assertNotEmpty($project); + $this->assertSame('My project 2', $project['name']); + $this->assertEquals('', $project['owner_name']); + $this->assertEquals('', $project['owner_username']); + $this->assertEquals(0, $project['owner_id']); + } +} diff --git a/tests/units/Model/ProjectTaskPriorityModelTest.php b/tests/units/Model/ProjectTaskPriorityModelTest.php new file mode 100644 index 00000000..61661e5e --- /dev/null +++ b/tests/units/Model/ProjectTaskPriorityModelTest.php @@ -0,0 +1,84 @@ +container); + $projectTaskPriorityModel = new ProjectTaskPriorityModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'My project 2'))); + $this->assertEquals(0, $projectTaskPriorityModel->getDefaultPriority(1)); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(0, $project['priority_default']); + $this->assertEquals(0, $project['priority_start']); + $this->assertEquals(3, $project['priority_end']); + + $this->assertEquals( + array(0 => 0, 1 => 1, 2 => 2, 3 => 3), + $projectTaskPriorityModel->getPriorities($project) + ); + + $this->assertTrue($projectModel->update(array('id' => 1, 'priority_start' => 2, 'priority_end' => 5, 'priority_default' => 4))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(4, $project['priority_default']); + $this->assertEquals(2, $project['priority_start']); + $this->assertEquals(5, $project['priority_end']); + + $this->assertEquals( + array(2 => 2, 3 => 3, 4 => 4, 5 => 5), + $projectTaskPriorityModel->getPriorities($project) + ); + + $this->assertEquals(4, $projectTaskPriorityModel->getDefaultPriority(1)); + } + + public function testGetPrioritySettings() + { + $projectModel = new ProjectModel($this->container); + $projectTaskPriorityModel = new ProjectTaskPriorityModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'My project 2'))); + + $expected = array( + 'priority_default' => 0, + 'priority_start' => 0, + 'priority_end' => 3, + ); + + $this->assertEquals($expected, $projectTaskPriorityModel->getPrioritySettings(1)); + $this->assertNull($projectTaskPriorityModel->getPrioritySettings(2)); + } + + public function testGetPriorityForProject() + { + $projectModel = new ProjectModel($this->container); + $projectTaskPriorityModel = new ProjectTaskPriorityModel($this->container); + + $this->assertEquals(1, $projectModel->create(array( + 'name' => 'My project 1', + 'priority_default' => 2, + 'priority_start' => -2, + 'priority_end' => 8, + ))); + + $this->assertEquals(2, $projectTaskPriorityModel->getPriorityForProject(1, 42)); + $this->assertEquals(0, $projectTaskPriorityModel->getPriorityForProject(1, 0)); + $this->assertEquals(1, $projectTaskPriorityModel->getPriorityForProject(1, 1)); + $this->assertEquals(-2, $projectTaskPriorityModel->getPriorityForProject(1, -2)); + $this->assertEquals(-1, $projectTaskPriorityModel->getPriorityForProject(1, -1)); + $this->assertEquals(8, $projectTaskPriorityModel->getPriorityForProject(1, 8)); + $this->assertEquals(5, $projectTaskPriorityModel->getPriorityForProject(1, 5)); + $this->assertEquals(2, $projectTaskPriorityModel->getPriorityForProject(1, 9)); + $this->assertEquals(2, $projectTaskPriorityModel->getPriorityForProject(1, -3)); + } +} diff --git a/tests/units/Model/ProjectTest.php b/tests/units/Model/ProjectTest.php deleted file mode 100644 index 472d7351..00000000 --- a/tests/units/Model/ProjectTest.php +++ /dev/null @@ -1,336 +0,0 @@ -container); - - foreach ($this->container['languageModel']->getLanguages() as $locale => $language) { - Translator::unload(); - Translator::load($locale); - $this->assertNotFalse($p->create(array('name' => 'UnitTest '.$locale)), 'Unable to create project with '.$locale.':'.$language); - } - - Translator::unload(); - } - - public function testCreation() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(1, $project['is_active']); - $this->assertEquals(0, $project['is_public']); - $this->assertEquals(0, $project['is_private']); - $this->assertEquals(time(), $project['last_modified'], '', 1); - $this->assertEmpty($project['token']); - } - - public function testCreationWithDuplicateName() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - $this->assertEquals(2, $p->create(array('name' => 'UnitTest'))); - } - - public function testCreationWithStartAndDate() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest', 'start_date' => '2015-01-01', 'end_date' => '2015-12-31'))); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals('2015-01-01', $project['start_date']); - $this->assertEquals('2015-12-31', $project['end_date']); - } - - public function testCreationWithDefaultCategories() - { - $p = new ProjectModel($this->container); - $c = new ConfigModel($this->container); - $cat = new CategoryModel($this->container); - - // Multiple categories correctly formatted - - $this->assertTrue($c->save(array('project_categories' => 'Test1, Test2'))); - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - - $categories = $cat->getAll(1); - $this->assertNotEmpty($categories); - $this->assertEquals(2, count($categories)); - $this->assertEquals('Test1', $categories[0]['name']); - $this->assertEquals('Test2', $categories[1]['name']); - - // Single category - - $this->assertTrue($c->save(array('project_categories' => 'Test1'))); - $this->container['memoryCache']->flush(); - $this->assertEquals(2, $p->create(array('name' => 'UnitTest2'))); - - $project = $p->getById(2); - $this->assertNotEmpty($project); - - $categories = $cat->getAll(2); - $this->assertNotEmpty($categories); - $this->assertEquals(1, count($categories)); - $this->assertEquals('Test1', $categories[0]['name']); - - // Multiple categories badly formatted - - $this->assertTrue($c->save(array('project_categories' => 'ABC, , DEF 3, '))); - $this->container['memoryCache']->flush(); - $this->assertEquals(3, $p->create(array('name' => 'UnitTest3'))); - - $project = $p->getById(3); - $this->assertNotEmpty($project); - - $categories = $cat->getAll(3); - $this->assertNotEmpty($categories); - $this->assertEquals(2, count($categories)); - $this->assertEquals('ABC', $categories[0]['name']); - $this->assertEquals('DEF 3', $categories[1]['name']); - - // No default categories - $this->assertTrue($c->save(array('project_categories' => ' '))); - $this->container['memoryCache']->flush(); - $this->assertEquals(4, $p->create(array('name' => 'UnitTest4'))); - - $project = $p->getById(4); - $this->assertNotEmpty($project); - - $categories = $cat->getAll(4); - $this->assertEmpty($categories); - } - - public function testUpdateLastModifiedDate() - { - $p = new ProjectModel($this->container); - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - - $now = time(); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals($now, $project['last_modified'], 'Wrong Timestamp', 1); - - sleep(1); - $this->assertTrue($p->updateModificationDate(1)); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertGreaterThan($now, $project['last_modified']); - } - - public function testGetAllIds() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - - $this->assertEmpty($p->getAllByIds(array())); - $this->assertNotEmpty($p->getAllByIds(array(1, 2))); - $this->assertCount(1, $p->getAllByIds(array(1))); - } - - public function testIsLastModified() - { - $p = new ProjectModel($this->container); - $tc = new TaskCreationModel($this->container); - - $now = time(); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals($now, $project['last_modified']); - - sleep(1); - - $listener = new ProjectModificationDateSubscriber($this->container); - $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE_UPDATE, array($listener, 'execute')); - - $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1))); - - $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.Kanboard\Subscriber\ProjectModificationDateSubscriber::execute', $called); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertTrue($p->isModifiedSince(1, $now)); - } - - public function testRemove() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - $this->assertTrue($p->remove(1)); - $this->assertFalse($p->remove(1234)); - } - - public function testEnable() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - $this->assertTrue($p->disable(1)); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(0, $project['is_active']); - - $this->assertFalse($p->disable(1111)); - } - - public function testDisable() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - $this->assertTrue($p->disable(1)); - $this->assertTrue($p->enable(1)); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(1, $project['is_active']); - - $this->assertFalse($p->enable(1234567)); - } - - public function testEnablePublicAccess() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - $this->assertTrue($p->enablePublicAccess(1)); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(1, $project['is_public']); - $this->assertNotEmpty($project['token']); - - $this->assertFalse($p->enablePublicAccess(123)); - } - - public function testDisablePublicAccess() - { - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); - $this->assertTrue($p->enablePublicAccess(1)); - $this->assertTrue($p->disablePublicAccess(1)); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(0, $project['is_public']); - $this->assertEmpty($project['token']); - - $this->assertFalse($p->disablePublicAccess(123)); - } - - public function testIdentifier() - { - $p = new ProjectModel($this->container); - - // Creation - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1', 'identifier' => 'test1'))); - $this->assertEquals(2, $p->create(array('name' => 'UnitTest2'))); - - $project = $p->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals('TEST1', $project['identifier']); - - $project = $p->getById(2); - $this->assertNotEmpty($project); - $this->assertEquals('', $project['identifier']); - - // Update - $this->assertTrue($p->update(array('id' => '2', 'identifier' => 'test2'))); - - $project = $p->getById(2); - $this->assertNotEmpty($project); - $this->assertEquals('TEST2', $project['identifier']); - - $project = $p->getByIdentifier('test1'); - $this->assertNotEmpty($project); - $this->assertEquals('TEST1', $project['identifier']); - - $project = $p->getByIdentifier(''); - $this->assertFalse($project); - } - - public function testThatProjectCreatorAreAlsoOwner() - { - $projectModel = new ProjectModel($this->container); - $userModel = new UserModel($this->container); - - $this->assertEquals(2, $userModel->create(array('username' => 'user1', 'name' => 'Me'))); - $this->assertEquals(1, $projectModel->create(array('name' => 'My project 1'), 2)); - $this->assertEquals(2, $projectModel->create(array('name' => 'My project 2'))); - - $project = $projectModel->getByIdWithOwner(1); - $this->assertNotEmpty($project); - $this->assertSame('My project 1', $project['name']); - $this->assertSame('Me', $project['owner_name']); - $this->assertSame('user1', $project['owner_username']); - $this->assertEquals(2, $project['owner_id']); - - $project = $projectModel->getByIdWithOwner(2); - $this->assertNotEmpty($project); - $this->assertSame('My project 2', $project['name']); - $this->assertEquals('', $project['owner_name']); - $this->assertEquals('', $project['owner_username']); - $this->assertEquals(0, $project['owner_id']); - } - - public function testPriority() - { - $projectModel = new ProjectModel($this->container); - $this->assertEquals(1, $projectModel->create(array('name' => 'My project 2'))); - - $project = $projectModel->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(0, $project['priority_default']); - $this->assertEquals(0, $project['priority_start']); - $this->assertEquals(3, $project['priority_end']); - - $this->assertEquals( - array(0 => 0, 1 => 1, 2 => 2, 3 => 3), - $projectModel->getPriorities($project) - ); - - $this->assertTrue($projectModel->update(array('id' => 1, 'priority_start' => 2, 'priority_end' => 5, 'priority_default' => 4))); - - $project = $projectModel->getById(1); - $this->assertNotEmpty($project); - $this->assertEquals(4, $project['priority_default']); - $this->assertEquals(2, $project['priority_start']); - $this->assertEquals(5, $project['priority_end']); - - $this->assertEquals( - array(2 => 2, 3 => 3, 4 => 4, 5 => 5), - $projectModel->getPriorities($project) - ); - } -} -- cgit v1.2.3 From a8a8bfb0afdd105980181a5fa11701028ff5adfe Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 2 Jul 2016 18:23:47 -0400 Subject: Added more unit tests for LDAP user class --- app/Core/Ldap/User.php | 8 ++--- tests/units/Core/Ldap/LdapUserTest.php | 60 ++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) (limited to 'app/Core') diff --git a/app/Core/Ldap/User.php b/app/Core/Ldap/User.php index 91b48530..4bc1f5f9 100644 --- a/app/Core/Ldap/User.php +++ b/app/Core/Ldap/User.php @@ -116,7 +116,7 @@ class User */ protected function getRole(array $groupIds) { - if ($this->hasGroupsNotConfigured()) { + if (! $this->hasGroupsConfigured()) { return null; } @@ -278,14 +278,14 @@ class User } /** - * Return true if LDAP Group mapping is not configured + * Return true if LDAP Group mapping are configured * * @access public * @return boolean */ - public function hasGroupsNotConfigured() + public function hasGroupsConfigured() { - return !$this->getGroupAdminDn() && !$this->getGroupManagerDn(); + return $this->getGroupAdminDn() || $this->getGroupManagerDn(); } /** diff --git a/tests/units/Core/Ldap/LdapUserTest.php b/tests/units/Core/Ldap/LdapUserTest.php index 505b8a03..143a8c0d 100644 --- a/tests/units/Core/Ldap/LdapUserTest.php +++ b/tests/units/Core/Ldap/LdapUserTest.php @@ -845,4 +845,64 @@ class LdapUserTest extends Base $this->assertTrue($this->user->hasGroupUserFilter()); } + + public function testHasGroupsConfigured() + { + $this->user + ->expects($this->any()) + ->method('getGroupAdminDn') + ->will($this->returnValue('something')); + + $this->user + ->expects($this->any()) + ->method('getGroupManagerDn') + ->will($this->returnValue('something')); + + $this->assertTrue($this->user->hasGroupsConfigured()); + } + + public function testHasGroupAdminDnConfigured() + { + $this->user + ->expects($this->any()) + ->method('getGroupAdminDn') + ->will($this->returnValue('something')); + + $this->user + ->expects($this->any()) + ->method('getGroupManagerDn') + ->will($this->returnValue('')); + + $this->assertTrue($this->user->hasGroupsConfigured()); + } + + public function testHasGroupManagerDnConfigured() + { + $this->user + ->expects($this->any()) + ->method('getGroupAdminDn') + ->will($this->returnValue('')); + + $this->user + ->expects($this->any()) + ->method('getGroupManagerDn') + ->will($this->returnValue('something')); + + $this->assertTrue($this->user->hasGroupsConfigured()); + } + + public function testHasGroupsNotConfigured() + { + $this->user + ->expects($this->any()) + ->method('getGroupAdminDn') + ->will($this->returnValue('')); + + $this->user + ->expects($this->any()) + ->method('getGroupManagerDn') + ->will($this->returnValue('')); + + $this->assertFalse($this->user->hasGroupsConfigured()); + } } -- cgit v1.2.3 From 9496dfdb6df0266b6b7c99c01a4eb9055322b581 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Thu, 14 Jul 2016 11:39:59 -0400 Subject: Make search attributes not case sensitive --- ChangeLog | 1 + app/Core/Filter/LexerBuilder.php | 2 +- tests/units/Core/Filter/LexerBuilderTest.php | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) (limited to 'app/Core') diff --git a/ChangeLog b/ChangeLog index 097ec68e..3fcb6ed6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,7 @@ New features: Improvements: +* Make search attributes not case sensitive * Display TOTP issuer for 2FA * Make sure that the table schema_version use InnoDB for Mysql diff --git a/app/Core/Filter/LexerBuilder.php b/app/Core/Filter/LexerBuilder.php index 7a9a714f..626d7614 100644 --- a/app/Core/Filter/LexerBuilder.php +++ b/app/Core/Filter/LexerBuilder.php @@ -69,7 +69,7 @@ class LexerBuilder foreach ($attributes as $attribute) { $this->filters[$attribute] = $filter; - $this->lexer->addToken(sprintf("/^(%s:)/", $attribute), $attribute); + $this->lexer->addToken(sprintf("/^(%s:)/i", $attribute), $attribute); if ($default) { $this->lexer->setDefaultToken($attribute); diff --git a/tests/units/Core/Filter/LexerBuilderTest.php b/tests/units/Core/Filter/LexerBuilderTest.php index 23726f32..65bb87b9 100644 --- a/tests/units/Core/Filter/LexerBuilderTest.php +++ b/tests/units/Core/Filter/LexerBuilderTest.php @@ -103,4 +103,24 @@ class LexerBuilderTest extends Base $this->assertFalse($builder === $clone); $this->assertFalse($builder->build('test')->getQuery() === $clone->build('test')->getQuery()); } + + public function testBuilderWithMixedCaseSearchAttribute() + { + $project = new ProjectModel($this->container); + $taskCreation = new TaskCreationModel($this->container); + $taskFinder = new TaskFinderModel($this->container); + $query = $taskFinder->getExtendedQuery(); + + $this->assertEquals(1, $project->create(array('name' => 'Project'))); + $this->assertNotFalse($taskCreation->create(array('project_id' => 1, 'title' => 'Test'))); + + $builder = new LexerBuilder(); + $builder->withFilter(new TaskAssigneeFilter()); + $builder->withFilter(new TaskTitleFilter(), true); + $builder->withQuery($query); + $tasks = $builder->build('AsSignEe:nobody')->toArray(); + + $this->assertCount(1, $tasks); + $this->assertEquals('Test', $tasks[0]['title']); + } } -- cgit v1.2.3 From 4364559805245260f89d70d590d0686250aa5f93 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 16 Jul 2016 14:11:14 -0400 Subject: Handle HTTP header X-Real-IP to get IP address --- ChangeLog | 1 + app/Core/Http/Request.php | 1 + tests/units/Core/Http/RequestTest.php | 3 +++ 3 files changed, 5 insertions(+) (limited to 'app/Core') diff --git a/ChangeLog b/ChangeLog index 6c5c5107..64476247 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,7 @@ New features: Improvements: +* Handle header X-Real-IP to get IP address * Display project name for task auto-complete fields * Make search attributes not case sensitive * Display TOTP issuer for 2FA diff --git a/app/Core/Http/Request.php b/app/Core/Http/Request.php index e0df2d3c..2e84958d 100644 --- a/app/Core/Http/Request.php +++ b/app/Core/Http/Request.php @@ -301,6 +301,7 @@ class Request extends Base public function getIpAddress() { $keys = array( + 'HTTP_X_REAL_IP', 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', diff --git a/tests/units/Core/Http/RequestTest.php b/tests/units/Core/Http/RequestTest.php index 6fa796f7..1db0100c 100644 --- a/tests/units/Core/Http/RequestTest.php +++ b/tests/units/Core/Http/RequestTest.php @@ -169,6 +169,9 @@ class RequestTest extends Base $request = new Request($this->container, array(), array(), array(), array(), array()); $this->assertEquals('Unknown', $request->getIpAddress()); + $request = new Request($this->container, array('HTTP_X_REAL_IP' => '192.168.1.1,127.0.0.1'), array(), array(), array(), array()); + $this->assertEquals('192.168.1.1', $request->getIpAddress()); + $request = new Request($this->container, array('HTTP_X_FORWARDED_FOR' => '192.168.0.1,127.0.0.1'), array(), array(), array(), array()); $this->assertEquals('192.168.0.1', $request->getIpAddress()); -- cgit v1.2.3 From ec0ecc5b0387924f061865f4ec12dbfc5b7018fe Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 17 Jul 2016 17:15:14 -0400 Subject: Added event for removed comments with some refactoring --- ChangeLog | 1 + app/Core/Base.php | 2 + app/Core/Queue/JobHandler.php | 24 +++-- app/Core/Queue/QueueManager.php | 6 +- app/EventBuilder/BaseEventBuilder.php | 23 +++++ app/EventBuilder/CommentEventBuilder.php | 48 ++++++++++ app/Job/CommentEventJob.php | 50 ++++++++++ app/Job/NotificationJob.php | 3 +- app/Model/CommentModel.php | 9 +- app/Model/NotificationModel.php | 5 + app/ServiceProvider/ClassProvider.php | 4 + app/Subscriber/NotificationSubscriber.php | 1 + app/Template/event/comment_remove.php | 11 +++ app/Template/event/comment_update.php | 3 + app/Template/notification/comment_remove.php | 7 ++ .../units/EventBuilder/CommentEventBuilderTest.php | 37 +++++++ tests/units/Job/CommentEventJobTest.php | 52 ++++++++++ tests/units/Model/CommentModelTest.php | 106 +++++++++++++++++++++ tests/units/Model/CommentTest.php | 106 --------------------- 19 files changed, 376 insertions(+), 122 deletions(-) create mode 100644 app/EventBuilder/BaseEventBuilder.php create mode 100644 app/EventBuilder/CommentEventBuilder.php create mode 100644 app/Job/CommentEventJob.php create mode 100644 app/Template/event/comment_remove.php create mode 100644 app/Template/notification/comment_remove.php create mode 100644 tests/units/EventBuilder/CommentEventBuilderTest.php create mode 100644 tests/units/Job/CommentEventJobTest.php create mode 100644 tests/units/Model/CommentModelTest.php delete mode 100644 tests/units/Model/CommentTest.php (limited to 'app/Core') diff --git a/ChangeLog b/ChangeLog index e87c0965..a1e39436 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ Version 1.0.32 (unreleased) New features: * New automated action to close tasks without activity in a specific column +* Added new event for removed comments * Added search filter for task priority * Added the possibility to hide tasks in dashboard for a specific column diff --git a/app/Core/Base.php b/app/Core/Base.php index 8103ec14..e413a4ac 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -150,6 +150,8 @@ use Pimple\Container; * @property \Kanboard\Core\Filter\QueryBuilder $taskQuery * @property \Kanboard\Core\Filter\LexerBuilder $taskLexer * @property \Kanboard\Core\Filter\LexerBuilder $projectActivityLexer + * @property \Kanboard\Job\CommentEventJob $commentEventJob + * @property \Kanboard\Job\NotificationJob $notificationJob * @property \Psr\Log\LoggerInterface $logger * @property \PicoDb\Database $db * @property \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher diff --git a/app/Core/Queue/JobHandler.php b/app/Core/Queue/JobHandler.php index 7ca36328..326f3cef 100644 --- a/app/Core/Queue/JobHandler.php +++ b/app/Core/Queue/JobHandler.php @@ -2,6 +2,7 @@ namespace Kanboard\Core\Queue; +use Exception; use Kanboard\Core\Base; use Kanboard\Job\BaseJob; use SimpleQueue\Job; @@ -39,16 +40,23 @@ class JobHandler extends Base public function executeJob(Job $job) { $payload = $job->getBody(); - $className = $payload['class']; - $this->memoryCache->flush(); - $this->prepareJobSession($payload['user_id']); - if (DEBUG) { - $this->logger->debug(__METHOD__.' Received job => '.$className.' ('.getmypid().')'); - } + try { + $className = $payload['class']; + $this->memoryCache->flush(); + $this->prepareJobSession($payload['user_id']); + + if (DEBUG) { + $this->logger->debug(__METHOD__.' Received job => '.$className.' ('.getmypid().')'); + $this->logger->debug(__METHOD__.' => '.json_encode($payload)); + } - $worker = new $className($this->container); - call_user_func_array(array($worker, 'execute'), $payload['params']); + $worker = new $className($this->container); + call_user_func_array(array($worker, 'execute'), $payload['params']); + } catch (Exception $e) { + $this->logger->error(__METHOD__.': Error during job execution: '.$e->getMessage()); + $this->logger->error(__METHOD__ .' => '.json_encode($payload)); + } } /** diff --git a/app/Core/Queue/QueueManager.php b/app/Core/Queue/QueueManager.php index f34cb220..dcf0ebf5 100644 --- a/app/Core/Queue/QueueManager.php +++ b/app/Core/Queue/QueueManager.php @@ -42,9 +42,13 @@ class QueueManager extends Base */ public function push(BaseJob $job) { + $jobClassName = get_class($job); + if ($this->queue !== null) { + $this->logger->debug(__METHOD__.': Job pushed in queue: '.$jobClassName); $this->queue->push(JobHandler::getInstance($this->container)->serializeJob($job)); } else { + $this->logger->debug(__METHOD__.': Job executed synchronously: '.$jobClassName); call_user_func_array(array($job, 'execute'), $job->getJobParams()); } @@ -60,7 +64,7 @@ class QueueManager extends Base public function listen() { if ($this->queue === null) { - throw new LogicException('No Queue Driver defined!'); + throw new LogicException('No queue driver defined!'); } while ($job = $this->queue->pull()) { diff --git a/app/EventBuilder/BaseEventBuilder.php b/app/EventBuilder/BaseEventBuilder.php new file mode 100644 index 00000000..c677563e --- /dev/null +++ b/app/EventBuilder/BaseEventBuilder.php @@ -0,0 +1,23 @@ +commentId = $commentId; + return $this; + } + + /** + * Build event data + * + * @access public + * @return CommentEvent|null + */ + public function build() + { + $comment = $this->commentModel->getById($this->commentId); + + if (empty($comment)) { + return null; + } + + return new CommentEvent(array( + 'comment' => $comment, + 'task' => $this->taskFinderModel->getDetails($comment['task_id']), + )); + } +} diff --git a/app/Job/CommentEventJob.php b/app/Job/CommentEventJob.php new file mode 100644 index 00000000..c89350ed --- /dev/null +++ b/app/Job/CommentEventJob.php @@ -0,0 +1,50 @@ +jobParams = array($commentId, $eventName); + return $this; + } + + /** + * Execute job + * + * @param int $commentId + * @param string $eventName + * @return $this + */ + public function execute($commentId, $eventName) + { + $event = CommentEventBuilder::getInstance($this->container) + ->withCommentId($commentId) + ->build(); + + if ($event !== null) { + $this->dispatcher->dispatch($eventName, $event); + + if ($eventName === CommentModel::EVENT_CREATE) { + $this->userMentionModel->fireEvents($event['comment']['comment'], CommentModel::EVENT_USER_MENTION, $event); + } + } + } +} diff --git a/app/Job/NotificationJob.php b/app/Job/NotificationJob.php index 904a9273..cfd0699d 100644 --- a/app/Job/NotificationJob.php +++ b/app/Job/NotificationJob.php @@ -75,8 +75,7 @@ class NotificationJob extends BaseJob $values['task'] = $this->taskFinderModel->getDetails($values['file']['task_id']); break; case 'Kanboard\Event\CommentEvent': - $values['comment'] = $this->commentModel->getById($event['id']); - $values['task'] = $this->taskFinderModel->getDetails($values['comment']['task_id']); + $values = $event; break; } diff --git a/app/Model/CommentModel.php b/app/Model/CommentModel.php index 4231f29d..6b983858 100644 --- a/app/Model/CommentModel.php +++ b/app/Model/CommentModel.php @@ -2,7 +2,6 @@ namespace Kanboard\Model; -use Kanboard\Event\CommentEvent; use Kanboard\Core\Base; /** @@ -27,6 +26,7 @@ class CommentModel extends Base */ const EVENT_UPDATE = 'comment.update'; const EVENT_CREATE = 'comment.create'; + const EVENT_REMOVE = 'comment.remove'; const EVENT_USER_MENTION = 'comment.user.mention'; /** @@ -130,9 +130,7 @@ class CommentModel extends Base $comment_id = $this->db->table(self::TABLE)->persist($values); if ($comment_id !== false) { - $event = new CommentEvent(array('id' => $comment_id) + $values); - $this->dispatcher->dispatch(self::EVENT_CREATE, $event); - $this->userMentionModel->fireEvents($values['comment'], self::EVENT_USER_MENTION, $event); + $this->queueManager->push($this->commentEventJob->withParams($comment_id, self::EVENT_CREATE)); } return $comment_id; @@ -153,7 +151,7 @@ class CommentModel extends Base ->update(array('comment' => $values['comment'])); if ($result) { - $this->container['dispatcher']->dispatch(self::EVENT_UPDATE, new CommentEvent($values)); + $this->queueManager->push($this->commentEventJob->withParams($values['id'], self::EVENT_UPDATE)); } return $result; @@ -168,6 +166,7 @@ class CommentModel extends Base */ public function remove($comment_id) { + $this->commentEventJob->execute($comment_id, self::EVENT_REMOVE); return $this->db->table(self::TABLE)->eq('id', $comment_id)->remove(); } } diff --git a/app/Model/NotificationModel.php b/app/Model/NotificationModel.php index 4d697b5e..df481fc7 100644 --- a/app/Model/NotificationModel.php +++ b/app/Model/NotificationModel.php @@ -74,6 +74,8 @@ class NotificationModel extends Base return e('%s updated a comment on the task #%d', $event_author, $event_data['task']['id']); case CommentModel::EVENT_CREATE: return e('%s commented on the task #%d', $event_author, $event_data['task']['id']); + case CommentModel::EVENT_REMOVE: + return e('%s removed a comment on the task #%d', $event_author, $event_data['task']['id']); case TaskFileModel::EVENT_CREATE: return e('%s attached a file to the task #%d', $event_author, $event_data['task']['id']); case TaskModel::EVENT_USER_MENTION: @@ -102,6 +104,8 @@ class NotificationModel extends Base return e('New comment on task #%d', $event_data['comment']['task_id']); case CommentModel::EVENT_UPDATE: return e('Comment updated on task #%d', $event_data['comment']['task_id']); + case CommentModel::EVENT_REMOVE: + return e('Comment removed on task #%d', $event_data['comment']['task_id']); case SubtaskModel::EVENT_CREATE: return e('New subtask on task #%d', $event_data['subtask']['task_id']); case SubtaskModel::EVENT_UPDATE: @@ -149,6 +153,7 @@ class NotificationModel extends Base return $event_data['file']['task_id']; case CommentModel::EVENT_CREATE: case CommentModel::EVENT_UPDATE: + case CommentModel::EVENT_REMOVE: return $event_data['comment']['task_id']; case SubtaskModel::EVENT_CREATE: case SubtaskModel::EVENT_UPDATE: diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index e32c0d43..43ade56e 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -26,6 +26,10 @@ class ClassProvider implements ServiceProviderInterface 'AverageLeadCycleTimeAnalytic', 'AverageTimeSpentColumnAnalytic', ), + 'Job' => array( + 'CommentEventJob', + 'NotificationJob', + ), 'Model' => array( 'ActionModel', 'ActionParameterModel', diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php index db11e585..6cd7675c 100644 --- a/app/Subscriber/NotificationSubscriber.php +++ b/app/Subscriber/NotificationSubscriber.php @@ -28,6 +28,7 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn SubtaskModel::EVENT_UPDATE => 'handleEvent', CommentModel::EVENT_CREATE => 'handleEvent', CommentModel::EVENT_UPDATE => 'handleEvent', + CommentModel::EVENT_REMOVE => 'handleEvent', CommentModel::EVENT_USER_MENTION => 'handleEvent', TaskFileModel::EVENT_CREATE => 'handleEvent', ); diff --git a/app/Template/event/comment_remove.php b/app/Template/event/comment_remove.php new file mode 100644 index 00000000..ead7d56a --- /dev/null +++ b/app/Template/event/comment_remove.php @@ -0,0 +1,11 @@ +

    + text->e($author), + $this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) + ) ?> + dt->datetime($date_creation) ?> +

    +
    +

    text->e($task['title']) ?>

    +
    text->markdown($comment['comment']) ?>
    +
    diff --git a/app/Template/event/comment_update.php b/app/Template/event/comment_update.php index 5a0821bd..5be598ac 100644 --- a/app/Template/event/comment_update.php +++ b/app/Template/event/comment_update.php @@ -7,4 +7,7 @@

    text->e($task['title']) ?>

    + +
    text->markdown($comment['comment']) ?>
    +
    diff --git a/app/Template/notification/comment_remove.php b/app/Template/notification/comment_remove.php new file mode 100644 index 00000000..928623ec --- /dev/null +++ b/app/Template/notification/comment_remove.php @@ -0,0 +1,7 @@ +

    text->e($task['title']) ?> (#)

    + +

    + +text->markdown($comment['comment']) ?> + +render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> diff --git a/tests/units/EventBuilder/CommentEventBuilderTest.php b/tests/units/EventBuilder/CommentEventBuilderTest.php new file mode 100644 index 00000000..a490799e --- /dev/null +++ b/tests/units/EventBuilder/CommentEventBuilderTest.php @@ -0,0 +1,37 @@ +container); + $commentEventBuilder->withCommentId(42); + $this->assertNull($commentEventBuilder->build()); + } + + public function testBuild() + { + $commentModel = new CommentModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $commentEventBuilder = new CommentEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'bla bla', 'user_id' => 1))); + + $commentEventBuilder->withCommentId(1); + $event = $commentEventBuilder->build(); + + $this->assertInstanceOf('Kanboard\Event\CommentEvent', $event); + $this->assertNotEmpty($event['comment']); + $this->assertNotEmpty($event['task']); + } +} diff --git a/tests/units/Job/CommentEventJobTest.php b/tests/units/Job/CommentEventJobTest.php new file mode 100644 index 00000000..88742feb --- /dev/null +++ b/tests/units/Job/CommentEventJobTest.php @@ -0,0 +1,52 @@ +container); + $commentEventJob->withParams(123, 'foobar'); + + $this->assertSame(array(123, 'foobar'), $commentEventJob->getJobParams()); + } + + public function testWithMissingComment() + { + $this->container['dispatcher']->addListener(CommentModel::EVENT_CREATE, function() {}); + + $commentEventJob = new CommentEventJob($this->container); + $commentEventJob->execute(42, CommentModel::EVENT_CREATE); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertEmpty($called); + } + + public function testTriggerEvents() + { + $this->container['dispatcher']->addListener(CommentModel::EVENT_CREATE, function() {}); + $this->container['dispatcher']->addListener(CommentModel::EVENT_UPDATE, function() {}); + $this->container['dispatcher']->addListener(CommentModel::EVENT_REMOVE, function() {}); + + $commentModel = new CommentModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'foobar', 'user_id' => 1))); + $this->assertTrue($commentModel->update(array('id' => 1, 'comment' => 'test'))); + $this->assertTrue($commentModel->remove(1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(CommentModel::EVENT_CREATE.'.closure', $called); + $this->assertArrayHasKey(CommentModel::EVENT_UPDATE.'.closure', $called); + $this->assertArrayHasKey(CommentModel::EVENT_REMOVE.'.closure', $called); + } +} diff --git a/tests/units/Model/CommentModelTest.php b/tests/units/Model/CommentModelTest.php new file mode 100644 index 00000000..4178a839 --- /dev/null +++ b/tests/units/Model/CommentModelTest.php @@ -0,0 +1,106 @@ +container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'bla bla', 'user_id' => 1))); + $this->assertEquals(2, $commentModel->create(array('task_id' => 1, 'comment' => 'bla bla'))); + + $comment = $commentModel->getById(1); + $this->assertNotEmpty($comment); + $this->assertEquals('bla bla', $comment['comment']); + $this->assertEquals(1, $comment['task_id']); + $this->assertEquals(1, $comment['user_id']); + $this->assertEquals('admin', $comment['username']); + $this->assertEquals(time(), $comment['date_creation'], '', 3); + + $comment = $commentModel->getById(2); + $this->assertNotEmpty($comment); + $this->assertEquals('bla bla', $comment['comment']); + $this->assertEquals(1, $comment['task_id']); + $this->assertEquals(0, $comment['user_id']); + $this->assertEquals('', $comment['username']); + $this->assertEquals(time(), $comment['date_creation'], '', 3); + } + + public function testGetAll() + { + $commentModel = new CommentModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); + $this->assertEquals(2, $commentModel->create(array('task_id' => 1, 'comment' => 'c2', 'user_id' => 1))); + $this->assertEquals(3, $commentModel->create(array('task_id' => 1, 'comment' => 'c3', 'user_id' => 1))); + + $comments = $commentModel->getAll(1); + + $this->assertNotEmpty($comments); + $this->assertEquals(3, count($comments)); + $this->assertEquals(1, $comments[0]['id']); + $this->assertEquals(2, $comments[1]['id']); + $this->assertEquals(3, $comments[2]['id']); + + $this->assertEquals(3, $commentModel->count(1)); + } + + public function testUpdate() + { + $commentModel = new CommentModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); + $this->assertTrue($commentModel->update(array('id' => 1, 'comment' => 'bla'))); + + $comment = $commentModel->getById(1); + $this->assertNotEmpty($comment); + $this->assertEquals('bla', $comment['comment']); + } + + public function testRemove() + { + $commentModel = new CommentModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); + + $this->assertTrue($commentModel->remove(1)); + $this->assertFalse($commentModel->remove(1)); + $this->assertFalse($commentModel->remove(1111)); + } + + public function testGetProjectId() + { + $commentModel = new CommentModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); + + $this->assertEquals(1, $commentModel->getProjectId(1)); + $this->assertSame(0, $commentModel->getProjectId(2)); + } +} diff --git a/tests/units/Model/CommentTest.php b/tests/units/Model/CommentTest.php deleted file mode 100644 index 574b5a87..00000000 --- a/tests/units/Model/CommentTest.php +++ /dev/null @@ -1,106 +0,0 @@ -container); - $taskCreationModel = new TaskCreationModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); - $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'bla bla', 'user_id' => 1))); - $this->assertEquals(2, $commentModel->create(array('task_id' => 1, 'comment' => 'bla bla'))); - - $comment = $commentModel->getById(1); - $this->assertNotEmpty($comment); - $this->assertEquals('bla bla', $comment['comment']); - $this->assertEquals(1, $comment['task_id']); - $this->assertEquals(1, $comment['user_id']); - $this->assertEquals('admin', $comment['username']); - $this->assertEquals(time(), $comment['date_creation'], '', 3); - - $comment = $commentModel->getById(2); - $this->assertNotEmpty($comment); - $this->assertEquals('bla bla', $comment['comment']); - $this->assertEquals(1, $comment['task_id']); - $this->assertEquals(0, $comment['user_id']); - $this->assertEquals('', $comment['username']); - $this->assertEquals(time(), $comment['date_creation'], '', 3); - } - - public function testGetAll() - { - $commentModel = new CommentModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); - $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); - $this->assertEquals(2, $commentModel->create(array('task_id' => 1, 'comment' => 'c2', 'user_id' => 1))); - $this->assertEquals(3, $commentModel->create(array('task_id' => 1, 'comment' => 'c3', 'user_id' => 1))); - - $comments = $commentModel->getAll(1); - - $this->assertNotEmpty($comments); - $this->assertEquals(3, count($comments)); - $this->assertEquals(1, $comments[0]['id']); - $this->assertEquals(2, $comments[1]['id']); - $this->assertEquals(3, $comments[2]['id']); - - $this->assertEquals(3, $commentModel->count(1)); - } - - public function testUpdate() - { - $commentModel = new CommentModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); - $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); - $this->assertTrue($commentModel->update(array('id' => 1, 'comment' => 'bla'))); - - $comment = $commentModel->getById(1); - $this->assertNotEmpty($comment); - $this->assertEquals('bla', $comment['comment']); - } - - public function validateRemove() - { - $commentModel = new CommentModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); - $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); - - $this->assertTrue($commentModel->remove(1)); - $this->assertFalse($commentModel->remove(1)); - $this->assertFalse($commentModel->remove(1111)); - } - - public function testGetProjectId() - { - $commentModel = new CommentModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1))); - $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1))); - - $this->assertEquals(1, $commentModel->getProjectId(1)); - $this->assertSame(0, $commentModel->getProjectId(2)); - } -} -- cgit v1.2.3 From cbe52e57200a66522d88dfc5d5f46de8eb87ffb2 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 17 Jul 2016 18:47:06 -0400 Subject: File events refactoring --- app/Core/Base.php | 2 + app/Event/FileEvent.php | 7 --- app/Event/ProjectFileEvent.php | 7 +++ app/Event/TaskFileEvent.php | 7 +++ app/EventBuilder/ProjectFileEventBuilder.php | 50 ++++++++++++++++++++++ app/EventBuilder/TaskFileEventBuilder.php | 50 ++++++++++++++++++++++ app/Job/NotificationJob.php | 7 +-- app/Job/ProjectFileEventJob.php | 45 +++++++++++++++++++ app/Job/TaskFileEventJob.php | 45 +++++++++++++++++++ app/Model/FileModel.php | 22 +++++----- app/Model/ProjectFileModel.php | 9 ++-- app/Model/TaskFileModel.php | 23 +++++----- app/ServiceProvider/ClassProvider.php | 2 + app/Subscriber/BaseSubscriber.php | 24 ----------- app/Subscriber/NotificationSubscriber.php | 10 ++--- app/Subscriber/ProjectDailySummarySubscriber.php | 2 +- .../ProjectModificationDateSubscriber.php | 2 +- .../EventBuilder/ProjectFileEventBuilderTest.php | 33 ++++++++++++++ .../EventBuilder/TaskFileEventBuilderTest.php | 36 ++++++++++++++++ tests/units/Job/ProjectFileEventJobTest.php | 43 +++++++++++++++++++ tests/units/Job/TaskFileEventJobTest.php | 46 ++++++++++++++++++++ 21 files changed, 398 insertions(+), 74 deletions(-) delete mode 100644 app/Event/FileEvent.php create mode 100644 app/Event/ProjectFileEvent.php create mode 100644 app/Event/TaskFileEvent.php create mode 100644 app/EventBuilder/ProjectFileEventBuilder.php create mode 100644 app/EventBuilder/TaskFileEventBuilder.php create mode 100644 app/Job/ProjectFileEventJob.php create mode 100644 app/Job/TaskFileEventJob.php create mode 100644 tests/units/EventBuilder/ProjectFileEventBuilderTest.php create mode 100644 tests/units/EventBuilder/TaskFileEventBuilderTest.php create mode 100644 tests/units/Job/ProjectFileEventJobTest.php create mode 100644 tests/units/Job/TaskFileEventJobTest.php (limited to 'app/Core') diff --git a/app/Core/Base.php b/app/Core/Base.php index e413a4ac..09e04456 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -151,6 +151,8 @@ use Pimple\Container; * @property \Kanboard\Core\Filter\LexerBuilder $taskLexer * @property \Kanboard\Core\Filter\LexerBuilder $projectActivityLexer * @property \Kanboard\Job\CommentEventJob $commentEventJob + * @property \Kanboard\Job\TaskFileEventJob $taskFileEventJob + * @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob * @property \Kanboard\Job\NotificationJob $notificationJob * @property \Psr\Log\LoggerInterface $logger * @property \PicoDb\Database $db diff --git a/app/Event/FileEvent.php b/app/Event/FileEvent.php deleted file mode 100644 index 482a4eab..00000000 --- a/app/Event/FileEvent.php +++ /dev/null @@ -1,7 +0,0 @@ -fileId = $fileId; + return $this; + } + + /** + * Build event data + * + * @access public + * @return GenericEvent|null + */ + public function build() + { + $file = $this->projectFileModel->getById($this->fileId); + + if (empty($file)) { + $this->logger->debug(__METHOD__.': File not found'); + return null; + } + + return new ProjectFileEvent(array( + 'file' => $file, + 'project' => $this->projectModel->getById($file['project_id']), + )); + } +} diff --git a/app/EventBuilder/TaskFileEventBuilder.php b/app/EventBuilder/TaskFileEventBuilder.php new file mode 100644 index 00000000..7f1ce3b3 --- /dev/null +++ b/app/EventBuilder/TaskFileEventBuilder.php @@ -0,0 +1,50 @@ +fileId = $fileId; + return $this; + } + + /** + * Build event data + * + * @access public + * @return GenericEvent|null + */ + public function build() + { + $file = $this->taskFileModel->getById($this->fileId); + + if (empty($file)) { + $this->logger->debug(__METHOD__.': File not found'); + return null; + } + + return new TaskFileEvent(array( + 'file' => $file, + 'task' => $this->taskFinderModel->getDetails($file['task_id']), + )); + } +} diff --git a/app/Job/NotificationJob.php b/app/Job/NotificationJob.php index cfd0699d..ed568e47 100644 --- a/app/Job/NotificationJob.php +++ b/app/Job/NotificationJob.php @@ -70,13 +70,8 @@ class NotificationJob extends BaseJob $values['subtask'] = $this->subtaskModel->getById($event['id'], true); $values['task'] = $this->taskFinderModel->getDetails($values['subtask']['task_id']); break; - case 'Kanboard\Event\FileEvent': - $values['file'] = $event; - $values['task'] = $this->taskFinderModel->getDetails($values['file']['task_id']); - break; - case 'Kanboard\Event\CommentEvent': + default: $values = $event; - break; } return $values; diff --git a/app/Job/ProjectFileEventJob.php b/app/Job/ProjectFileEventJob.php new file mode 100644 index 00000000..d68949c5 --- /dev/null +++ b/app/Job/ProjectFileEventJob.php @@ -0,0 +1,45 @@ +jobParams = array($fileId, $eventName); + return $this; + } + + /** + * Execute job + * + * @param int $fileId + * @param string $eventName + * @return $this + */ + public function execute($fileId, $eventName) + { + $event = ProjectFileEventBuilder::getInstance($this->container) + ->withFileId($fileId) + ->build(); + + if ($event !== null) { + $this->dispatcher->dispatch($eventName, $event); + } + } +} diff --git a/app/Job/TaskFileEventJob.php b/app/Job/TaskFileEventJob.php new file mode 100644 index 00000000..de2c40db --- /dev/null +++ b/app/Job/TaskFileEventJob.php @@ -0,0 +1,45 @@ +jobParams = array($fileId, $eventName); + return $this; + } + + /** + * Execute job + * + * @param int $fileId + * @param string $eventName + * @return $this + */ + public function execute($fileId, $eventName) + { + $event = TaskFileEventBuilder::getInstance($this->container) + ->withFileId($fileId) + ->build(); + + if ($event !== null) { + $this->dispatcher->dispatch($eventName, $event); + } + } +} diff --git a/app/Model/FileModel.php b/app/Model/FileModel.php index 8cdea9a0..98032f9d 100644 --- a/app/Model/FileModel.php +++ b/app/Model/FileModel.php @@ -5,7 +5,6 @@ namespace Kanboard\Model; use Exception; use Kanboard\Core\Base; use Kanboard\Core\Thumbnail; -use Kanboard\Event\FileEvent; use Kanboard\Core\ObjectStorage\ObjectStorageException; /** @@ -44,13 +43,13 @@ abstract class FileModel extends Base abstract protected function getPathPrefix(); /** - * Get event name + * Fire file creation event * * @abstract * @access protected - * @return string + * @param integer $file_id */ - abstract protected function getEventName(); + abstract protected function fireCreationEvent($file_id); /** * Get PicoDb query to get all files @@ -130,16 +129,16 @@ abstract class FileModel extends Base * Create a file entry in the database * * @access public - * @param integer $id Foreign key - * @param string $name Filename - * @param string $path Path on the disk - * @param integer $size File size + * @param integer $foreign_key_id Foreign key + * @param string $name Filename + * @param string $path Path on the disk + * @param integer $size File size * @return bool|integer */ - public function create($id, $name, $path, $size) + public function create($foreign_key_id, $name, $path, $size) { $values = array( - $this->getForeignKey() => $id, + $this->getForeignKey() => $foreign_key_id, 'name' => substr($name, 0, 255), 'path' => $path, 'is_image' => $this->isImage($name) ? 1 : 0, @@ -152,8 +151,7 @@ abstract class FileModel extends Base if ($result) { $file_id = (int) $this->db->getLastId(); - $event = new FileEvent($values + array('file_id' => $file_id)); - $this->dispatcher->dispatch($this->getEventName(), $event); + $this->fireCreationEvent($file_id); return $file_id; } diff --git a/app/Model/ProjectFileModel.php b/app/Model/ProjectFileModel.php index b464bb2a..4de4d66d 100644 --- a/app/Model/ProjectFileModel.php +++ b/app/Model/ProjectFileModel.php @@ -61,14 +61,13 @@ class ProjectFileModel extends FileModel } /** - * Get event name + * Fire file creation event * - * @abstract * @access protected - * @return string + * @param integer $file_id */ - protected function getEventName() + protected function fireCreationEvent($file_id) { - return self::EVENT_CREATE; + $this->queueManager->push($this->projectFileEventJob->withParams($file_id, self::EVENT_CREATE)); } } diff --git a/app/Model/TaskFileModel.php b/app/Model/TaskFileModel.php index 7603019a..0163da28 100644 --- a/app/Model/TaskFileModel.php +++ b/app/Model/TaskFileModel.php @@ -60,18 +60,6 @@ class TaskFileModel extends FileModel return 'tasks'; } - /** - * Get event name - * - * @abstract - * @access protected - * @return string - */ - protected function getEventName() - { - return self::EVENT_CREATE; - } - /** * Get projectId from fileId * @@ -101,4 +89,15 @@ class TaskFileModel extends FileModel $original_filename = e('Screenshot taken %s', $this->helper->dt->datetime(time())).'.png'; return $this->uploadContent($task_id, $original_filename, $blob); } + + /** + * Fire file creation event + * + * @access protected + * @param integer $file_id + */ + protected function fireCreationEvent($file_id) + { + $this->queueManager->push($this->taskFileEventJob->withParams($file_id, self::EVENT_CREATE)); + } } diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 43ade56e..428a8015 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -28,6 +28,8 @@ class ClassProvider implements ServiceProviderInterface ), 'Job' => array( 'CommentEventJob', + 'TaskFileEventJob', + 'ProjectFileEventJob', 'NotificationJob', ), 'Model' => array( diff --git a/app/Subscriber/BaseSubscriber.php b/app/Subscriber/BaseSubscriber.php index fdea29f6..92441962 100644 --- a/app/Subscriber/BaseSubscriber.php +++ b/app/Subscriber/BaseSubscriber.php @@ -12,28 +12,4 @@ use Kanboard\Core\Base; */ class BaseSubscriber extends Base { - /** - * Method called - * - * @access private - * @var array - */ - private $called = array(); - - /** - * Check if a listener has been executed - * - * @access public - * @param string $key - * @return boolean - */ - public function isExecuted($key = '') - { - if (isset($this->called[$key])) { - return true; - } - - $this->called[$key] = true; - return false; - } } diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php index 6cd7675c..47222f73 100644 --- a/app/Subscriber/NotificationSubscriber.php +++ b/app/Subscriber/NotificationSubscriber.php @@ -36,12 +36,10 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn public function handleEvent(GenericEvent $event, $eventName) { - if (!$this->isExecuted($eventName)) { - $this->logger->debug('Subscriber executed: ' . __METHOD__); + $this->logger->debug('Subscriber executed: ' . __METHOD__); - $this->queueManager->push(NotificationJob::getInstance($this->container) - ->withParams($event, $eventName, get_class($event)) - ); - } + $this->queueManager->push(NotificationJob::getInstance($this->container) + ->withParams($event, $eventName, get_class($event)) + ); } } diff --git a/app/Subscriber/ProjectDailySummarySubscriber.php b/app/Subscriber/ProjectDailySummarySubscriber.php index 6971a121..7e3c11c3 100644 --- a/app/Subscriber/ProjectDailySummarySubscriber.php +++ b/app/Subscriber/ProjectDailySummarySubscriber.php @@ -22,7 +22,7 @@ class ProjectDailySummarySubscriber extends BaseSubscriber implements EventSubsc public function execute(TaskEvent $event) { - if (isset($event['project_id']) && !$this->isExecuted()) { + if (isset($event['project_id'])) { $this->logger->debug('Subscriber executed: '.__METHOD__); $this->queueManager->push(ProjectMetricJob::getInstance($this->container)->withParams($event['project_id'])); } diff --git a/app/Subscriber/ProjectModificationDateSubscriber.php b/app/Subscriber/ProjectModificationDateSubscriber.php index fee04eaa..97923af9 100644 --- a/app/Subscriber/ProjectModificationDateSubscriber.php +++ b/app/Subscriber/ProjectModificationDateSubscriber.php @@ -24,7 +24,7 @@ class ProjectModificationDateSubscriber extends BaseSubscriber implements EventS public function execute(GenericEvent $event) { - if (isset($event['project_id']) && !$this->isExecuted()) { + if (isset($event['project_id'])) { $this->logger->debug('Subscriber executed: '.__METHOD__); $this->projectModel->updateModificationDate($event['project_id']); } diff --git a/tests/units/EventBuilder/ProjectFileEventBuilderTest.php b/tests/units/EventBuilder/ProjectFileEventBuilderTest.php new file mode 100644 index 00000000..bfe22719 --- /dev/null +++ b/tests/units/EventBuilder/ProjectFileEventBuilderTest.php @@ -0,0 +1,33 @@ +container); + $projectFileEventBuilder->withFileId(42); + $this->assertNull($projectFileEventBuilder->build()); + } + + public function testBuild() + { + $projectModel = new ProjectModel($this->container); + $projectFileModel = new ProjectFileModel($this->container); + $projectFileEventBuilder = new ProjectFileEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $projectFileModel->create(1, 'Test', '/tmp/test', 123)); + + $event = $projectFileEventBuilder->withFileId(1)->build(); + + $this->assertInstanceOf('Kanboard\Event\ProjectFileEvent', $event); + $this->assertNotEmpty($event['file']); + $this->assertNotEmpty($event['project']); + } +} diff --git a/tests/units/EventBuilder/TaskFileEventBuilderTest.php b/tests/units/EventBuilder/TaskFileEventBuilderTest.php new file mode 100644 index 00000000..c253b913 --- /dev/null +++ b/tests/units/EventBuilder/TaskFileEventBuilderTest.php @@ -0,0 +1,36 @@ +container); + $taskFileEventBuilder->withFileId(42); + $this->assertNull($taskFileEventBuilder->build()); + } + + public function testBuild() + { + $taskFileModel = new TaskFileModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskFileEventBuilder = new TaskFileEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $taskFileModel->create(1, 'Test', '/tmp/test', 123)); + + $event = $taskFileEventBuilder->withFileId(1)->build(); + + $this->assertInstanceOf('Kanboard\Event\TaskFileEvent', $event); + $this->assertNotEmpty($event['file']); + $this->assertNotEmpty($event['task']); + } +} diff --git a/tests/units/Job/ProjectFileEventJobTest.php b/tests/units/Job/ProjectFileEventJobTest.php new file mode 100644 index 00000000..f266d293 --- /dev/null +++ b/tests/units/Job/ProjectFileEventJobTest.php @@ -0,0 +1,43 @@ +container); + $projectFileEventJob->withParams(123, 'foobar'); + + $this->assertSame(array(123, 'foobar'), $projectFileEventJob->getJobParams()); + } + + public function testWithMissingFile() + { + $this->container['dispatcher']->addListener(ProjectFileModel::EVENT_CREATE, function() {}); + + $projectFileEventJob = new ProjectFileEventJob($this->container); + $projectFileEventJob->execute(42, ProjectFileModel::EVENT_CREATE); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertEmpty($called); + } + + public function testTriggerEvents() + { + $this->container['dispatcher']->addListener(ProjectFileModel::EVENT_CREATE, function() {}); + + $projectModel = new ProjectModel($this->container); + $projectFileModel = new ProjectFileModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $projectFileModel->create(1, 'Test', '/tmp/test', 123)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(ProjectFileModel::EVENT_CREATE.'.closure', $called); + } +} diff --git a/tests/units/Job/TaskFileEventJobTest.php b/tests/units/Job/TaskFileEventJobTest.php new file mode 100644 index 00000000..921fe801 --- /dev/null +++ b/tests/units/Job/TaskFileEventJobTest.php @@ -0,0 +1,46 @@ +container); + $taskFileEventJob->withParams(123, 'foobar'); + + $this->assertSame(array(123, 'foobar'), $taskFileEventJob->getJobParams()); + } + + public function testWithMissingFile() + { + $this->container['dispatcher']->addListener(TaskFileModel::EVENT_CREATE, function() {}); + + $taskFileEventJob = new TaskFileEventJob($this->container); + $taskFileEventJob->execute(42, TaskFileModel::EVENT_CREATE); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertEmpty($called); + } + + public function testTriggerEvents() + { + $this->container['dispatcher']->addListener(TaskFileModel::EVENT_CREATE, function() {}); + + $taskFileModel = new TaskFileModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $taskFileModel->create(1, 'Test', '/tmp/test', 123)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskFileModel::EVENT_CREATE.'.closure', $called); + } +} -- cgit v1.2.3 From d9d37882228771bca0c7f53f5ffcef90ba7ac1c5 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 17 Jul 2016 20:33:27 -0400 Subject: Subtasks events refactoring and show delete in activity stream --- app/Core/Base.php | 1 + app/EventBuilder/SubtaskEventBuilder.php | 79 ++++++++++++++++++++++ app/Job/NotificationJob.php | 4 -- app/Job/SubtaskEventJob.php | 48 +++++++++++++ app/Model/NotificationModel.php | 5 ++ app/Model/SubtaskModel.php | 22 ++---- app/ServiceProvider/ClassProvider.php | 6 -- app/ServiceProvider/JobProvider.php | 52 ++++++++++++++ app/ServiceProvider/QueueProvider.php | 6 +- app/Subscriber/NotificationSubscriber.php | 1 + app/Template/event/subtask_delete.php | 15 ++++ app/Template/notification/subtask_delete.php | 11 +++ app/common.php | 1 + tests/units/Base.php | 1 + .../units/EventBuilder/SubtaskEventBuilderTest.php | 62 +++++++++++++++++ tests/units/Job/SubtaskEventJobTest.php | 52 ++++++++++++++ tests/units/Model/SubtaskModelTest.php | 70 +------------------ 17 files changed, 339 insertions(+), 97 deletions(-) create mode 100644 app/EventBuilder/SubtaskEventBuilder.php create mode 100644 app/Job/SubtaskEventJob.php create mode 100644 app/ServiceProvider/JobProvider.php create mode 100644 app/Template/event/subtask_delete.php create mode 100644 app/Template/notification/subtask_delete.php create mode 100644 tests/units/EventBuilder/SubtaskEventBuilderTest.php create mode 100644 tests/units/Job/SubtaskEventJobTest.php (limited to 'app/Core') diff --git a/app/Core/Base.php b/app/Core/Base.php index 09e04456..6650680b 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -151,6 +151,7 @@ use Pimple\Container; * @property \Kanboard\Core\Filter\LexerBuilder $taskLexer * @property \Kanboard\Core\Filter\LexerBuilder $projectActivityLexer * @property \Kanboard\Job\CommentEventJob $commentEventJob + * @property \Kanboard\Job\SubtaskEventJob $subtaskEventJob * @property \Kanboard\Job\TaskFileEventJob $taskFileEventJob * @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob * @property \Kanboard\Job\NotificationJob $notificationJob diff --git a/app/EventBuilder/SubtaskEventBuilder.php b/app/EventBuilder/SubtaskEventBuilder.php new file mode 100644 index 00000000..f0271257 --- /dev/null +++ b/app/EventBuilder/SubtaskEventBuilder.php @@ -0,0 +1,79 @@ +subtaskId = $subtaskId; + return $this; + } + + /** + * Set values + * + * @param array $values + * @return $this + */ + public function withValues(array $values) + { + $this->values = $values; + return $this; + } + + /** + * Build event data + * + * @access public + * @return GenericEvent|null + */ + public function build() + { + $eventData = array(); + $eventData['subtask'] = $this->subtaskModel->getById($this->subtaskId, true); + + if (empty($eventData['subtask'])) { + $this->logger->debug(__METHOD__.': Subtask not found'); + return null; + } + + if (! empty($this->values)) { + $eventData['changes'] = array_diff_assoc($this->values, $eventData['subtask']); + } + + $eventData['task'] = $this->taskFinderModel->getDetails($eventData['subtask']['task_id']); + return new SubtaskEvent($eventData); + } +} diff --git a/app/Job/NotificationJob.php b/app/Job/NotificationJob.php index ed568e47..5a52eb31 100644 --- a/app/Job/NotificationJob.php +++ b/app/Job/NotificationJob.php @@ -66,10 +66,6 @@ class NotificationJob extends BaseJob case 'Kanboard\Event\TaskEvent': $values['task'] = $this->taskFinderModel->getDetails($event['task_id']); break; - case 'Kanboard\Event\SubtaskEvent': - $values['subtask'] = $this->subtaskModel->getById($event['id'], true); - $values['task'] = $this->taskFinderModel->getDetails($values['subtask']['task_id']); - break; default: $values = $event; } diff --git a/app/Job/SubtaskEventJob.php b/app/Job/SubtaskEventJob.php new file mode 100644 index 00000000..1dc243ef --- /dev/null +++ b/app/Job/SubtaskEventJob.php @@ -0,0 +1,48 @@ +jobParams = array($subtaskId, $eventName, $values); + return $this; + } + + /** + * Execute job + * + * @param int $subtaskId + * @param string $eventName + * @param array $values + * @return $this + */ + public function execute($subtaskId, $eventName, array $values = array()) + { + $event = SubtaskEventBuilder::getInstance($this->container) + ->withSubtaskId($subtaskId) + ->withValues($values) + ->build(); + + if ($event !== null) { + $this->dispatcher->dispatch($eventName, $event); + } + } +} diff --git a/app/Model/NotificationModel.php b/app/Model/NotificationModel.php index df481fc7..ac8d9bae 100644 --- a/app/Model/NotificationModel.php +++ b/app/Model/NotificationModel.php @@ -70,6 +70,8 @@ class NotificationModel extends Base return e('%s updated a subtask for the task #%d', $event_author, $event_data['task']['id']); case SubtaskModel::EVENT_CREATE: return e('%s created a subtask for the task #%d', $event_author, $event_data['task']['id']); + case SubtaskModel::EVENT_DELETE: + return e('%s removed a subtask for the task #%d', $event_author, $event_data['task']['id']); case CommentModel::EVENT_UPDATE: return e('%s updated a comment on the task #%d', $event_author, $event_data['task']['id']); case CommentModel::EVENT_CREATE: @@ -110,6 +112,8 @@ class NotificationModel extends Base return e('New subtask on task #%d', $event_data['subtask']['task_id']); case SubtaskModel::EVENT_UPDATE: return e('Subtask updated on task #%d', $event_data['subtask']['task_id']); + case SubtaskModel::EVENT_DELETE: + return e('Subtask removed on task #%d', $event_data['subtask']['task_id']); case TaskModel::EVENT_CREATE: return e('New task #%d: %s', $event_data['task']['id'], $event_data['task']['title']); case TaskModel::EVENT_UPDATE: @@ -157,6 +161,7 @@ class NotificationModel extends Base return $event_data['comment']['task_id']; case SubtaskModel::EVENT_CREATE: case SubtaskModel::EVENT_UPDATE: + case SubtaskModel::EVENT_DELETE: return $event_data['subtask']['task_id']; case TaskModel::EVENT_CREATE: case TaskModel::EVENT_UPDATE: diff --git a/app/Model/SubtaskModel.php b/app/Model/SubtaskModel.php index a97bddbf..6dd1f26a 100644 --- a/app/Model/SubtaskModel.php +++ b/app/Model/SubtaskModel.php @@ -66,7 +66,7 @@ class SubtaskModel extends Base ->join(TaskModel::TABLE, 'id', 'task_id') ->findOneColumn(TaskModel::TABLE . '.project_id') ?: 0; } - + /** * Get available status * @@ -235,10 +235,7 @@ class SubtaskModel extends Base $subtask_id = $this->db->table(self::TABLE)->persist($values); if ($subtask_id !== false) { - $this->container['dispatcher']->dispatch( - self::EVENT_CREATE, - new SubtaskEvent(array('id' => $subtask_id) + $values) - ); + $this->queueManager->push($this->subtaskEventJob->withParams($subtask_id, self::EVENT_CREATE)); } return $subtask_id; @@ -255,13 +252,10 @@ class SubtaskModel extends Base public function update(array $values, $fire_events = true) { $this->prepare($values); - $subtask = $this->getById($values['id']); $result = $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values); if ($result && $fire_events) { - $event = $subtask; - $event['changes'] = array_diff_assoc($values, $subtask); - $this->container['dispatcher']->dispatch(self::EVENT_UPDATE, new SubtaskEvent($event)); + $this->queueManager->push($this->subtaskEventJob->withParams($values['id'], self::EVENT_UPDATE, $values)); } return $result; @@ -377,14 +371,8 @@ class SubtaskModel extends Base */ public function remove($subtask_id) { - $subtask = $this->getById($subtask_id); - $result = $this->db->table(self::TABLE)->eq('id', $subtask_id)->remove(); - - if ($result) { - $this->container['dispatcher']->dispatch(self::EVENT_DELETE, new SubtaskEvent($subtask)); - } - - return $result; + $this->subtaskEventJob->execute($subtask_id, self::EVENT_DELETE); + return $this->db->table(self::TABLE)->eq('id', $subtask_id)->remove(); } /** diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 428a8015..e32c0d43 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -26,12 +26,6 @@ class ClassProvider implements ServiceProviderInterface 'AverageLeadCycleTimeAnalytic', 'AverageTimeSpentColumnAnalytic', ), - 'Job' => array( - 'CommentEventJob', - 'TaskFileEventJob', - 'ProjectFileEventJob', - 'NotificationJob', - ), 'Model' => array( 'ActionModel', 'ActionParameterModel', diff --git a/app/ServiceProvider/JobProvider.php b/app/ServiceProvider/JobProvider.php new file mode 100644 index 00000000..bfea6e6e --- /dev/null +++ b/app/ServiceProvider/JobProvider.php @@ -0,0 +1,52 @@ +factory(function ($c) { + return new CommentEventJob($c); + }); + + $container['subtaskEventJob'] = $container->factory(function ($c) { + return new SubtaskEventJob($c); + }); + + $container['taskFileEventJob'] = $container->factory(function ($c) { + return new TaskFileEventJob($c); + }); + + $container['projectFileEventJob'] = $container->factory(function ($c) { + return new ProjectFileEventJob($c); + }); + + $container['notificationJob'] = $container->factory(function ($c) { + return new NotificationJob($c); + }); + + return $container; + } +} diff --git a/app/ServiceProvider/QueueProvider.php b/app/ServiceProvider/QueueProvider.php index 946b436a..570f2e77 100644 --- a/app/ServiceProvider/QueueProvider.php +++ b/app/ServiceProvider/QueueProvider.php @@ -15,9 +15,11 @@ use Pimple\ServiceProviderInterface; class QueueProvider implements ServiceProviderInterface { /** - * Registers services on the given container. + * Register providers * - * @param Container $container + * @access public + * @param \Pimple\Container $container + * @return \Pimple\Container */ public function register(Container $container) { diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php index 47222f73..0b3760c4 100644 --- a/app/Subscriber/NotificationSubscriber.php +++ b/app/Subscriber/NotificationSubscriber.php @@ -26,6 +26,7 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn TaskModel::EVENT_ASSIGNEE_CHANGE => 'handleEvent', SubtaskModel::EVENT_CREATE => 'handleEvent', SubtaskModel::EVENT_UPDATE => 'handleEvent', + SubtaskModel::EVENT_DELETE => 'handleEvent', CommentModel::EVENT_CREATE => 'handleEvent', CommentModel::EVENT_UPDATE => 'handleEvent', CommentModel::EVENT_REMOVE => 'handleEvent', diff --git a/app/Template/event/subtask_delete.php b/app/Template/event/subtask_delete.php new file mode 100644 index 00000000..8ac11853 --- /dev/null +++ b/app/Template/event/subtask_delete.php @@ -0,0 +1,15 @@ +

    + text->e($author), + $this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) + ) ?> + dt->datetime($date_creation) ?> +

    +
    +

    text->e($task['title']) ?>

    +
      +
    • + text->e($subtask['title']) ?> (text->e($subtask['status_name']) ?>) +
    • +
    +
    diff --git a/app/Template/notification/subtask_delete.php b/app/Template/notification/subtask_delete.php new file mode 100644 index 00000000..8c5f262c --- /dev/null +++ b/app/Template/notification/subtask_delete.php @@ -0,0 +1,11 @@ +

    text->e($task['title']) ?> (#)

    + +

    + +
      +
    • text->e($subtask['title']) ?>
    • +
    • text->e($subtask['status_name']) ?>
    • +
    • text->e($subtask['name'] ?: $subtask['username'] ?: '?') ?>
    • +
    + +render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> diff --git a/app/common.php b/app/common.php index 72be3603..15fd7a75 100644 --- a/app/common.php +++ b/app/common.php @@ -46,6 +46,7 @@ $container->register(new Kanboard\ServiceProvider\ActionProvider()); $container->register(new Kanboard\ServiceProvider\ExternalLinkProvider()); $container->register(new Kanboard\ServiceProvider\AvatarProvider()); $container->register(new Kanboard\ServiceProvider\FilterProvider()); +$container->register(new Kanboard\ServiceProvider\JobProvider()); $container->register(new Kanboard\ServiceProvider\QueueProvider()); $container->register(new Kanboard\ServiceProvider\ApiProvider()); $container->register(new Kanboard\ServiceProvider\CommandProvider()); diff --git a/tests/units/Base.php b/tests/units/Base.php index 9dbfb280..c471ee31 100644 --- a/tests/units/Base.php +++ b/tests/units/Base.php @@ -41,6 +41,7 @@ abstract class Base extends PHPUnit_Framework_TestCase $this->container->register(new Kanboard\ServiceProvider\RouteProvider()); $this->container->register(new Kanboard\ServiceProvider\AvatarProvider()); $this->container->register(new Kanboard\ServiceProvider\FilterProvider()); + $this->container->register(new Kanboard\ServiceProvider\JobProvider()); $this->container->register(new Kanboard\ServiceProvider\QueueProvider()); $this->container['dispatcher'] = new TraceableEventDispatcher( diff --git a/tests/units/EventBuilder/SubtaskEventBuilderTest.php b/tests/units/EventBuilder/SubtaskEventBuilderTest.php new file mode 100644 index 00000000..062bdfb4 --- /dev/null +++ b/tests/units/EventBuilder/SubtaskEventBuilderTest.php @@ -0,0 +1,62 @@ +container); + $subtaskEventBuilder->withSubtaskId(42); + $this->assertNull($subtaskEventBuilder->build()); + } + + public function testBuildWithoutChanges() + { + $subtaskModel = new SubtaskModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $subtaskEventBuilder = new SubtaskEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('task_id' => 1, 'title' => 'test'))); + + $event = $subtaskEventBuilder->withSubtaskId(1)->build(); + + $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); + $this->assertNotEmpty($event['subtask']); + $this->assertNotEmpty($event['task']); + $this->assertArrayNotHasKey('changes', $event); + } + + public function testBuildWithChanges() + { + $subtaskModel = new SubtaskModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $subtaskEventBuilder = new SubtaskEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('task_id' => 1, 'title' => 'test'))); + + $event = $subtaskEventBuilder + ->withSubtaskId(1) + ->withValues(array('title' => 'new title', 'user_id' => 1)) + ->build(); + + $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); + $this->assertNotEmpty($event['subtask']); + $this->assertNotEmpty($event['task']); + $this->assertNotEmpty($event['changes']); + $this->assertCount(2, $event['changes']); + $this->assertEquals('new title', $event['changes']['title']); + $this->assertEquals(1, $event['changes']['user_id']); + } +} diff --git a/tests/units/Job/SubtaskEventJobTest.php b/tests/units/Job/SubtaskEventJobTest.php new file mode 100644 index 00000000..265a8e2d --- /dev/null +++ b/tests/units/Job/SubtaskEventJobTest.php @@ -0,0 +1,52 @@ +container); + $subtaskEventJob->withParams(123, 'foobar', array('k' => 'v')); + + $this->assertSame(array(123, 'foobar', array('k' => 'v')), $subtaskEventJob->getJobParams()); + } + + public function testWithMissingSubtask() + { + $this->container['dispatcher']->addListener(SubtaskModel::EVENT_CREATE, function() {}); + + $SubtaskEventJob = new SubtaskEventJob($this->container); + $SubtaskEventJob->execute(42, SubtaskModel::EVENT_CREATE); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertEmpty($called); + } + + public function testTriggerEvents() + { + $this->container['dispatcher']->addListener(SubtaskModel::EVENT_CREATE, function() {}); + $this->container['dispatcher']->addListener(SubtaskModel::EVENT_UPDATE, function() {}); + $this->container['dispatcher']->addListener(SubtaskModel::EVENT_DELETE, function() {}); + + $subtaskModel = new SubtaskModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('task_id' => 1, 'title' => 'before'))); + $this->assertTrue($subtaskModel->update(array('id' => 1, 'title' => 'after'))); + $this->assertTrue($subtaskModel->remove(1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(SubtaskModel::EVENT_CREATE.'.closure', $called); + $this->assertArrayHasKey(SubtaskModel::EVENT_UPDATE.'.closure', $called); + $this->assertArrayHasKey(SubtaskModel::EVENT_DELETE.'.closure', $called); + } +} diff --git a/tests/units/Model/SubtaskModelTest.php b/tests/units/Model/SubtaskModelTest.php index 6451189d..7e438651 100644 --- a/tests/units/Model/SubtaskModelTest.php +++ b/tests/units/Model/SubtaskModelTest.php @@ -9,64 +9,6 @@ use Kanboard\Model\TaskFinderModel; class SubtaskModelTest extends Base { - public function onSubtaskCreated($event) - { - $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); - $data = $event->getAll(); - - $this->assertArrayHasKey('id', $data); - $this->assertArrayHasKey('title', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('time_estimated', $data); - $this->assertArrayHasKey('time_spent', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('task_id', $data); - $this->assertArrayHasKey('user_id', $data); - $this->assertArrayHasKey('position', $data); - $this->assertNotEmpty($data['task_id']); - $this->assertNotEmpty($data['id']); - } - - public function onSubtaskUpdated($event) - { - $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); - $data = $event->getAll(); - - $this->assertArrayHasKey('id', $data); - $this->assertArrayHasKey('title', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('time_estimated', $data); - $this->assertArrayHasKey('time_spent', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('task_id', $data); - $this->assertArrayHasKey('user_id', $data); - $this->assertArrayHasKey('position', $data); - $this->assertArrayHasKey('changes', $data); - $this->assertArrayHasKey('user_id', $data['changes']); - $this->assertArrayHasKey('status', $data['changes']); - - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $data['changes']['status']); - $this->assertEquals(1, $data['changes']['user_id']); - } - - public function onSubtaskDeleted($event) - { - $this->assertInstanceOf('Kanboard\Event\SubtaskEvent', $event); - $data = $event->getAll(); - - $this->assertArrayHasKey('id', $data); - $this->assertArrayHasKey('title', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('time_estimated', $data); - $this->assertArrayHasKey('time_spent', $data); - $this->assertArrayHasKey('status', $data); - $this->assertArrayHasKey('task_id', $data); - $this->assertArrayHasKey('user_id', $data); - $this->assertArrayHasKey('position', $data); - $this->assertNotEmpty($data['task_id']); - $this->assertNotEmpty($data['id']); - } - public function testCreation() { $taskCreationModel = new TaskCreationModel($this->container); @@ -75,9 +17,6 @@ class SubtaskModelTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->container['dispatcher']->addListener(SubtaskModel::EVENT_CREATE, array($this, 'onSubtaskCreated')); - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); $subtask = $subtaskModel->getById(1); @@ -101,8 +40,6 @@ class SubtaskModelTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - $this->container['dispatcher']->addListener(SubtaskModel::EVENT_UPDATE, array($this, 'onSubtaskUpdated')); - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); $this->assertTrue($subtaskModel->update(array('id' => 1, 'user_id' => 1, 'status' => SubtaskModel::STATUS_INPROGRESS))); @@ -128,8 +65,6 @@ class SubtaskModelTest extends Base $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); - $this->container['dispatcher']->addListener(SubtaskModel::EVENT_DELETE, array($this, 'onSubtaskDeleted')); - $subtask = $subtaskModel->getById(1); $this->assertNotEmpty($subtask); @@ -269,7 +204,6 @@ class SubtaskModelTest extends Base $this->assertTrue($subtaskModel->duplicate(1, 2)); $subtasks = $subtaskModel->getAll(2); - $this->assertNotFalse($subtasks); $this->assertNotEmpty($subtasks); $this->assertEquals(2, count($subtasks)); @@ -383,7 +317,7 @@ class SubtaskModelTest extends Base $this->assertEquals(2, $task['time_spent']); $this->assertEquals(3, $task['time_estimated']); } - + public function testGetProjectId() { $taskCreationModel = new TaskCreationModel($this->container); @@ -393,7 +327,7 @@ class SubtaskModelTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); - + $this->assertEquals(1, $subtaskModel->getProjectId(1)); $this->assertEquals(0, $subtaskModel->getProjectId(2)); } -- cgit v1.2.3 From 390082aa41cb81610089163b1cc3a256f3b3c513 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Tue, 19 Jul 2016 22:38:30 -0400 Subject: Refactoring of internal task events --- app/Action/Base.php | 13 +- app/Action/CommentCreationMoveTaskColumn.php | 12 +- app/Action/TaskAssignCategoryColor.php | 7 +- app/Action/TaskAssignColorCategory.php | 7 +- app/Action/TaskAssignColorColumn.php | 7 +- app/Action/TaskAssignColorPriority.php | 7 +- app/Action/TaskAssignColorUser.php | 7 +- app/Action/TaskAssignCurrentUserColumn.php | 7 +- app/Action/TaskAssignSpecificUser.php | 7 +- app/Action/TaskCloseColumn.php | 10 +- app/Action/TaskCreation.php | 1 + app/Action/TaskDuplicateAnotherProject.php | 14 +- app/Action/TaskEmail.php | 14 +- app/Action/TaskMoveAnotherProject.php | 8 +- app/Action/TaskMoveColumnAssigned.php | 19 +- app/Action/TaskMoveColumnCategoryChange.php | 19 +- app/Action/TaskMoveColumnUnAssigned.php | 19 +- app/Action/TaskUpdateStartDate.php | 7 +- app/Core/Base.php | 1 + app/EventBuilder/TaskEventBuilder.php | 123 ++++ app/Job/NotificationJob.php | 50 +- app/Job/TaskEventJob.php | 75 +++ app/Model/SubtaskModel.php | 1 - app/Model/TaskCreationModel.php | 32 +- app/Model/TaskModificationModel.php | 62 +- app/Model/TaskPositionModel.php | 28 +- app/Model/TaskProjectMoveModel.php | 7 +- app/Model/TaskStatusModel.php | 8 +- app/ServiceProvider/JobProvider.php | 5 + app/Subscriber/NotificationSubscriber.php | 6 +- .../ProjectModificationDateSubscriber.php | 6 +- tests/units/Action/BaseActionTest.php | 10 +- .../Action/CommentCreationMoveTaskColumnTest.php | 6 +- tests/units/Action/TaskAssignCategoryColorTest.php | 18 +- tests/units/Action/TaskAssignCategoryLinkTest.php | 43 +- tests/units/Action/TaskAssignColorCategoryTest.php | 18 +- tests/units/Action/TaskAssignColorColumnTest.php | 18 +- tests/units/Action/TaskAssignColorPriorityTest.php | 18 +- tests/units/Action/TaskAssignColorUserTest.php | 18 +- .../Action/TaskAssignCurrentUserColumnTest.php | 26 +- tests/units/Action/TaskAssignSpecificUserTest.php | 17 +- tests/units/Action/TaskCloseColumnTest.php | 18 +- tests/units/Action/TaskCloseTest.php | 15 +- .../Action/TaskDuplicateAnotherProjectTest.php | 18 +- tests/units/Action/TaskEmailTest.php | 19 +- tests/units/Action/TaskMoveAnotherProjectTest.php | 17 +- tests/units/Action/TaskMoveColumnAssignedTest.php | 18 +- .../Action/TaskMoveColumnCategoryChangeTest.php | 31 +- .../units/Action/TaskMoveColumnUnAssignedTest.php | 31 +- tests/units/Action/TaskOpenTest.php | 15 +- tests/units/Action/TaskUpdateStartDateTest.php | 17 +- tests/units/EventBuilder/TaskEventBuilderTest.php | 100 ++++ tests/units/Job/SubtaskEventJobTest.php | 4 +- tests/units/Job/TaskEventJobTest.php | 189 ++++++ tests/units/Model/TaskCreationModelTest.php | 2 +- tests/units/Model/TaskModificationModelTest.php | 13 +- tests/units/Model/TaskPositionModelTest.php | 631 +++++++++++++++++++++ tests/units/Model/TaskPositionTest.php | 631 --------------------- tests/units/Model/TaskProjectMoveModelTest.php | 2 +- 59 files changed, 1647 insertions(+), 905 deletions(-) create mode 100644 app/EventBuilder/TaskEventBuilder.php create mode 100644 app/Job/TaskEventJob.php create mode 100644 tests/units/EventBuilder/TaskEventBuilderTest.php create mode 100644 tests/units/Job/TaskEventJobTest.php create mode 100644 tests/units/Model/TaskPositionModelTest.php delete mode 100644 tests/units/Model/TaskPositionTest.php (limited to 'app/Core') diff --git a/app/Action/Base.php b/app/Action/Base.php index e5c65a17..e0ed8bde 100644 --- a/app/Action/Base.php +++ b/app/Action/Base.php @@ -216,7 +216,8 @@ abstract class Base extends \Kanboard\Core\Base */ public function hasRequiredProject(array $data) { - return isset($data['project_id']) && $data['project_id'] == $this->getProjectId(); + return (isset($data['project_id']) && $data['project_id'] == $this->getProjectId()) || + (isset($data['task']['project_id']) && $data['task']['project_id'] == $this->getProjectId()); } /** @@ -226,10 +227,14 @@ abstract class Base extends \Kanboard\Core\Base * @param array $data Event data dictionary * @return bool True if all keys are there */ - public function hasRequiredParameters(array $data) + public function hasRequiredParameters(array $data, array $parameters = array()) { - foreach ($this->getEventRequiredParameters() as $parameter) { - if (! isset($data[$parameter])) { + $parameters = $parameters ?: $this->getEventRequiredParameters(); + + foreach ($parameters as $key => $value) { + if (is_array($value)) { + return isset($data[$key]) && $this->hasRequiredParameters($data[$key], $value); + } else if (! isset($data[$value])) { return false; } } diff --git a/app/Action/CommentCreationMoveTaskColumn.php b/app/Action/CommentCreationMoveTaskColumn.php index 1b16f481..8ab792ad 100644 --- a/app/Action/CommentCreationMoveTaskColumn.php +++ b/app/Action/CommentCreationMoveTaskColumn.php @@ -55,7 +55,13 @@ class CommentCreationMoveTaskColumn extends Base */ public function getEventRequiredParameters() { - return array('task_id', 'column_id'); + return array( + 'task_id', + 'task' => array( + 'column_id', + 'project_id', + ), + ); } /** @@ -71,7 +77,7 @@ class CommentCreationMoveTaskColumn extends Base return false; } - $column = $this->columnModel->getById($data['column_id']); + $column = $this->columnModel->getById($data['task']['column_id']); return (bool) $this->commentModel->create(array( 'comment' => t('Moved to column %s', $column['title']), @@ -89,6 +95,6 @@ class CommentCreationMoveTaskColumn extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Action/TaskAssignCategoryColor.php b/app/Action/TaskAssignCategoryColor.php index fc486870..2df90b2c 100644 --- a/app/Action/TaskAssignCategoryColor.php +++ b/app/Action/TaskAssignCategoryColor.php @@ -60,7 +60,10 @@ class TaskAssignCategoryColor extends Base { return array( 'task_id', - 'color_id', + 'task' => array( + 'project_id', + 'color_id', + ), ); } @@ -90,6 +93,6 @@ class TaskAssignCategoryColor extends Base */ public function hasRequiredCondition(array $data) { - return $data['color_id'] == $this->getParam('color_id'); + return $data['task']['color_id'] == $this->getParam('color_id'); } } diff --git a/app/Action/TaskAssignColorCategory.php b/app/Action/TaskAssignColorCategory.php index 284b8f40..91860be4 100644 --- a/app/Action/TaskAssignColorCategory.php +++ b/app/Action/TaskAssignColorCategory.php @@ -60,7 +60,10 @@ class TaskAssignColorCategory extends Base { return array( 'task_id', - 'category_id', + 'task' => array( + 'project_id', + 'category_id', + ), ); } @@ -90,6 +93,6 @@ class TaskAssignColorCategory extends Base */ public function hasRequiredCondition(array $data) { - return $data['category_id'] == $this->getParam('category_id'); + return $data['task']['category_id'] == $this->getParam('category_id'); } } diff --git a/app/Action/TaskAssignColorColumn.php b/app/Action/TaskAssignColorColumn.php index 57fd6f44..6c674b1f 100644 --- a/app/Action/TaskAssignColorColumn.php +++ b/app/Action/TaskAssignColorColumn.php @@ -61,7 +61,10 @@ class TaskAssignColorColumn extends Base { return array( 'task_id', - 'column_id', + 'task' => array( + 'project_id', + 'column_id', + ), ); } @@ -91,6 +94,6 @@ class TaskAssignColorColumn extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Action/TaskAssignColorPriority.php b/app/Action/TaskAssignColorPriority.php index eae1b771..57000ba8 100644 --- a/app/Action/TaskAssignColorPriority.php +++ b/app/Action/TaskAssignColorPriority.php @@ -60,7 +60,10 @@ class TaskAssignColorPriority extends Base { return array( 'task_id', - 'priority', + 'task' => array( + 'project_id', + 'priority', + ), ); } @@ -90,6 +93,6 @@ class TaskAssignColorPriority extends Base */ public function hasRequiredCondition(array $data) { - return $data['priority'] == $this->getParam('priority'); + return $data['task']['priority'] == $this->getParam('priority'); } } diff --git a/app/Action/TaskAssignColorUser.php b/app/Action/TaskAssignColorUser.php index 4bcf7a5c..385db793 100644 --- a/app/Action/TaskAssignColorUser.php +++ b/app/Action/TaskAssignColorUser.php @@ -61,7 +61,10 @@ class TaskAssignColorUser extends Base { return array( 'task_id', - 'owner_id', + 'task' => array( + 'project_id', + 'owner_id', + ), ); } @@ -91,6 +94,6 @@ class TaskAssignColorUser extends Base */ public function hasRequiredCondition(array $data) { - return $data['owner_id'] == $this->getParam('user_id'); + return $data['task']['owner_id'] == $this->getParam('user_id'); } } diff --git a/app/Action/TaskAssignCurrentUserColumn.php b/app/Action/TaskAssignCurrentUserColumn.php index bc28a90b..e4eade33 100644 --- a/app/Action/TaskAssignCurrentUserColumn.php +++ b/app/Action/TaskAssignCurrentUserColumn.php @@ -59,7 +59,10 @@ class TaskAssignCurrentUserColumn extends Base { return array( 'task_id', - 'column_id', + 'task' => array( + 'project_id', + 'column_id', + ), ); } @@ -93,6 +96,6 @@ class TaskAssignCurrentUserColumn extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Action/TaskAssignSpecificUser.php b/app/Action/TaskAssignSpecificUser.php index 50a2b2ae..2c7dcacd 100644 --- a/app/Action/TaskAssignSpecificUser.php +++ b/app/Action/TaskAssignSpecificUser.php @@ -61,7 +61,10 @@ class TaskAssignSpecificUser extends Base { return array( 'task_id', - 'column_id', + 'task' => array( + 'project_id', + 'column_id', + ), ); } @@ -91,6 +94,6 @@ class TaskAssignSpecificUser extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Action/TaskCloseColumn.php b/app/Action/TaskCloseColumn.php index 1edce8fa..4f1ffc92 100644 --- a/app/Action/TaskCloseColumn.php +++ b/app/Action/TaskCloseColumn.php @@ -55,7 +55,13 @@ class TaskCloseColumn extends Base */ public function getEventRequiredParameters() { - return array('task_id', 'column_id'); + return array( + 'task_id', + 'task' => array( + 'project_id', + 'column_id', + ) + ); } /** @@ -79,6 +85,6 @@ class TaskCloseColumn extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Action/TaskCreation.php b/app/Action/TaskCreation.php index e9e5c5f3..0620afd3 100644 --- a/app/Action/TaskCreation.php +++ b/app/Action/TaskCreation.php @@ -52,6 +52,7 @@ class TaskCreation extends Base public function getEventRequiredParameters() { return array( + 'project_id', 'reference', 'title', ); diff --git a/app/Action/TaskDuplicateAnotherProject.php b/app/Action/TaskDuplicateAnotherProject.php index d70d2ee8..d6d8d51f 100644 --- a/app/Action/TaskDuplicateAnotherProject.php +++ b/app/Action/TaskDuplicateAnotherProject.php @@ -62,7 +62,10 @@ class TaskDuplicateAnotherProject extends Base { return array( 'task_id', - 'column_id', + 'task' => array( + 'project_id', + 'column_id', + ) ); } @@ -76,7 +79,12 @@ class TaskDuplicateAnotherProject extends Base public function doAction(array $data) { $destination_column_id = $this->columnModel->getFirstColumnId($this->getParam('project_id')); - return (bool) $this->taskProjectDuplicationModel->duplicateToProject($data['task_id'], $this->getParam('project_id'), null, $destination_column_id); + return (bool) $this->taskProjectDuplicationModel->duplicateToProject( + $data['task_id'], + $this->getParam('project_id'), + null, + $destination_column_id + ); } /** @@ -88,6 +96,6 @@ class TaskDuplicateAnotherProject extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id') && $data['project_id'] != $this->getParam('project_id'); + return $data['task']['column_id'] == $this->getParam('column_id') && $data['task']['project_id'] != $this->getParam('project_id'); } } diff --git a/app/Action/TaskEmail.php b/app/Action/TaskEmail.php index 7f9ba416..526e9aa8 100644 --- a/app/Action/TaskEmail.php +++ b/app/Action/TaskEmail.php @@ -62,7 +62,10 @@ class TaskEmail extends Base { return array( 'task_id', - 'column_id', + 'task' => array( + 'project_id', + 'column_id', + ), ); } @@ -78,13 +81,14 @@ class TaskEmail extends Base $user = $this->userModel->getById($this->getParam('user_id')); if (! empty($user['email'])) { - $task = $this->taskFinderModel->getDetails($data['task_id']); - $this->emailClient->send( $user['email'], $user['name'] ?: $user['username'], $this->getParam('subject'), - $this->template->render('notification/task_create', array('task' => $task, 'application_url' => $this->configModel->get('application_url'))) + $this->template->render('notification/task_create', array( + 'task' => $data['task'], + 'application_url' => $this->configModel->get('application_url'), + )) ); return true; @@ -102,6 +106,6 @@ class TaskEmail extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Action/TaskMoveAnotherProject.php b/app/Action/TaskMoveAnotherProject.php index 66635a63..148b6b0c 100644 --- a/app/Action/TaskMoveAnotherProject.php +++ b/app/Action/TaskMoveAnotherProject.php @@ -61,8 +61,10 @@ class TaskMoveAnotherProject extends Base { return array( 'task_id', - 'column_id', - 'project_id', + 'task' => array( + 'project_id', + 'column_id', + ) ); } @@ -87,6 +89,6 @@ class TaskMoveAnotherProject extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id') && $data['project_id'] != $this->getParam('project_id'); + return $data['task']['column_id'] == $this->getParam('column_id') && $data['task']['project_id'] != $this->getParam('project_id'); } } diff --git a/app/Action/TaskMoveColumnAssigned.php b/app/Action/TaskMoveColumnAssigned.php index 7e3db9c5..1c1f657a 100644 --- a/app/Action/TaskMoveColumnAssigned.php +++ b/app/Action/TaskMoveColumnAssigned.php @@ -61,8 +61,13 @@ class TaskMoveColumnAssigned extends Base { return array( 'task_id', - 'column_id', - 'owner_id' + 'task' => array( + 'project_id', + 'column_id', + 'owner_id', + 'position', + 'swimlane_id', + ) ); } @@ -75,14 +80,12 @@ class TaskMoveColumnAssigned extends Base */ public function doAction(array $data) { - $original_task = $this->taskFinderModel->getById($data['task_id']); - return $this->taskPositionModel->movePosition( - $data['project_id'], + $data['task']['project_id'], $data['task_id'], $this->getParam('dest_column_id'), - $original_task['position'], - $original_task['swimlane_id'], + $data['task']['position'], + $data['task']['swimlane_id'], false ); } @@ -96,6 +99,6 @@ class TaskMoveColumnAssigned extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('src_column_id') && $data['owner_id'] > 0; + return $data['task']['column_id'] == $this->getParam('src_column_id') && $data['task']['owner_id'] > 0; } } diff --git a/app/Action/TaskMoveColumnCategoryChange.php b/app/Action/TaskMoveColumnCategoryChange.php index e4f88760..4c2b289a 100644 --- a/app/Action/TaskMoveColumnCategoryChange.php +++ b/app/Action/TaskMoveColumnCategoryChange.php @@ -60,8 +60,13 @@ class TaskMoveColumnCategoryChange extends Base { return array( 'task_id', - 'column_id', - 'category_id', + 'task' => array( + 'project_id', + 'column_id', + 'category_id', + 'position', + 'swimlane_id', + ) ); } @@ -74,14 +79,12 @@ class TaskMoveColumnCategoryChange extends Base */ public function doAction(array $data) { - $original_task = $this->taskFinderModel->getById($data['task_id']); - return $this->taskPositionModel->movePosition( - $data['project_id'], + $data['task']['project_id'], $data['task_id'], $this->getParam('dest_column_id'), - $original_task['position'], - $original_task['swimlane_id'], + $data['task']['position'], + $data['task']['swimlane_id'], false ); } @@ -95,6 +98,6 @@ class TaskMoveColumnCategoryChange extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] != $this->getParam('dest_column_id') && $data['category_id'] == $this->getParam('category_id'); + return $data['task']['column_id'] != $this->getParam('dest_column_id') && $data['task']['category_id'] == $this->getParam('category_id'); } } diff --git a/app/Action/TaskMoveColumnUnAssigned.php b/app/Action/TaskMoveColumnUnAssigned.php index c3ae9e1d..0e9a8a16 100644 --- a/app/Action/TaskMoveColumnUnAssigned.php +++ b/app/Action/TaskMoveColumnUnAssigned.php @@ -61,8 +61,13 @@ class TaskMoveColumnUnAssigned extends Base { return array( 'task_id', - 'column_id', - 'owner_id' + 'task' => array( + 'project_id', + 'column_id', + 'owner_id', + 'position', + 'swimlane_id', + ) ); } @@ -75,14 +80,12 @@ class TaskMoveColumnUnAssigned extends Base */ public function doAction(array $data) { - $original_task = $this->taskFinderModel->getById($data['task_id']); - return $this->taskPositionModel->movePosition( - $data['project_id'], + $data['task']['project_id'], $data['task_id'], $this->getParam('dest_column_id'), - $original_task['position'], - $original_task['swimlane_id'], + $data['task']['position'], + $data['task']['swimlane_id'], false ); } @@ -96,6 +99,6 @@ class TaskMoveColumnUnAssigned extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('src_column_id') && $data['owner_id'] == 0; + return $data['task']['column_id'] == $this->getParam('src_column_id') && $data['task']['owner_id'] == 0; } } diff --git a/app/Action/TaskUpdateStartDate.php b/app/Action/TaskUpdateStartDate.php index e5410a87..cc016da1 100644 --- a/app/Action/TaskUpdateStartDate.php +++ b/app/Action/TaskUpdateStartDate.php @@ -59,7 +59,10 @@ class TaskUpdateStartDate extends Base { return array( 'task_id', - 'column_id', + 'task' => array( + 'project_id', + 'column_id', + ), ); } @@ -89,6 +92,6 @@ class TaskUpdateStartDate extends Base */ public function hasRequiredCondition(array $data) { - return $data['column_id'] == $this->getParam('column_id'); + return $data['task']['column_id'] == $this->getParam('column_id'); } } diff --git a/app/Core/Base.php b/app/Core/Base.php index 6650680b..098bd880 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -152,6 +152,7 @@ use Pimple\Container; * @property \Kanboard\Core\Filter\LexerBuilder $projectActivityLexer * @property \Kanboard\Job\CommentEventJob $commentEventJob * @property \Kanboard\Job\SubtaskEventJob $subtaskEventJob + * @property \Kanboard\Job\TaskEventJob $taskEventJob * @property \Kanboard\Job\TaskFileEventJob $taskFileEventJob * @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob * @property \Kanboard\Job\NotificationJob $notificationJob diff --git a/app/EventBuilder/TaskEventBuilder.php b/app/EventBuilder/TaskEventBuilder.php new file mode 100644 index 00000000..e7a5653d --- /dev/null +++ b/app/EventBuilder/TaskEventBuilder.php @@ -0,0 +1,123 @@ +taskId = $taskId; + return $this; + } + + /** + * Set task + * + * @param array $task + * @return $this + */ + public function withTask(array $task) + { + $this->task = $task; + return $this; + } + + /** + * Set values + * + * @param array $values + * @return $this + */ + public function withValues(array $values) + { + $this->values = $values; + return $this; + } + + /** + * Set changes + * + * @param array $changes + * @return $this + */ + public function withChanges(array $changes) + { + $this->changes = $changes; + return $this; + } + + /** + * Build event data + * + * @access public + * @return TaskEvent|null + */ + public function build() + { + $eventData = array(); + $eventData['task_id'] = $this->taskId; + $eventData['task'] = $this->taskFinderModel->getDetails($this->taskId); + + if (empty($eventData['task'])) { + $this->logger->debug(__METHOD__.': Task not found'); + return null; + } + + if (! empty($this->changes)) { + if (empty($this->task)) { + $this->task = $eventData['task']; + } + + $eventData['changes'] = array_diff_assoc($this->changes, $this->task); + unset($eventData['changes']['date_modification']); + } + + return new TaskEvent(array_merge($eventData, $this->values)); + } +} diff --git a/app/Job/NotificationJob.php b/app/Job/NotificationJob.php index 5a52eb31..8fb260e8 100644 --- a/app/Job/NotificationJob.php +++ b/app/Job/NotificationJob.php @@ -17,59 +17,27 @@ class NotificationJob extends BaseJob * * @param GenericEvent $event * @param string $eventName - * @param string $eventObjectName * @return $this */ - public function withParams(GenericEvent $event, $eventName, $eventObjectName) + public function withParams(GenericEvent $event, $eventName) { - $this->jobParams = array($event->getAll(), $eventName, $eventObjectName); + $this->jobParams = array($event->getAll(), $eventName); return $this; } /** * Execute job * - * @param array $event + * @param array $eventData * @param string $eventName - * @param string $eventObjectName */ - public function execute(array $event, $eventName, $eventObjectName) + public function execute(array $eventData, $eventName) { - $eventData = $this->getEventData($event, $eventObjectName); - - if (! empty($eventData)) { - if (! empty($event['mention'])) { - $this->userNotificationModel->sendUserNotification($event['mention'], $eventName, $eventData); - } else { - $this->userNotificationModel->sendNotifications($eventName, $eventData); - $this->projectNotificationModel->sendNotifications($eventData['task']['project_id'], $eventName, $eventData); - } - } - } - - /** - * Get event data - * - * @param array $event - * @param string $eventObjectName - * @return array - */ - public function getEventData(array $event, $eventObjectName) - { - $values = array(); - - if (! empty($event['changes'])) { - $values['changes'] = $event['changes']; + if (! empty($eventData['mention'])) { + $this->userNotificationModel->sendUserNotification($eventData['mention'], $eventName, $eventData); + } else { + $this->userNotificationModel->sendNotifications($eventName, $eventData); + $this->projectNotificationModel->sendNotifications($eventData['task']['project_id'], $eventName, $eventData); } - - switch ($eventObjectName) { - case 'Kanboard\Event\TaskEvent': - $values['task'] = $this->taskFinderModel->getDetails($event['task_id']); - break; - default: - $values = $event; - } - - return $values; } } diff --git a/app/Job/TaskEventJob.php b/app/Job/TaskEventJob.php new file mode 100644 index 00000000..46f7a16c --- /dev/null +++ b/app/Job/TaskEventJob.php @@ -0,0 +1,75 @@ +jobParams = array($taskId, $eventNames, $changes, $values, $task); + return $this; + } + + /** + * Execute job + * + * @param int $taskId + * @param array $eventNames + * @param array $changes + * @param array $values + * @param array $task + * @return $this + */ + public function execute($taskId, array $eventNames, array $changes = array(), array $values = array(), array $task = array()) + { + $event = TaskEventBuilder::getInstance($this->container) + ->withTaskId($taskId) + ->withChanges($changes) + ->withValues($values) + ->withTask($task) + ->build(); + + if ($event !== null) { + foreach ($eventNames as $eventName) { + $this->fireEvent($eventName, $event); + } + } + } + + /** + * Trigger event + * + * @access protected + * @param string $eventName + * @param TaskEvent $event + */ + protected function fireEvent($eventName, TaskEvent $event) + { + $this->logger->debug(__METHOD__.' Event fired: '.$eventName); + $this->dispatcher->dispatch($eventName, $event); + + if ($eventName === TaskModel::EVENT_CREATE) { + $this->userMentionModel->fireEvents($event['task']['description'], TaskModel::EVENT_USER_MENTION, $event); + } + } +} diff --git a/app/Model/SubtaskModel.php b/app/Model/SubtaskModel.php index 6dd1f26a..f3fc72ba 100644 --- a/app/Model/SubtaskModel.php +++ b/app/Model/SubtaskModel.php @@ -4,7 +4,6 @@ namespace Kanboard\Model; use PicoDb\Database; use Kanboard\Core\Base; -use Kanboard\Event\SubtaskEvent; /** * Subtask Model diff --git a/app/Model/TaskCreationModel.php b/app/Model/TaskCreationModel.php index cd70a028..1c0fd7d9 100644 --- a/app/Model/TaskCreationModel.php +++ b/app/Model/TaskCreationModel.php @@ -3,7 +3,6 @@ namespace Kanboard\Model; use Kanboard\Core\Base; -use Kanboard\Event\TaskEvent; /** * Task Creation @@ -42,7 +41,10 @@ class TaskCreationModel extends Base $this->taskTagModel->save($values['project_id'], $task_id, $tags); } - $this->fireEvents($task_id, $values); + $this->queueManager->push($this->taskEventJob->withParams( + $task_id, + array(TaskModel::EVENT_CREATE_UPDATE, TaskModel::EVENT_CREATE) + )); } return (int) $task_id; @@ -51,10 +53,10 @@ class TaskCreationModel extends Base /** * Prepare data * - * @access public + * @access protected * @param array $values Form values */ - public function prepare(array &$values) + protected function prepare(array &$values) { $values = $this->dateParser->convert($values, array('date_due')); $values = $this->dateParser->convert($values, array('date_started'), true); @@ -84,26 +86,4 @@ class TaskCreationModel extends Base $values['date_moved'] = $values['date_creation']; $values['position'] = $this->taskFinderModel->countByColumnAndSwimlaneId($values['project_id'], $values['column_id'], $values['swimlane_id']) + 1; } - - /** - * Fire events - * - * @access private - * @param integer $task_id Task id - * @param array $values Form values - */ - private function fireEvents($task_id, array $values) - { - $event = new TaskEvent(array('task_id' => $task_id) + $values); - - $this->logger->debug('Event fired: '.TaskModel::EVENT_CREATE_UPDATE); - $this->logger->debug('Event fired: '.TaskModel::EVENT_CREATE); - - $this->dispatcher->dispatch(TaskModel::EVENT_CREATE_UPDATE, $event); - $this->dispatcher->dispatch(TaskModel::EVENT_CREATE, $event); - - if (! empty($values['description'])) { - $this->userMentionModel->fireEvents($values['description'], TaskModel::EVENT_USER_MENTION, $event); - } - } } diff --git a/app/Model/TaskModificationModel.php b/app/Model/TaskModificationModel.php index be5f53c8..16b48f3d 100644 --- a/app/Model/TaskModificationModel.php +++ b/app/Model/TaskModificationModel.php @@ -3,7 +3,6 @@ namespace Kanboard\Model; use Kanboard\Core\Base; -use Kanboard\Event\TaskEvent; /** * Task Modification @@ -23,14 +22,14 @@ class TaskModificationModel extends Base */ public function update(array $values, $fire_events = true) { - $original_task = $this->taskFinderModel->getById($values['id']); + $task = $this->taskFinderModel->getById($values['id']); - $this->updateTags($values, $original_task); + $this->updateTags($values, $task); $this->prepare($values); - $result = $this->db->table(TaskModel::TABLE)->eq('id', $original_task['id'])->update($values); + $result = $this->db->table(TaskModel::TABLE)->eq('id', $task['id'])->update($values); if ($fire_events && $result) { - $this->fireEvents($original_task, $values); + $this->fireEvents($task, $values); } return $result; @@ -39,43 +38,56 @@ class TaskModificationModel extends Base /** * Fire events * - * @access public - * @param array $task - * @param array $new_values + * @access protected + * @param array $task + * @param array $changes */ - public function fireEvents(array $task, array $new_values) + protected function fireEvents(array $task, array $changes) { $events = array(); - $event_data = array_merge($task, $new_values, array('task_id' => $task['id'])); - // Values changed - $event_data['changes'] = array_diff_assoc($new_values, $task); - unset($event_data['changes']['date_modification']); - - if ($this->isFieldModified('owner_id', $event_data['changes'])) { + if ($this->isAssigneeChanged($task, $changes)) { $events[] = TaskModel::EVENT_ASSIGNEE_CHANGE; - } elseif (! empty($event_data['changes'])) { + } elseif ($this->isModified($task, $changes)) { $events[] = TaskModel::EVENT_CREATE_UPDATE; $events[] = TaskModel::EVENT_UPDATE; } - foreach ($events as $event) { - $this->logger->debug('Event fired: '.$event); - $this->dispatcher->dispatch($event, new TaskEvent($event_data)); + if (! empty($events)) { + $this->queueManager->push($this->taskEventJob + ->withParams($task['id'], $events, $changes, array(), $task) + ); } } + /** + * Return true if the task have been modified + * + * @access protected + * @param array $task + * @param array $changes + * @return bool + */ + protected function isModified(array $task, array $changes) + { + $diff = array_diff_assoc($changes, $task); + unset($diff['date_modification']); + return count($diff) > 0; + } + /** * Return true if the field is the only modified value * - * @access public - * @param string $field - * @param array $changes - * @return boolean + * @access protected + * @param array $task + * @param array $changes + * @return bool */ - public function isFieldModified($field, array $changes) + protected function isAssigneeChanged(array $task, array $changes) { - return isset($changes[$field]) && count($changes) === 1; + $diff = array_diff_assoc($changes, $task); + unset($diff['date_modification']); + return isset($changes['owner_id']) && $task['owner_id'] != $changes['owner_id'] && count($diff) === 1; } /** diff --git a/app/Model/TaskPositionModel.php b/app/Model/TaskPositionModel.php index 9fdb8f7d..d6d2a0af 100644 --- a/app/Model/TaskPositionModel.php +++ b/app/Model/TaskPositionModel.php @@ -3,7 +3,6 @@ namespace Kanboard\Model; use Kanboard\Core\Base; -use Kanboard\Event\TaskEvent; /** * Task Position @@ -212,8 +211,7 @@ class TaskPositionModel extends Base */ private function fireEvents(array $task, $new_column_id, $new_position, $new_swimlane_id) { - $event_data = array( - 'task_id' => $task['id'], + $changes = array( 'project_id' => $task['project_id'], 'position' => $new_position, 'column_id' => $new_column_id, @@ -226,14 +224,26 @@ class TaskPositionModel extends Base ); if ($task['swimlane_id'] != $new_swimlane_id) { - $this->logger->debug('Event fired: '.TaskModel::EVENT_MOVE_SWIMLANE); - $this->dispatcher->dispatch(TaskModel::EVENT_MOVE_SWIMLANE, new TaskEvent($event_data)); + $this->queueManager->push($this->taskEventJob->withParams( + $task['id'], + array(TaskModel::EVENT_MOVE_SWIMLANE), + $changes, + $changes + )); } elseif ($task['column_id'] != $new_column_id) { - $this->logger->debug('Event fired: '.TaskModel::EVENT_MOVE_COLUMN); - $this->dispatcher->dispatch(TaskModel::EVENT_MOVE_COLUMN, new TaskEvent($event_data)); + $this->queueManager->push($this->taskEventJob->withParams( + $task['id'], + array(TaskModel::EVENT_MOVE_COLUMN), + $changes, + $changes + )); } elseif ($task['position'] != $new_position) { - $this->logger->debug('Event fired: '.TaskModel::EVENT_MOVE_POSITION); - $this->dispatcher->dispatch(TaskModel::EVENT_MOVE_POSITION, new TaskEvent($event_data)); + $this->queueManager->push($this->taskEventJob->withParams( + $task['id'], + array(TaskModel::EVENT_MOVE_POSITION), + $changes, + $changes + )); } } } diff --git a/app/Model/TaskProjectMoveModel.php b/app/Model/TaskProjectMoveModel.php index eda23c0b..ae3ae084 100644 --- a/app/Model/TaskProjectMoveModel.php +++ b/app/Model/TaskProjectMoveModel.php @@ -2,8 +2,6 @@ namespace Kanboard\Model; -use Kanboard\Event\TaskEvent; - /** * Task Project Move * @@ -32,9 +30,8 @@ class TaskProjectMoveModel extends TaskDuplicationModel $this->checkDestinationProjectValues($values); $this->tagDuplicationModel->syncTaskTagsToAnotherProject($task_id, $project_id); - if ($this->db->table(TaskModel::TABLE)->eq('id', $task['id'])->update($values)) { - $event = new TaskEvent(array_merge($task, $values, array('task_id' => $task['id']))); - $this->dispatcher->dispatch(TaskModel::EVENT_MOVE_PROJECT, $event); + if ($this->db->table(TaskModel::TABLE)->eq('id', $task_id)->update($values)) { + $this->queueManager->push($this->taskEventJob->withParams($task_id, array(TaskModel::EVENT_MOVE_PROJECT), $values)); } return true; diff --git a/app/Model/TaskStatusModel.php b/app/Model/TaskStatusModel.php index 4d573f0e..ea304beb 100644 --- a/app/Model/TaskStatusModel.php +++ b/app/Model/TaskStatusModel.php @@ -3,7 +3,6 @@ namespace Kanboard\Model; use Kanboard\Core\Base; -use Kanboard\Event\TaskEvent; /** * Task Status @@ -101,10 +100,10 @@ class TaskStatusModel extends Base * @param integer $task_id Task id * @param integer $status Task status * @param integer $date_completed Timestamp - * @param string $event Event name + * @param string $event_name Event name * @return boolean */ - private function changeStatus($task_id, $status, $date_completed, $event) + private function changeStatus($task_id, $status, $date_completed, $event_name) { if (! $this->taskFinderModel->exists($task_id)) { return false; @@ -120,8 +119,7 @@ class TaskStatusModel extends Base )); if ($result) { - $this->logger->debug('Event fired: '.$event); - $this->dispatcher->dispatch($event, new TaskEvent(array('task_id' => $task_id) + $this->taskFinderModel->getById($task_id))); + $this->queueManager->push($this->taskEventJob->withParams($task_id, array($event_name))); } return $result; diff --git a/app/ServiceProvider/JobProvider.php b/app/ServiceProvider/JobProvider.php index bfea6e6e..c7f323f1 100644 --- a/app/ServiceProvider/JobProvider.php +++ b/app/ServiceProvider/JobProvider.php @@ -6,6 +6,7 @@ use Kanboard\Job\CommentEventJob; use Kanboard\Job\NotificationJob; use Kanboard\Job\ProjectFileEventJob; use Kanboard\Job\SubtaskEventJob; +use Kanboard\Job\TaskEventJob; use Kanboard\Job\TaskFileEventJob; use Pimple\Container; use Pimple\ServiceProviderInterface; @@ -35,6 +36,10 @@ class JobProvider implements ServiceProviderInterface return new SubtaskEventJob($c); }); + $container['taskEventJob'] = $container->factory(function ($c) { + return new TaskEventJob($c); + }); + $container['taskFileEventJob'] = $container->factory(function ($c) { return new TaskFileEventJob($c); }); diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php index 0b3760c4..104927a0 100644 --- a/app/Subscriber/NotificationSubscriber.php +++ b/app/Subscriber/NotificationSubscriber.php @@ -3,7 +3,6 @@ namespace Kanboard\Subscriber; use Kanboard\Event\GenericEvent; -use Kanboard\Job\NotificationJob; use Kanboard\Model\TaskModel; use Kanboard\Model\CommentModel; use Kanboard\Model\SubtaskModel; @@ -38,9 +37,6 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn public function handleEvent(GenericEvent $event, $eventName) { $this->logger->debug('Subscriber executed: ' . __METHOD__); - - $this->queueManager->push(NotificationJob::getInstance($this->container) - ->withParams($event, $eventName, get_class($event)) - ); + $this->queueManager->push($this->notificationJob->withParams($event, $eventName)); } } diff --git a/app/Subscriber/ProjectModificationDateSubscriber.php b/app/Subscriber/ProjectModificationDateSubscriber.php index 97923af9..1ffe0248 100644 --- a/app/Subscriber/ProjectModificationDateSubscriber.php +++ b/app/Subscriber/ProjectModificationDateSubscriber.php @@ -24,9 +24,7 @@ class ProjectModificationDateSubscriber extends BaseSubscriber implements EventS public function execute(GenericEvent $event) { - if (isset($event['project_id'])) { - $this->logger->debug('Subscriber executed: '.__METHOD__); - $this->projectModel->updateModificationDate($event['project_id']); - } + $this->logger->debug('Subscriber executed: '.__METHOD__); + $this->projectModel->updateModificationDate($event['task']['project_id']); } } diff --git a/tests/units/Action/BaseActionTest.php b/tests/units/Action/BaseActionTest.php index 1d50c70e..feeba3f9 100644 --- a/tests/units/Action/BaseActionTest.php +++ b/tests/units/Action/BaseActionTest.php @@ -23,7 +23,7 @@ class DummyAction extends Kanboard\Action\Base public function getEventRequiredParameters() { - return array('p1', 'p2'); + return array('p1', 'p2', 'p3' => array('p4')); } public function doAction(array $data) @@ -60,7 +60,7 @@ class BaseActionTest extends Base public function testGetEventRequiredParameters() { $dummyAction = new DummyAction($this->container); - $this->assertEquals(array('p1', 'p2'), $dummyAction->getEventRequiredParameters()); + $this->assertEquals(array('p1', 'p2', 'p3' => array('p4')), $dummyAction->getEventRequiredParameters()); } public function testGetCompatibleEvents() @@ -113,7 +113,7 @@ class BaseActionTest extends Base $dummyAction = new DummyAction($this->container); $dummyAction->setProjectId(1234); - $this->assertTrue($dummyAction->hasRequiredParameters(array('p1' => 12, 'p2' => 34))); + $this->assertTrue($dummyAction->hasRequiredParameters(array('p1' => 12, 'p2' => 34, 'p3' => array('p4' => 'foobar')))); $this->assertFalse($dummyAction->hasRequiredParameters(array('p1' => 12))); $this->assertFalse($dummyAction->hasRequiredParameters(array())); } @@ -125,7 +125,7 @@ class BaseActionTest extends Base $dummyAction->addEvent('my.event', 'My Event Overrided'); $events = $dummyAction->getEvents(); - $this->assertcount(2, $events); + $this->assertCount(2, $events); $this->assertEquals(array('my.event', 'foobar'), $events); } @@ -136,7 +136,7 @@ class BaseActionTest extends Base $dummyAction->setParam('p1', 'something'); $dummyAction->addEvent('foobar', 'FooBar'); - $event = new GenericEvent(array('project_id' => 1234, 'p1' => 'something', 'p2' => 'abc')); + $event = new GenericEvent(array('project_id' => 1234, 'p1' => 'something', 'p2' => 'abc', 'p3' => array('p4' => 'a'))); $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 index 5eaf515e..b3d21287 100644 --- a/tests/units/Action/CommentCreationMoveTaskColumnTest.php +++ b/tests/units/Action/CommentCreationMoveTaskColumnTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\CommentModel; @@ -22,7 +22,7 @@ class CommentCreationMoveTaskColumnTest extends Base $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)); + $event = new TaskEvent(array('task' => array('project_id' => 1, 'column_id' => 2), 'task_id' => 1)); $action = new CommentCreationMoveTaskColumn($this->container); $action->setProjectId(1); @@ -45,7 +45,7 @@ class CommentCreationMoveTaskColumnTest extends Base $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)); + $event = new TaskEvent(array('task' => array('project_id' => 1, 'column_id' => 3), 'task_id' => 1)); $action = new CommentCreationMoveTaskColumn($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignCategoryColorTest.php b/tests/units/Action/TaskAssignCategoryColorTest.php index 09c08264..5a0f7d03 100644 --- a/tests/units/Action/TaskAssignCategoryColorTest.php +++ b/tests/units/Action/TaskAssignCategoryColorTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\CategoryModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; @@ -23,7 +23,13 @@ class TaskAssignCategoryColorTest extends Base $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')); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'color_id' => 'red', + ) + )); $action = new TaskAssignCategoryColor($this->container); $action->setProjectId(1); @@ -47,7 +53,13 @@ class TaskAssignCategoryColorTest extends Base $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')); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'color_id' => 'blue', + ) + )); $action = new TaskAssignCategoryColor($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignCategoryLinkTest.php b/tests/units/Action/TaskAssignCategoryLinkTest.php index 712c3c02..d7e68f72 100644 --- a/tests/units/Action/TaskAssignCategoryLinkTest.php +++ b/tests/units/Action/TaskAssignCategoryLinkTest.php @@ -14,19 +14,19 @@ class TaskAssignCategoryLinkTest extends Base { public function testAssignCategory() { - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $c = new CategoryModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); $action = new TaskAssignCategoryLink($this->container); $action->setProjectId(1); $action->setParam('category_id', 1); $action->setParam('link_id', 2); - $this->assertEquals(1, $p->create(array('name' => 'P1'))); - $this->assertEquals(1, $c->create(array('name' => 'C1', 'project_id' => 1))); - $this->assertEquals(1, $tc->create(array('title' => 'T1', 'project_id' => 1))); + $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'C1', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1))); $event = new TaskLinkEvent(array( 'project_id' => 1, @@ -37,25 +37,24 @@ class TaskAssignCategoryLinkTest extends Base $this->assertTrue($action->execute($event, TaskLinkModel::EVENT_CREATE_UPDATE)); - $task = $tf->getById(1); + $task = $taskFinderModel->getById(1); $this->assertEquals(1, $task['category_id']); } public function testWhenLinkDontMatch() { - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $c = new CategoryModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); $action = new TaskAssignCategoryLink($this->container); $action->setProjectId(1); $action->setParam('category_id', 1); $action->setParam('link_id', 1); - $this->assertEquals(1, $p->create(array('name' => 'P1'))); - $this->assertEquals(1, $c->create(array('name' => 'C1', 'project_id' => 1))); - $this->assertEquals(1, $tc->create(array('title' => 'T1', 'project_id' => 1))); + $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); + $this->assertEquals(1, $categoryModel->create(array('name' => 'C1', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1))); $event = new TaskLinkEvent(array( 'project_id' => 1, @@ -69,19 +68,19 @@ class TaskAssignCategoryLinkTest extends Base public function testThatExistingCategoryWillNotChange() { - $tc = new TaskCreationModel($this->container); - $p = new ProjectModel($this->container); - $c = new CategoryModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $categoryModel = new CategoryModel($this->container); $action = new TaskAssignCategoryLink($this->container); $action->setProjectId(1); $action->setParam('category_id', 2); $action->setParam('link_id', 2); - $this->assertEquals(1, $p->create(array('name' => 'P1'))); - $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' => 'T1', 'project_id' => 1, 'category_id' => 1))); + $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); + $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('title' => 'T1', 'project_id' => 1, 'category_id' => 1))); $event = new TaskLinkEvent(array( 'project_id' => 1, diff --git a/tests/units/Action/TaskAssignColorCategoryTest.php b/tests/units/Action/TaskAssignColorCategoryTest.php index 6502035f..16ad1290 100644 --- a/tests/units/Action/TaskAssignColorCategoryTest.php +++ b/tests/units/Action/TaskAssignColorCategoryTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\CategoryModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; @@ -23,7 +23,13 @@ class TaskAssignColorCategoryTest extends Base $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, 'category_id' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'category_id' => 1, + ) + )); $action = new TaskAssignColorCategory($this->container); $action->setProjectId(1); @@ -45,7 +51,13 @@ class TaskAssignColorCategoryTest extends Base $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, 'category_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'category_id' => 2, + ) + )); $action = new TaskAssignColorCategory($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignColorColumnTest.php b/tests/units/Action/TaskAssignColorColumnTest.php index d4ba8e01..ccfb9e88 100644 --- a/tests/units/Action/TaskAssignColorColumnTest.php +++ b/tests/units/Action/TaskAssignColorColumnTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -20,7 +20,13 @@ class TaskAssignColorColumnTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskAssignColorColumn($this->container); $action->setProjectId(1); @@ -42,7 +48,13 @@ class TaskAssignColorColumnTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskAssignColorColumn($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignColorPriorityTest.php b/tests/units/Action/TaskAssignColorPriorityTest.php index 2fce8e66..0ea874cd 100644 --- a/tests/units/Action/TaskAssignColorPriorityTest.php +++ b/tests/units/Action/TaskAssignColorPriorityTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\CategoryModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; @@ -23,7 +23,13 @@ class TaskAssignColorPriorityTest extends Base $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, 'priority' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'priority' => 1, + ) + )); $action = new TaskAssignColorPriority($this->container); $action->setProjectId(1); @@ -45,7 +51,13 @@ class TaskAssignColorPriorityTest extends Base $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, 'priority' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'priority' => 2, + ) + )); $action = new TaskAssignColorPriority($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignColorUserTest.php b/tests/units/Action/TaskAssignColorUserTest.php index 370f9070..45faa3ff 100644 --- a/tests/units/Action/TaskAssignColorUserTest.php +++ b/tests/units/Action/TaskAssignColorUserTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -20,7 +20,13 @@ class TaskAssignColorUserTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'owner_id' => 1, + ) + )); $action = new TaskAssignColorUser($this->container); $action->setProjectId(1); @@ -42,7 +48,13 @@ class TaskAssignColorUserTest extends Base $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' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'owner_id' => 2, + ) + )); $action = new TaskAssignColorUser($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignCurrentUserColumnTest.php b/tests/units/Action/TaskAssignCurrentUserColumnTest.php index 6fdbda63..3b64d718 100644 --- a/tests/units/Action/TaskAssignCurrentUserColumnTest.php +++ b/tests/units/Action/TaskAssignCurrentUserColumnTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -22,7 +22,13 @@ class TaskAssignCurrentUserColumnTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskAssignCurrentUserColumn($this->container); $action->setProjectId(1); @@ -45,7 +51,13 @@ class TaskAssignCurrentUserColumnTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskAssignCurrentUserColumn($this->container); $action->setProjectId(1); @@ -62,7 +74,13 @@ class TaskAssignCurrentUserColumnTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskAssignCurrentUserColumn($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskAssignSpecificUserTest.php b/tests/units/Action/TaskAssignSpecificUserTest.php index 78ec314f..0e63fc13 100644 --- a/tests/units/Action/TaskAssignSpecificUserTest.php +++ b/tests/units/Action/TaskAssignSpecificUserTest.php @@ -3,6 +3,7 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -20,7 +21,13 @@ class TaskAssignSpecificUserTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test', 'owner_id' => 0))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskAssignSpecificUser($this->container); $action->setProjectId(1); @@ -42,7 +49,13 @@ class TaskAssignSpecificUserTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskAssignSpecificUser($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskCloseColumnTest.php b/tests/units/Action/TaskCloseColumnTest.php index f9a938f0..7afb0478 100644 --- a/tests/units/Action/TaskCloseColumnTest.php +++ b/tests/units/Action/TaskCloseColumnTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -20,7 +20,13 @@ class TaskCloseColumnTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskCloseColumn($this->container); $action->setProjectId(1); @@ -41,7 +47,13 @@ class TaskCloseColumnTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskCloseColumn($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskCloseTest.php b/tests/units/Action/TaskCloseTest.php index 3df10cb8..589ef133 100644 --- a/tests/units/Action/TaskCloseTest.php +++ b/tests/units/Action/TaskCloseTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -19,7 +19,12 @@ class TaskCloseTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + ) + )); $action = new TaskClose($this->container); $action->setProjectId(1); @@ -40,7 +45,11 @@ class TaskCloseTest extends Base $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)); + $event = new TaskEvent(array( + 'task' => array( + 'project_id' => 1, + ) + )); $action = new TaskClose($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskDuplicateAnotherProjectTest.php b/tests/units/Action/TaskDuplicateAnotherProjectTest.php index 98ff187f..5cd0c977 100644 --- a/tests/units/Action/TaskDuplicateAnotherProjectTest.php +++ b/tests/units/Action/TaskDuplicateAnotherProjectTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\TaskCreationModel; @@ -21,7 +21,13 @@ class TaskDuplicateAnotherProjectTest extends Base $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' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskDuplicateAnotherProject($this->container); $action->setProjectId(1); @@ -43,7 +49,13 @@ class TaskDuplicateAnotherProjectTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskDuplicateAnotherProject($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskEmailTest.php b/tests/units/Action/TaskEmailTest.php index df71aaf8..421c89ca 100644 --- a/tests/units/Action/TaskEmailTest.php +++ b/tests/units/Action/TaskEmailTest.php @@ -2,7 +2,8 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; +use Kanboard\Model\TaskFinderModel; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\ProjectModel; @@ -16,16 +17,20 @@ class TaskEmailTest extends Base $userModel = new UserModel($this->container); $projectModel = new ProjectModel($this->container); $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); $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'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => $taskFinderModel->getDetails(1) + )); $action = new TaskEmail($this->container); $action->setProjectId(1); - $action->setParam('column_id', 2); + $action->setParam('column_id', 1); $action->setParam('user_id', 1); $action->setParam('subject', 'My email subject'); @@ -47,7 +52,13 @@ class TaskEmailTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 3)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskEmail($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskMoveAnotherProjectTest.php b/tests/units/Action/TaskMoveAnotherProjectTest.php index d36df47b..a41fd03f 100644 --- a/tests/units/Action/TaskMoveAnotherProjectTest.php +++ b/tests/units/Action/TaskMoveAnotherProjectTest.php @@ -3,6 +3,7 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\TaskCreationModel; @@ -21,7 +22,13 @@ class TaskMoveAnotherProjectTest extends Base $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' => 2)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskMoveAnotherProject($this->container); $action->setProjectId(1); @@ -44,7 +51,13 @@ class TaskMoveAnotherProjectTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskMoveAnotherProject($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskMoveColumnAssignedTest.php b/tests/units/Action/TaskMoveColumnAssignedTest.php index f8982969..aa9d3592 100644 --- a/tests/units/Action/TaskMoveColumnAssignedTest.php +++ b/tests/units/Action/TaskMoveColumnAssignedTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\TaskCreationModel; @@ -19,9 +19,12 @@ class TaskMoveColumnAssignedTest extends Base $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->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test', 'owner_id' => 1))); - $event = new GenericEvent(array('project_id' => 1, 'task_id' => 1, 'column_id' => 1, 'owner_id' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => $taskFinderModel->getDetails(1), + )); $action = new TaskMoveColumnAssigned($this->container); $action->setProjectId(1); @@ -43,7 +46,14 @@ class TaskMoveColumnAssignedTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + 'owner_id' => 1, + ) + )); $action = new TaskMoveColumnAssigned($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskMoveColumnCategoryChangeTest.php b/tests/units/Action/TaskMoveColumnCategoryChangeTest.php index c42383f8..7e0856df 100644 --- a/tests/units/Action/TaskMoveColumnCategoryChangeTest.php +++ b/tests/units/Action/TaskMoveColumnCategoryChangeTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\CategoryModel; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskFinderModel; @@ -24,7 +24,16 @@ class TaskMoveColumnCategoryChangeTest extends Base $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' => 1, 'category_id' => 1)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 1, + 'category_id' => 1, + 'position' => 1, + 'swimlane_id' => 0, + ) + )); $action = new TaskMoveColumnCategoryChange($this->container); $action->setProjectId(1); @@ -50,7 +59,14 @@ class TaskMoveColumnCategoryChangeTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + 'category_id' => 1, + ) + )); $action = new TaskMoveColumnCategoryChange($this->container); $action->setProjectId(1); @@ -72,7 +88,14 @@ class TaskMoveColumnCategoryChangeTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 1, + 'category_id' => 2, + ) + )); $action = new TaskMoveColumnCategoryChange($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskMoveColumnUnAssignedTest.php b/tests/units/Action/TaskMoveColumnUnAssignedTest.php index befae36b..b45dec08 100644 --- a/tests/units/Action/TaskMoveColumnUnAssignedTest.php +++ b/tests/units/Action/TaskMoveColumnUnAssignedTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\TaskCreationModel; @@ -21,7 +21,16 @@ class TaskMoveColumnUnAssignedTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 1, + 'owner_id' => 0, + 'position' => 1, + 'swimlane_id' => 0, + ) + )); $action = new TaskMoveColumnUnAssigned($this->container); $action->setProjectId(1); @@ -43,7 +52,14 @@ class TaskMoveColumnUnAssignedTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + 'owner_id' => 0, + ) + )); $action = new TaskMoveColumnUnAssigned($this->container); $action->setProjectId(1); @@ -60,7 +76,14 @@ class TaskMoveColumnUnAssignedTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 1, + 'owner_id' => 1, + ) + )); $action = new TaskMoveColumnUnAssigned($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskOpenTest.php b/tests/units/Action/TaskOpenTest.php index 1018e2ea..825c6ac9 100644 --- a/tests/units/Action/TaskOpenTest.php +++ b/tests/units/Action/TaskOpenTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -19,7 +19,12 @@ class TaskOpenTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + ) + )); $action = new TaskOpen($this->container); $action->setProjectId(1); @@ -40,7 +45,11 @@ class TaskOpenTest extends Base $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)); + $event = new TaskEvent(array( + 'task' => array( + 'project_id' => 1, + ) + )); $action = new TaskOpen($this->container); $action->setProjectId(1); diff --git a/tests/units/Action/TaskUpdateStartDateTest.php b/tests/units/Action/TaskUpdateStartDateTest.php index ddd9eafd..8d609b3e 100644 --- a/tests/units/Action/TaskUpdateStartDateTest.php +++ b/tests/units/Action/TaskUpdateStartDateTest.php @@ -3,6 +3,7 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Event\GenericEvent; +use Kanboard\Event\TaskEvent; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -20,7 +21,13 @@ class TaskUpdateStartDateTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 2, + ) + )); $action = new TaskUpdateStartDate($this->container); $action->setProjectId(1); @@ -41,7 +48,13 @@ class TaskUpdateStartDateTest extends Base $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)); + $event = new TaskEvent(array( + 'task_id' => 1, + 'task' => array( + 'project_id' => 1, + 'column_id' => 3, + ) + )); $action = new TaskUpdateStartDate($this->container); $action->setProjectId(1); diff --git a/tests/units/EventBuilder/TaskEventBuilderTest.php b/tests/units/EventBuilder/TaskEventBuilderTest.php new file mode 100644 index 00000000..e6334fe2 --- /dev/null +++ b/tests/units/EventBuilder/TaskEventBuilderTest.php @@ -0,0 +1,100 @@ +container); + $taskEventBuilder->withTaskId(42); + $this->assertNull($taskEventBuilder->build()); + } + + public function testBuildWithTask() + { + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskEventBuilder = new TaskEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'before', 'project_id' => 1))); + + $event = $taskEventBuilder + ->withTaskId(1) + ->withTask(array('title' => 'before')) + ->withChanges(array('title' => 'after')) + ->build(); + + $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); + $this->assertNotEmpty($event['task']); + $this->assertEquals(1, $event['task_id']); + $this->assertEquals(array('title' => 'after'), $event['changes']); + } + + public function testBuildWithoutChanges() + { + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskEventBuilder = new TaskEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + + $event = $taskEventBuilder->withTaskId(1)->build(); + + $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); + $this->assertNotEmpty($event['task']); + $this->assertEquals(1, $event['task_id']); + $this->assertArrayNotHasKey('changes', $event); + } + + public function testBuildWithChanges() + { + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskEventBuilder = new TaskEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + + $event = $taskEventBuilder + ->withTaskId(1) + ->withChanges(array('title' => 'new title')) + ->build(); + + $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); + $this->assertNotEmpty($event['task']); + $this->assertNotEmpty($event['changes']); + $this->assertEquals('new title', $event['changes']['title']); + } + + public function testBuildWithChangesAndValues() + { + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskEventBuilder = new TaskEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + + $event = $taskEventBuilder + ->withTaskId(1) + ->withChanges(array('title' => 'new title', 'project_id' => 1)) + ->withValues(array('key' => 'value')) + ->build(); + + $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); + $this->assertNotEmpty($event['task']); + $this->assertNotEmpty($event['changes']); + $this->assertNotEmpty($event['key']); + $this->assertEquals('value', $event['key']); + + $this->assertCount(1, $event['changes']); + $this->assertEquals('new title', $event['changes']['title']); + } +} diff --git a/tests/units/Job/SubtaskEventJobTest.php b/tests/units/Job/SubtaskEventJobTest.php index 265a8e2d..66c3db05 100644 --- a/tests/units/Job/SubtaskEventJobTest.php +++ b/tests/units/Job/SubtaskEventJobTest.php @@ -21,8 +21,8 @@ class SubtaskEventJobTest extends Base { $this->container['dispatcher']->addListener(SubtaskModel::EVENT_CREATE, function() {}); - $SubtaskEventJob = new SubtaskEventJob($this->container); - $SubtaskEventJob->execute(42, SubtaskModel::EVENT_CREATE); + $subtaskEventJob = new SubtaskEventJob($this->container); + $subtaskEventJob->execute(42, SubtaskModel::EVENT_CREATE); $called = $this->container['dispatcher']->getCalledListeners(); $this->assertEmpty($called); diff --git a/tests/units/Job/TaskEventJobTest.php b/tests/units/Job/TaskEventJobTest.php new file mode 100644 index 00000000..c399faad --- /dev/null +++ b/tests/units/Job/TaskEventJobTest.php @@ -0,0 +1,189 @@ +container); + $taskEventJob->withParams(123, array('foobar'), array('k' => 'v'), array('k1' => 'v1'), array('k2' => 'v2')); + + $this->assertSame( + array(123, array('foobar'), array('k' => 'v'), array('k1' => 'v1'), array('k2' => 'v2')), + $taskEventJob->getJobParams() + ); + } + + public function testWithMissingTask() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE, function() {}); + + $taskEventJob = new TaskEventJob($this->container); + $taskEventJob->execute(42, array(TaskModel::EVENT_CREATE)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertEmpty($called); + } + + public function testTriggerCreateEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE, function() {}); + $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE_UPDATE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_CREATE.'.closure', $called); + $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.closure', $called); + } + + public function testTriggerUpdateEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_UPDATE, function() {}); + $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE_UPDATE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskModificationModel = new TaskModificationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertTrue($taskModificationModel->update(array('id' => 1, 'title' => 'new title'))); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_UPDATE.'.closure', $called); + $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.closure', $called); + } + + public function testTriggerAssigneeChangeEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_ASSIGNEE_CHANGE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskModificationModel = new TaskModificationModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertTrue($taskModificationModel->update(array('id' => 1, 'owner_id' => 1))); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_ASSIGNEE_CHANGE.'.closure', $called); + } + + public function testTriggerCloseEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_CLOSE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskStatusModel = new TaskStatusModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertTrue($taskStatusModel->close(1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_CLOSE.'.closure', $called); + } + + public function testTriggerOpenEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_OPEN, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskStatusModel = new TaskStatusModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertTrue($taskStatusModel->close(1)); + $this->assertTrue($taskStatusModel->open(1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_OPEN.'.closure', $called); + } + + public function testTriggerMovePositionEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_POSITION, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskPositionModel = new TaskPositionModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'test 2', 'project_id' => 1))); + $this->assertTrue($taskPositionModel->movePosition(1, 1, 1, 2)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_POSITION.'.closure', $called); + } + + public function testTriggerMoveColumnEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_COLUMN, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskPositionModel = new TaskPositionModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + $this->assertTrue($taskPositionModel->movePosition(1, 1, 2, 2)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_COLUMN.'.closure', $called); + } + + public function testTriggerMoveSwimlaneEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_SWIMLANE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $taskPositionModel = new TaskPositionModel($this->container); + $projectModel = new ProjectModel($this->container); + $swimlaneModel = new SwimlaneModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $swimlaneModel->create(array('name' => 'S1', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + $this->assertTrue($taskPositionModel->movePosition(1, 1, 1, 1, 1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_SWIMLANE.'.closure', $called); + } + + public function testTriggerMoveProjectEvent() + { + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_PROJECT, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskProjectMoveModel = new TaskProjectMoveModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + $this->assertTrue($taskProjectMoveModel->moveToProject(1, 1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_PROJECT.'.closure', $called); + } +} diff --git a/tests/units/Model/TaskCreationModelTest.php b/tests/units/Model/TaskCreationModelTest.php index f97c61dc..ce9996d9 100644 --- a/tests/units/Model/TaskCreationModelTest.php +++ b/tests/units/Model/TaskCreationModelTest.php @@ -17,7 +17,7 @@ class TaskCreationModelTest extends Base $event_data = $event->getAll(); $this->assertNotEmpty($event_data); $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals('test', $event_data['title']); + $this->assertEquals('test', $event_data['task']['title']); } public function testNoTitle() diff --git a/tests/units/Model/TaskModificationModelTest.php b/tests/units/Model/TaskModificationModelTest.php index c81f968b..f70561b3 100644 --- a/tests/units/Model/TaskModificationModelTest.php +++ b/tests/units/Model/TaskModificationModelTest.php @@ -18,7 +18,8 @@ class TaskModificationModelTest extends Base $event_data = $event->getAll(); $this->assertNotEmpty($event_data); $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals('Task #1', $event_data['title']); + $this->assertEquals('After', $event_data['task']['title']); + $this->assertEquals('After', $event_data['changes']['title']); } public function onUpdate($event) @@ -28,7 +29,7 @@ class TaskModificationModelTest extends Base $event_data = $event->getAll(); $this->assertNotEmpty($event_data); $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals('Task #1', $event_data['title']); + $this->assertEquals('After', $event_data['task']['title']); } public function onAssigneeChange($event) @@ -38,7 +39,7 @@ class TaskModificationModelTest extends Base $event_data = $event->getAll(); $this->assertNotEmpty($event_data); $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals(1, $event_data['owner_id']); + $this->assertEquals(1, $event_data['changes']['owner_id']); } public function testThatNoEventAreFiredWhenNoChanges() @@ -66,19 +67,19 @@ class TaskModificationModelTest extends Base $taskFinderModel = new TaskFinderModel($this->container); $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Before', 'project_id' => 1))); $this->container['dispatcher']->addListener(TaskModel::EVENT_CREATE_UPDATE, array($this, 'onCreateUpdate')); $this->container['dispatcher']->addListener(TaskModel::EVENT_UPDATE, array($this, 'onUpdate')); - $this->assertTrue($taskModificationModel->update(array('id' => 1, 'title' => 'Task #1'))); + $this->assertTrue($taskModificationModel->update(array('id' => 1, 'title' => 'After'))); $called = $this->container['dispatcher']->getCalledListeners(); $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.TaskModificationModelTest::onCreateUpdate', $called); $this->assertArrayHasKey(TaskModel::EVENT_UPDATE.'.TaskModificationModelTest::onUpdate', $called); $task = $taskFinderModel->getById(1); - $this->assertEquals('Task #1', $task['title']); + $this->assertEquals('After', $task['title']); } public function testChangeAssignee() diff --git a/tests/units/Model/TaskPositionModelTest.php b/tests/units/Model/TaskPositionModelTest.php new file mode 100644 index 00000000..03caf7ed --- /dev/null +++ b/tests/units/Model/TaskPositionModelTest.php @@ -0,0 +1,631 @@ +container); + $taskStatusModel = new TaskStatusModel($this->container); + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $columnModel = new ColumnModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(0, $taskModel->getProgress($taskFinderModel->getById(1), $columnModel->getList(1))); + + $this->assertTrue($taskPositionModel->movePosition(1, 1, 2, 1)); + $this->assertEquals(25, $taskModel->getProgress($taskFinderModel->getById(1), $columnModel->getList(1))); + + $this->assertTrue($taskPositionModel->movePosition(1, 1, 3, 1)); + $this->assertEquals(50, $taskModel->getProgress($taskFinderModel->getById(1), $columnModel->getList(1))); + + $this->assertTrue($taskPositionModel->movePosition(1, 1, 4, 1)); + $this->assertEquals(75, $taskModel->getProgress($taskFinderModel->getById(1), $columnModel->getList(1))); + + $this->assertTrue($taskStatusModel->close(1)); + $this->assertEquals(100, $taskModel->getProgress($taskFinderModel->getById(1), $columnModel->getList(1))); + } + + public function testMoveTaskToWrongPosition() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + + // We move the task 2 to the position 0 + $this->assertFalse($taskPositionModel->movePosition(1, 1, 3, 0)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + } + + public function testMoveTaskToGreaterPosition() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + + // We move the task 2 to the position 42 + $this->assertTrue($taskPositionModel->movePosition(1, 1, 1, 42)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + } + + public function testMoveTaskToEmptyColumn() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + + // We move the task 1 to the column 3 + $this->assertTrue($taskPositionModel->movePosition(1, 1, 3, 1)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(3, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + } + + public function testMoveTaskToAnotherColumn() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(3, $taskCreationModel->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(4, $taskCreationModel->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 2))); + $this->assertEquals(5, $taskCreationModel->create(array('title' => 'Task #5', 'project_id' => 1, 'column_id' => 2))); + $this->assertEquals(6, $taskCreationModel->create(array('title' => 'Task #6', 'project_id' => 1, 'column_id' => 2))); + $this->assertEquals(7, $taskCreationModel->create(array('title' => 'Task #7', 'project_id' => 1, 'column_id' => 3))); + $this->assertEquals(8, $taskCreationModel->create(array('title' => 'Task #8', 'project_id' => 1, 'column_id' => 1))); + + // We move the task 3 to the column 3 + $this->assertTrue($taskPositionModel->movePosition(1, 3, 3, 2)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(3, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(5); + $this->assertEquals(5, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(6); + $this->assertEquals(6, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(3, $task['position']); + + $task = $taskFinderModel->getById(7); + $this->assertEquals(7, $task['id']); + $this->assertEquals(3, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(8); + $this->assertEquals(8, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(3, $task['position']); + } + + public function testMoveTaskTop() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(3, $taskCreationModel->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(4, $taskCreationModel->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 1))); + + // Move the last task to the top + $this->assertTrue($taskPositionModel->movePosition(1, 4, 1, 1)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(3, $task['position']); + + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(4, $task['position']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + } + + public function testMoveTaskBottom() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(3, $taskCreationModel->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(4, $taskCreationModel->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 1))); + + // Move the first task to the bottom + $this->assertTrue($taskPositionModel->movePosition(1, 1, 1, 4)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(4, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(3, $task['position']); + } + + public function testMovePosition() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $counter = 1; + $task_per_column = 5; + + foreach (array(1, 2, 3, 4) as $column_id) { + for ($i = 1; $i <= $task_per_column; $i++, $counter++) { + $task = array( + 'title' => 'Task #'.$i.'-'.$column_id, + 'project_id' => 1, + 'column_id' => $column_id, + 'owner_id' => 0, + ); + + $this->assertEquals($counter, $taskCreationModel->create($task)); + + $task = $taskFinderModel->getById($counter); + $this->assertNotEmpty($task); + $this->assertEquals($i, $task['position']); + } + } + + // We move task id #4, column 1, position 4 to the column 2, position 3 + $this->assertTrue($taskPositionModel->movePosition(1, 4, 2, 3)); + + // We check the new position of the task + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(3, $task['position']); + + // The tasks before have the correct position + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(3, $task['position']); + + $task = $taskFinderModel->getById(7); + $this->assertEquals(7, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(2, $task['position']); + + // The tasks after have the correct position + $task = $taskFinderModel->getById(5); + $this->assertEquals(5, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(4, $task['position']); + + $task = $taskFinderModel->getById(8); + $this->assertEquals(8, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(4, $task['position']); + + // The number of tasks per column + $this->assertEquals($task_per_column - 1, $taskFinderModel->countByColumnId(1, 1)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 2)); + $this->assertEquals($task_per_column, $taskFinderModel->countByColumnId(1, 3)); + $this->assertEquals($task_per_column, $taskFinderModel->countByColumnId(1, 4)); + + // We move task id #1, column 1, position 1 to the column 4, position 6 (last position) + $this->assertTrue($taskPositionModel->movePosition(1, 1, 4, $task_per_column + 1)); + + // We check the new position of the task + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(4, $task['column_id']); + $this->assertEquals($task_per_column + 1, $task['position']); + + // The tasks before have the correct position + $task = $taskFinderModel->getById(20); + $this->assertEquals(20, $task['id']); + $this->assertEquals(4, $task['column_id']); + $this->assertEquals($task_per_column, $task['position']); + + // The tasks after have the correct position + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + + // The number of tasks per column + $this->assertEquals($task_per_column - 2, $taskFinderModel->countByColumnId(1, 1)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 2)); + $this->assertEquals($task_per_column, $taskFinderModel->countByColumnId(1, 3)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 4)); + + // Our previous moved task should stay at the same place + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(3, $task['position']); + + // Test wrong position number + $this->assertFalse($taskPositionModel->movePosition(1, 2, 3, 0)); + $this->assertFalse($taskPositionModel->movePosition(1, 2, 3, -2)); + + // Wrong column + $this->assertFalse($taskPositionModel->movePosition(1, 2, 22, 2)); + + // Test position greater than the last position + $this->assertTrue($taskPositionModel->movePosition(1, 11, 1, 22)); + + $task = $taskFinderModel->getById(11); + $this->assertEquals(11, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals($taskFinderModel->countByColumnId(1, 1), $task['position']); + + $task = $taskFinderModel->getById(5); + $this->assertEquals(5, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals($taskFinderModel->countByColumnId(1, 1) - 1, $task['position']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(3, $task['position']); + + $this->assertEquals($task_per_column - 1, $taskFinderModel->countByColumnId(1, 1)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 2)); + $this->assertEquals($task_per_column - 1, $taskFinderModel->countByColumnId(1, 3)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 4)); + + // Our previous moved task should stay at the same place + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(3, $task['position']); + + // Test moving task to position 1 + $this->assertTrue($taskPositionModel->movePosition(1, 14, 1, 1)); + + $task = $taskFinderModel->getById(14); + $this->assertEquals(14, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $this->assertEquals($task_per_column, $taskFinderModel->countByColumnId(1, 1)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 2)); + $this->assertEquals($task_per_column - 2, $taskFinderModel->countByColumnId(1, 3)); + $this->assertEquals($task_per_column + 1, $taskFinderModel->countByColumnId(1, 4)); + } + + public function testMoveTaskSwimlane() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $swimlaneModel = new SwimlaneModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $swimlaneModel->create(array('project_id' => 1, 'name' => 'test 1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(3, $taskCreationModel->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(4, $taskCreationModel->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(5, $taskCreationModel->create(array('title' => 'Task #5', 'project_id' => 1, 'column_id' => 1))); + + // Move the task to the swimlane + $this->assertTrue($taskPositionModel->movePosition(1, 1, 2, 1, 1)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(1, $task['swimlane_id']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(3, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + // Move the task to the swimlane + $this->assertTrue($taskPositionModel->movePosition(1, 2, 2, 1, 1)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(2, $task['position']); + $this->assertEquals(1, $task['swimlane_id']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(1, $task['swimlane_id']); + + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + // Move the task 5 to the last column + $this->assertTrue($taskPositionModel->movePosition(1, 5, 4, 1, 0)); + + // Check tasks position + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(2, $task['position']); + $this->assertEquals(1, $task['swimlane_id']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(1, $task['swimlane_id']); + + $task = $taskFinderModel->getById(3); + $this->assertEquals(3, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + $task = $taskFinderModel->getById(4); + $this->assertEquals(4, $task['id']); + $this->assertEquals(1, $task['column_id']); + $this->assertEquals(2, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + $task = $taskFinderModel->getById(5); + $this->assertEquals(5, $task['id']); + $this->assertEquals(4, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + } + + public function testEvents() + { + $taskPositionModel = new TaskPositionModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $swimlaneModel = new SwimlaneModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $swimlaneModel->create(array('project_id' => 1, 'name' => 'test 1'))); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 2))); + + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_COLUMN, array($this, 'onMoveColumn')); + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_POSITION, array($this, 'onMovePosition')); + $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_SWIMLANE, array($this, 'onMoveSwimlane')); + + // We move the task 1 to the column 2 + $this->assertTrue($taskPositionModel->movePosition(1, 1, 2, 1)); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_COLUMN.'.TaskPositionModelTest::onMoveColumn', $called); + $this->assertEquals(1, count($called)); + + // We move the task 1 to the position 2 + $this->assertTrue($taskPositionModel->movePosition(1, 1, 2, 2)); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(2, $task['position']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_POSITION.'.TaskPositionModelTest::onMovePosition', $called); + $this->assertEquals(2, count($called)); + + // Move to another swimlane + $this->assertTrue($taskPositionModel->movePosition(1, 1, 3, 1, 1)); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['id']); + $this->assertEquals(3, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(1, $task['swimlane_id']); + + $task = $taskFinderModel->getById(2); + $this->assertEquals(2, $task['id']); + $this->assertEquals(2, $task['column_id']); + $this->assertEquals(1, $task['position']); + $this->assertEquals(0, $task['swimlane_id']); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskModel::EVENT_MOVE_SWIMLANE.'.TaskPositionModelTest::onMoveSwimlane', $called); + $this->assertEquals(3, count($called)); + } + + public function onMoveColumn($event) + { + $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); + + $event_data = $event->getAll(); + $this->assertNotEmpty($event_data); + $this->assertEquals(1, $event_data['task_id']); + $this->assertEquals(1, $event_data['position']); + $this->assertEquals(2, $event_data['column_id']); + $this->assertEquals(1, $event_data['project_id']); + } + + public function onMovePosition($event) + { + $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); + + $event_data = $event->getAll(); + $this->assertNotEmpty($event_data); + $this->assertEquals(1, $event_data['task_id']); + $this->assertEquals(2, $event_data['position']); + $this->assertEquals(2, $event_data['column_id']); + $this->assertEquals(1, $event_data['project_id']); + } + + public function onMoveSwimlane($event) + { + $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); + + $event_data = $event->getAll(); + $this->assertNotEmpty($event_data); + $this->assertEquals(1, $event_data['task_id']); + $this->assertEquals(1, $event_data['position']); + $this->assertEquals(3, $event_data['column_id']); + $this->assertEquals(1, $event_data['project_id']); + $this->assertEquals(1, $event_data['swimlane_id']); + } +} diff --git a/tests/units/Model/TaskPositionTest.php b/tests/units/Model/TaskPositionTest.php deleted file mode 100644 index 7ab6950e..00000000 --- a/tests/units/Model/TaskPositionTest.php +++ /dev/null @@ -1,631 +0,0 @@ -container); - $ts = new TaskStatusModel($this->container); - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $columnModel = new ColumnModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(0, $t->getProgress($tf->getById(1), $columnModel->getList(1))); - - $this->assertTrue($tp->movePosition(1, 1, 2, 1)); - $this->assertEquals(25, $t->getProgress($tf->getById(1), $columnModel->getList(1))); - - $this->assertTrue($tp->movePosition(1, 1, 3, 1)); - $this->assertEquals(50, $t->getProgress($tf->getById(1), $columnModel->getList(1))); - - $this->assertTrue($tp->movePosition(1, 1, 4, 1)); - $this->assertEquals(75, $t->getProgress($tf->getById(1), $columnModel->getList(1))); - - $this->assertTrue($ts->close(1)); - $this->assertEquals(100, $t->getProgress($tf->getById(1), $columnModel->getList(1))); - } - - public function testMoveTaskToWrongPosition() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - - $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(2, $tc->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); - - // We move the task 2 to the position 0 - $this->assertFalse($tp->movePosition(1, 1, 3, 0)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - } - - public function testMoveTaskToGreaterPosition() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - - $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(2, $tc->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); - - // We move the task 2 to the position 42 - $this->assertTrue($tp->movePosition(1, 1, 1, 42)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - } - - public function testMoveTaskToEmptyColumn() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - - $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(2, $tc->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); - - // We move the task 1 to the column 3 - $this->assertTrue($tp->movePosition(1, 1, 3, 1)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(3, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - } - - public function testMoveTaskToAnotherColumn() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - - $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(2, $tc->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(3, $tc->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(4, $tc->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 2))); - $this->assertEquals(5, $tc->create(array('title' => 'Task #5', 'project_id' => 1, 'column_id' => 2))); - $this->assertEquals(6, $tc->create(array('title' => 'Task #6', 'project_id' => 1, 'column_id' => 2))); - $this->assertEquals(7, $tc->create(array('title' => 'Task #7', 'project_id' => 1, 'column_id' => 3))); - $this->assertEquals(8, $tc->create(array('title' => 'Task #8', 'project_id' => 1, 'column_id' => 1))); - - // We move the task 3 to the column 3 - $this->assertTrue($tp->movePosition(1, 3, 3, 2)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(3, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(5); - $this->assertEquals(5, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(6); - $this->assertEquals(6, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(3, $task['position']); - - $task = $tf->getById(7); - $this->assertEquals(7, $task['id']); - $this->assertEquals(3, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(8); - $this->assertEquals(8, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(3, $task['position']); - } - - public function testMoveTaskTop() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(2, $tc->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(3, $tc->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(4, $tc->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 1))); - - // Move the last task to the top - $this->assertTrue($tp->movePosition(1, 4, 1, 1)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(3, $task['position']); - - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(4, $task['position']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - } - - public function testMoveTaskBottom() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(2, $tc->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(3, $tc->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(4, $tc->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 1))); - - // Move the first task to the bottom - $this->assertTrue($tp->movePosition(1, 1, 1, 4)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(4, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(3, $task['position']); - } - - public function testMovePosition() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - $counter = 1; - $task_per_column = 5; - - foreach (array(1, 2, 3, 4) as $column_id) { - for ($i = 1; $i <= $task_per_column; $i++, $counter++) { - $task = array( - 'title' => 'Task #'.$i.'-'.$column_id, - 'project_id' => 1, - 'column_id' => $column_id, - 'owner_id' => 0, - ); - - $this->assertEquals($counter, $tc->create($task)); - - $task = $tf->getById($counter); - $this->assertNotEmpty($task); - $this->assertEquals($i, $task['position']); - } - } - - // We move task id #4, column 1, position 4 to the column 2, position 3 - $this->assertTrue($tp->movePosition(1, 4, 2, 3)); - - // We check the new position of the task - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(3, $task['position']); - - // The tasks before have the correct position - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(3, $task['position']); - - $task = $tf->getById(7); - $this->assertEquals(7, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(2, $task['position']); - - // The tasks after have the correct position - $task = $tf->getById(5); - $this->assertEquals(5, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(4, $task['position']); - - $task = $tf->getById(8); - $this->assertEquals(8, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(4, $task['position']); - - // The number of tasks per column - $this->assertEquals($task_per_column - 1, $tf->countByColumnId(1, 1)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 2)); - $this->assertEquals($task_per_column, $tf->countByColumnId(1, 3)); - $this->assertEquals($task_per_column, $tf->countByColumnId(1, 4)); - - // We move task id #1, column 1, position 1 to the column 4, position 6 (last position) - $this->assertTrue($tp->movePosition(1, 1, 4, $task_per_column + 1)); - - // We check the new position of the task - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(4, $task['column_id']); - $this->assertEquals($task_per_column + 1, $task['position']); - - // The tasks before have the correct position - $task = $tf->getById(20); - $this->assertEquals(20, $task['id']); - $this->assertEquals(4, $task['column_id']); - $this->assertEquals($task_per_column, $task['position']); - - // The tasks after have the correct position - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - - // The number of tasks per column - $this->assertEquals($task_per_column - 2, $tf->countByColumnId(1, 1)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 2)); - $this->assertEquals($task_per_column, $tf->countByColumnId(1, 3)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 4)); - - // Our previous moved task should stay at the same place - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(3, $task['position']); - - // Test wrong position number - $this->assertFalse($tp->movePosition(1, 2, 3, 0)); - $this->assertFalse($tp->movePosition(1, 2, 3, -2)); - - // Wrong column - $this->assertFalse($tp->movePosition(1, 2, 22, 2)); - - // Test position greater than the last position - $this->assertTrue($tp->movePosition(1, 11, 1, 22)); - - $task = $tf->getById(11); - $this->assertEquals(11, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals($tf->countByColumnId(1, 1), $task['position']); - - $task = $tf->getById(5); - $this->assertEquals(5, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals($tf->countByColumnId(1, 1) - 1, $task['position']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(3, $task['position']); - - $this->assertEquals($task_per_column - 1, $tf->countByColumnId(1, 1)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 2)); - $this->assertEquals($task_per_column - 1, $tf->countByColumnId(1, 3)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 4)); - - // Our previous moved task should stay at the same place - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(3, $task['position']); - - // Test moving task to position 1 - $this->assertTrue($tp->movePosition(1, 14, 1, 1)); - - $task = $tf->getById(14); - $this->assertEquals(14, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $this->assertEquals($task_per_column, $tf->countByColumnId(1, 1)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 2)); - $this->assertEquals($task_per_column - 2, $tf->countByColumnId(1, 3)); - $this->assertEquals($task_per_column + 1, $tf->countByColumnId(1, 4)); - } - - public function testMoveTaskSwimlane() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $s = new SwimlaneModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $s->create(array('project_id' => 1, 'name' => 'test 1'))); - $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(2, $tc->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(3, $tc->create(array('title' => 'Task #3', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(4, $tc->create(array('title' => 'Task #4', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(5, $tc->create(array('title' => 'Task #5', 'project_id' => 1, 'column_id' => 1))); - - // Move the task to the swimlane - $this->assertTrue($tp->movePosition(1, 1, 2, 1, 1)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(1, $task['swimlane_id']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(3, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - // Move the task to the swimlane - $this->assertTrue($tp->movePosition(1, 2, 2, 1, 1)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(2, $task['position']); - $this->assertEquals(1, $task['swimlane_id']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(1, $task['swimlane_id']); - - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - // Move the task 5 to the last column - $this->assertTrue($tp->movePosition(1, 5, 4, 1, 0)); - - // Check tasks position - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(2, $task['position']); - $this->assertEquals(1, $task['swimlane_id']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(1, $task['swimlane_id']); - - $task = $tf->getById(3); - $this->assertEquals(3, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - $task = $tf->getById(4); - $this->assertEquals(4, $task['id']); - $this->assertEquals(1, $task['column_id']); - $this->assertEquals(2, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - $task = $tf->getById(5); - $this->assertEquals(5, $task['id']); - $this->assertEquals(4, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - } - - public function testEvents() - { - $tp = new TaskPositionModel($this->container); - $tc = new TaskCreationModel($this->container); - $tf = new TaskFinderModel($this->container); - $p = new ProjectModel($this->container); - $s = new SwimlaneModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); - $this->assertEquals(1, $s->create(array('project_id' => 1, 'name' => 'test 1'))); - - $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(2, $tc->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 2))); - - $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_COLUMN, array($this, 'onMoveColumn')); - $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_POSITION, array($this, 'onMovePosition')); - $this->container['dispatcher']->addListener(TaskModel::EVENT_MOVE_SWIMLANE, array($this, 'onMoveSwimlane')); - - // We move the task 1 to the column 2 - $this->assertTrue($tp->movePosition(1, 1, 2, 1)); - - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_COLUMN.'.TaskPositionTest::onMoveColumn', $called); - $this->assertEquals(1, count($called)); - - // We move the task 1 to the position 2 - $this->assertTrue($tp->movePosition(1, 1, 2, 2)); - - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(2, $task['position']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - - $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_POSITION.'.TaskPositionTest::onMovePosition', $called); - $this->assertEquals(2, count($called)); - - // Move to another swimlane - $this->assertTrue($tp->movePosition(1, 1, 3, 1, 1)); - - $task = $tf->getById(1); - $this->assertEquals(1, $task['id']); - $this->assertEquals(3, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(1, $task['swimlane_id']); - - $task = $tf->getById(2); - $this->assertEquals(2, $task['id']); - $this->assertEquals(2, $task['column_id']); - $this->assertEquals(1, $task['position']); - $this->assertEquals(0, $task['swimlane_id']); - - $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_SWIMLANE.'.TaskPositionTest::onMoveSwimlane', $called); - $this->assertEquals(3, count($called)); - } - - public function onMoveColumn($event) - { - $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); - - $event_data = $event->getAll(); - $this->assertNotEmpty($event_data); - $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals(1, $event_data['position']); - $this->assertEquals(2, $event_data['column_id']); - $this->assertEquals(1, $event_data['project_id']); - } - - public function onMovePosition($event) - { - $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); - - $event_data = $event->getAll(); - $this->assertNotEmpty($event_data); - $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals(2, $event_data['position']); - $this->assertEquals(2, $event_data['column_id']); - $this->assertEquals(1, $event_data['project_id']); - } - - public function onMoveSwimlane($event) - { - $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); - - $event_data = $event->getAll(); - $this->assertNotEmpty($event_data); - $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals(1, $event_data['position']); - $this->assertEquals(3, $event_data['column_id']); - $this->assertEquals(1, $event_data['project_id']); - $this->assertEquals(1, $event_data['swimlane_id']); - } -} diff --git a/tests/units/Model/TaskProjectMoveModelTest.php b/tests/units/Model/TaskProjectMoveModelTest.php index c4282638..52f61b28 100644 --- a/tests/units/Model/TaskProjectMoveModelTest.php +++ b/tests/units/Model/TaskProjectMoveModelTest.php @@ -24,7 +24,7 @@ class TaskProjectMoveModelTest extends Base $event_data = $event->getAll(); $this->assertNotEmpty($event_data); $this->assertEquals(1, $event_data['task_id']); - $this->assertEquals('test', $event_data['title']); + $this->assertEquals('test', $event_data['task']['title']); } public function testMoveAnotherProject() -- cgit v1.2.3 From b6119e7dee84869a619dedccd9c80df4422a4f5b Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 23 Jul 2016 14:05:15 -0400 Subject: Added internal task links to activity stream --- ChangeLog | 1 + app/Action/TaskAssignCategoryLink.php | 13 +- app/Action/TaskAssignColorLink.php | 10 +- app/Core/Base.php | 1 + app/EventBuilder/TaskLinkEventBuilder.php | 89 +++++++++++ app/Helper/HookHelper.php | 2 +- app/Job/TaskLinkEventJob.php | 45 ++++++ app/Model/NotificationModel.php | 39 ++--- app/Model/TaskLinkModel.php | 173 ++++++++++++--------- app/ServiceProvider/JobProvider.php | 5 + app/Subscriber/NotificationSubscriber.php | 3 + .../event/task_internal_link_create_update.php | 16 ++ app/Template/event/task_internal_link_delete.php | 16 ++ app/Template/notification/task_file_create.php | 2 +- .../task_internal_link_create_update.php | 11 ++ .../notification/task_internal_link_delete.php | 11 ++ tests/units/Action/TaskAssignCategoryLinkTest.php | 51 +++--- tests/units/Action/TaskAssignColorLinkTest.php | 45 ++++-- .../EventBuilder/TaskLinkEventBuilderTest.php | 70 +++++++++ tests/units/Job/TaskLinkEventJobTest.php | 65 ++++++++ tests/units/Model/NotificationModelTest.php | 39 ++--- tests/units/Model/TaskLinkModelTest.php | 28 ++++ tests/units/Notification/MailNotificationTest.php | 117 ++++++++++++++ tests/units/Notification/MailTest.php | 117 -------------- .../units/Notification/WebhookNotificationTest.php | 29 ++++ tests/units/Notification/WebhookTest.php | 29 ---- 26 files changed, 705 insertions(+), 322 deletions(-) create mode 100644 app/EventBuilder/TaskLinkEventBuilder.php create mode 100644 app/Job/TaskLinkEventJob.php create mode 100644 app/Template/event/task_internal_link_create_update.php create mode 100644 app/Template/event/task_internal_link_delete.php create mode 100644 app/Template/notification/task_internal_link_create_update.php create mode 100644 app/Template/notification/task_internal_link_delete.php create mode 100644 tests/units/EventBuilder/TaskLinkEventBuilderTest.php create mode 100644 tests/units/Job/TaskLinkEventJobTest.php create mode 100644 tests/units/Notification/MailNotificationTest.php delete mode 100644 tests/units/Notification/MailTest.php create mode 100644 tests/units/Notification/WebhookNotificationTest.php delete mode 100644 tests/units/Notification/WebhookTest.php (limited to 'app/Core') diff --git a/ChangeLog b/ChangeLog index a1e39436..ee57c86c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ Version 1.0.32 (unreleased) New features: * New automated action to close tasks without activity in a specific column +* Added internal task links to activity stream * Added new event for removed comments * Added search filter for task priority * Added the possibility to hide tasks in dashboard for a specific column diff --git a/app/Action/TaskAssignCategoryLink.php b/app/Action/TaskAssignCategoryLink.php index 6937edd1..d4a4c0ec 100644 --- a/app/Action/TaskAssignCategoryLink.php +++ b/app/Action/TaskAssignCategoryLink.php @@ -60,8 +60,10 @@ class TaskAssignCategoryLink extends Base public function getEventRequiredParameters() { return array( - 'task_id', - 'link_id', + 'task_link' => array( + 'task_id', + 'link_id', + ) ); } @@ -75,7 +77,7 @@ class TaskAssignCategoryLink extends Base public function doAction(array $data) { $values = array( - 'id' => $data['task_id'], + 'id' => $data['task_link']['task_id'], 'category_id' => $this->getParam('category_id'), ); @@ -91,9 +93,8 @@ class TaskAssignCategoryLink extends Base */ public function hasRequiredCondition(array $data) { - if ($data['link_id'] == $this->getParam('link_id')) { - $task = $this->taskFinderModel->getById($data['task_id']); - return empty($task['category_id']); + if ($data['task_link']['link_id'] == $this->getParam('link_id')) { + return empty($data['task']['category_id']); } return false; diff --git a/app/Action/TaskAssignColorLink.php b/app/Action/TaskAssignColorLink.php index 9ab5458b..9759f622 100644 --- a/app/Action/TaskAssignColorLink.php +++ b/app/Action/TaskAssignColorLink.php @@ -59,8 +59,10 @@ class TaskAssignColorLink extends Base public function getEventRequiredParameters() { return array( - 'task_id', - 'link_id', + 'task_link' => array( + 'task_id', + 'link_id', + ) ); } @@ -74,7 +76,7 @@ class TaskAssignColorLink extends Base public function doAction(array $data) { $values = array( - 'id' => $data['task_id'], + 'id' => $data['task_link']['task_id'], 'color_id' => $this->getParam('color_id'), ); @@ -90,6 +92,6 @@ class TaskAssignColorLink extends Base */ public function hasRequiredCondition(array $data) { - return $data['link_id'] == $this->getParam('link_id'); + return $data['task_link']['link_id'] == $this->getParam('link_id'); } } diff --git a/app/Core/Base.php b/app/Core/Base.php index 098bd880..20a2d391 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -154,6 +154,7 @@ use Pimple\Container; * @property \Kanboard\Job\SubtaskEventJob $subtaskEventJob * @property \Kanboard\Job\TaskEventJob $taskEventJob * @property \Kanboard\Job\TaskFileEventJob $taskFileEventJob + * @property \Kanboard\Job\TaskLinkEventJob $taskLinkEventJob * @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob * @property \Kanboard\Job\NotificationJob $notificationJob * @property \Psr\Log\LoggerInterface $logger diff --git a/app/EventBuilder/TaskLinkEventBuilder.php b/app/EventBuilder/TaskLinkEventBuilder.php new file mode 100644 index 00000000..8be5299f --- /dev/null +++ b/app/EventBuilder/TaskLinkEventBuilder.php @@ -0,0 +1,89 @@ +taskLinkId = $taskLinkId; + return $this; + } + + /** + * Build event data + * + * @access public + * @return TaskLinkEvent|null + */ + public function build() + { + $taskLink = $this->taskLinkModel->getById($this->taskLinkId); + + if (empty($taskLink)) { + $this->logger->debug(__METHOD__.': TaskLink not found'); + return null; + } + + return new TaskLinkEvent(array( + 'task_link' => $taskLink, + 'task' => $this->taskFinderModel->getDetails($taskLink['task_id']), + )); + } + + /** + * Get event title with author + * + * @access public + * @param string $author + * @param string $eventName + * @param array $eventData + * @return string + */ + public function buildTitleWithAuthor($author, $eventName, array $eventData) + { + if ($eventName === TaskLinkModel::EVENT_CREATE_UPDATE) { + return e('%s set a new internal link for the task #%d', $author, $eventData['task']['id']); + } elseif ($eventName === TaskLinkModel::EVENT_DELETE) { + return e('%s removed an internal link for the task #%d', $author, $eventData['task']['id']); + } + + return ''; + } + + /** + * Get event title without author + * + * @access public + * @param string $eventName + * @param array $eventData + * @return string + */ + public function buildTitleWithoutAuthor($eventName, array $eventData) + { + if ($eventName === TaskLinkModel::EVENT_CREATE_UPDATE) { + return e('A new internal link for the task #%d have been defined', $eventData['task']['id']); + } elseif ($eventName === TaskLinkModel::EVENT_DELETE) { + return e('Internal link removed for the task #%d', $eventData['task']['id']); + } + + return ''; + } +} diff --git a/app/Helper/HookHelper.php b/app/Helper/HookHelper.php index 2d13ebcc..cb4dc1ef 100644 --- a/app/Helper/HookHelper.php +++ b/app/Helper/HookHelper.php @@ -56,7 +56,7 @@ class HookHelper extends Base * @access public * @param string $hook * @param string $template - * @return \Kanboard\Helper\Hook + * @return $this */ public function attach($hook, $template) { diff --git a/app/Job/TaskLinkEventJob.php b/app/Job/TaskLinkEventJob.php new file mode 100644 index 00000000..669608ad --- /dev/null +++ b/app/Job/TaskLinkEventJob.php @@ -0,0 +1,45 @@ +jobParams = array($taskLinkId, $eventName); + return $this; + } + + /** + * Execute job + * + * @param int $taskLinkId + * @param string $eventName + * @return $this + */ + public function execute($taskLinkId, $eventName) + { + $event = TaskLinkEventBuilder::getInstance($this->container) + ->withTaskLinkId($taskLinkId) + ->build(); + + if ($event !== null) { + $this->dispatcher->dispatch($eventName, $event); + } + } +} diff --git a/app/Model/NotificationModel.php b/app/Model/NotificationModel.php index 925d646e..39c1f581 100644 --- a/app/Model/NotificationModel.php +++ b/app/Model/NotificationModel.php @@ -3,6 +3,7 @@ namespace Kanboard\Model; use Kanboard\Core\Base; +use Kanboard\EventBuilder\TaskLinkEventBuilder; /** * Notification @@ -85,7 +86,9 @@ class NotificationModel extends Base case CommentModel::EVENT_USER_MENTION: return e('%s mentioned you in a comment on the task #%d', $event_author, $event_data['task']['id']); default: - return e('Notification'); + return TaskLinkEventBuilder::getInstance($this->container) + ->buildTitleWithAuthor($event_author, $event_name, $event_data) ?: + e('Notification'); } } @@ -138,7 +141,9 @@ class NotificationModel extends Base case CommentModel::EVENT_USER_MENTION: return e('You were mentioned in a comment on the task #%d', $event_data['task']['id']); default: - return e('Notification'); + return TaskLinkEventBuilder::getInstance($this->container) + ->buildTitleWithoutAuthor($event_name, $event_data) ?: + e('Notification'); } } @@ -152,32 +157,10 @@ class NotificationModel extends Base */ public function getTaskIdFromEvent($event_name, array $event_data) { - switch ($event_name) { - case TaskFileModel::EVENT_CREATE: - return $event_data['file']['task_id']; - case CommentModel::EVENT_CREATE: - case CommentModel::EVENT_UPDATE: - case CommentModel::EVENT_DELETE: - return $event_data['comment']['task_id']; - case SubtaskModel::EVENT_CREATE: - case SubtaskModel::EVENT_UPDATE: - case SubtaskModel::EVENT_DELETE: - return $event_data['subtask']['task_id']; - case TaskModel::EVENT_CREATE: - case TaskModel::EVENT_UPDATE: - case TaskModel::EVENT_CLOSE: - case TaskModel::EVENT_OPEN: - case TaskModel::EVENT_MOVE_COLUMN: - case TaskModel::EVENT_MOVE_POSITION: - case TaskModel::EVENT_MOVE_SWIMLANE: - case TaskModel::EVENT_ASSIGNEE_CHANGE: - case CommentModel::EVENT_USER_MENTION: - case TaskModel::EVENT_USER_MENTION: - return $event_data['task']['id']; - case TaskModel::EVENT_OVERDUE: - return $event_data['tasks'][0]['id']; - default: - return 0; + if ($event_name === TaskModel::EVENT_OVERDUE) { + return $event_data['tasks'][0]['id']; } + + return isset($event_data['task']['id']) ? $event_data['task']['id'] : 0; } } diff --git a/app/Model/TaskLinkModel.php b/app/Model/TaskLinkModel.php index 09978eae..e8d3c5df 100644 --- a/app/Model/TaskLinkModel.php +++ b/app/Model/TaskLinkModel.php @@ -3,7 +3,6 @@ namespace Kanboard\Model; use Kanboard\Core\Base; -use Kanboard\Event\TaskLinkEvent; /** * TaskLink model @@ -26,7 +25,8 @@ class TaskLinkModel extends Base * * @var string */ - const EVENT_CREATE_UPDATE = 'tasklink.create_update'; + const EVENT_CREATE_UPDATE = 'task_internal_link.create_update'; + const EVENT_DELETE = 'task_internal_link.delete'; /** * Get projectId from $task_link_id @@ -53,7 +53,19 @@ class TaskLinkModel extends Base */ public function getById($task_link_id) { - return $this->db->table(self::TABLE)->eq('id', $task_link_id)->findOne(); + return $this->db + ->table(self::TABLE) + ->columns( + self::TABLE.'.id', + self::TABLE.'.opposite_task_id', + self::TABLE.'.task_id', + self::TABLE.'.link_id', + LinkModel::TABLE.'.label', + LinkModel::TABLE.'.opposite_id AS opposite_link_id' + ) + ->eq(self::TABLE.'.id', $task_link_id) + ->join(LinkModel::TABLE, 'id', 'link_id') + ->findOne(); } /** @@ -139,20 +151,6 @@ class TaskLinkModel extends Base return $result; } - /** - * Publish events - * - * @access private - * @param array $events - */ - private function fireEvents(array $events) - { - foreach ($events as $event) { - $event['project_id'] = $this->taskFinderModel->getProjectId($event['task_id']); - $this->container['dispatcher']->dispatch(self::EVENT_CREATE_UPDATE, new TaskLinkEvent($event)); - } - } - /** * Create a new link * @@ -160,42 +158,25 @@ class TaskLinkModel extends Base * @param integer $task_id Task id * @param integer $opposite_task_id Opposite task id * @param integer $link_id Link id - * @return integer Task link id + * @return integer|boolean */ public function create($task_id, $opposite_task_id, $link_id) { - $events = array(); $this->db->startTransaction(); - // Get opposite link $opposite_link_id = $this->linkModel->getOppositeLinkId($link_id); + $task_link_id1 = $this->createTaskLink($task_id, $opposite_task_id, $link_id); + $task_link_id2 = $this->createTaskLink($opposite_task_id, $task_id, $opposite_link_id); - $values = array( - 'task_id' => $task_id, - 'opposite_task_id' => $opposite_task_id, - 'link_id' => $link_id, - ); - - // Create the original task link - $this->db->table(self::TABLE)->insert($values); - $task_link_id = $this->db->getLastId(); - $events[] = $values; - - // Create the opposite task link - $values = array( - 'task_id' => $opposite_task_id, - 'opposite_task_id' => $task_id, - 'link_id' => $opposite_link_id, - ); - - $this->db->table(self::TABLE)->insert($values); - $events[] = $values; + if ($task_link_id1 === false || $task_link_id2 === false) { + $this->db->cancelTransaction(); + return false; + } $this->db->closeTransaction(); + $this->fireEvents(array($task_link_id1, $task_link_id2), self::EVENT_CREATE_UPDATE); - $this->fireEvents($events); - - return (int) $task_link_id; + return $task_link_id1; } /** @@ -210,46 +191,24 @@ class TaskLinkModel extends Base */ public function update($task_link_id, $task_id, $opposite_task_id, $link_id) { - $events = array(); $this->db->startTransaction(); - // Get original task link $task_link = $this->getById($task_link_id); - - // Find opposite task link $opposite_task_link = $this->getOppositeTaskLink($task_link); - - // Get opposite link $opposite_link_id = $this->linkModel->getOppositeLinkId($link_id); - // Update the original task link - $values = array( - 'task_id' => $task_id, - 'opposite_task_id' => $opposite_task_id, - 'link_id' => $link_id, - ); - - $rs1 = $this->db->table(self::TABLE)->eq('id', $task_link_id)->update($values); - $events[] = $values; + $result1 = $this->updateTaskLink($task_link_id, $task_id, $opposite_task_id, $link_id); + $result2 = $this->updateTaskLink($opposite_task_link['id'], $opposite_task_id, $task_id, $opposite_link_id); - // Update the opposite link - $values = array( - 'task_id' => $opposite_task_id, - 'opposite_task_id' => $task_id, - 'link_id' => $opposite_link_id, - ); - - $rs2 = $this->db->table(self::TABLE)->eq('id', $opposite_task_link['id'])->update($values); - $events[] = $values; + if ($result1 === false || $result2 === false) { + $this->db->cancelTransaction(); + return false; + } $this->db->closeTransaction(); + $this->fireEvents(array($task_link_id, $opposite_task_link['id']), self::EVENT_CREATE_UPDATE); - if ($rs1 && $rs2) { - $this->fireEvents($events); - return true; - } - - return false; + return true; } /** @@ -261,21 +220,83 @@ class TaskLinkModel extends Base */ public function remove($task_link_id) { + $this->taskLinkEventJob->execute($task_link_id, self::EVENT_DELETE); + $this->db->startTransaction(); $link = $this->getById($task_link_id); $link_id = $this->linkModel->getOppositeLinkId($link['link_id']); - $this->db->table(self::TABLE)->eq('id', $task_link_id)->remove(); + $result1 = $this->db + ->table(self::TABLE) + ->eq('id', $task_link_id) + ->remove(); - $this->db + $result2 = $this->db ->table(self::TABLE) ->eq('opposite_task_id', $link['task_id']) ->eq('task_id', $link['opposite_task_id']) - ->eq('link_id', $link_id)->remove(); + ->eq('link_id', $link_id) + ->remove(); + + if ($result1 === false || $result2 === false) { + $this->db->cancelTransaction(); + return false; + } $this->db->closeTransaction(); return true; } + + /** + * Publish events + * + * @access protected + * @param integer[] $task_link_ids + * @param string $eventName + */ + protected function fireEvents(array $task_link_ids, $eventName) + { + foreach ($task_link_ids as $task_link_id) { + $this->queueManager->push($this->taskLinkEventJob->withParams($task_link_id, $eventName)); + } + } + + /** + * Create task link + * + * @access protected + * @param integer $task_id + * @param integer $opposite_task_id + * @param integer $link_id + * @return integer|boolean + */ + protected function createTaskLink($task_id, $opposite_task_id, $link_id) + { + return $this->db->table(self::TABLE)->persist(array( + 'task_id' => $task_id, + 'opposite_task_id' => $opposite_task_id, + 'link_id' => $link_id, + )); + } + + /** + * Update task link + * + * @access protected + * @param integer $task_link_id + * @param integer $task_id + * @param integer $opposite_task_id + * @param integer $link_id + * @return boolean + */ + protected function updateTaskLink($task_link_id, $task_id, $opposite_task_id, $link_id) + { + return $this->db->table(self::TABLE)->eq('id', $task_link_id)->update(array( + 'task_id' => $task_id, + 'opposite_task_id' => $opposite_task_id, + 'link_id' => $link_id, + )); + } } diff --git a/app/ServiceProvider/JobProvider.php b/app/ServiceProvider/JobProvider.php index c7f323f1..5b42794b 100644 --- a/app/ServiceProvider/JobProvider.php +++ b/app/ServiceProvider/JobProvider.php @@ -8,6 +8,7 @@ use Kanboard\Job\ProjectFileEventJob; use Kanboard\Job\SubtaskEventJob; use Kanboard\Job\TaskEventJob; use Kanboard\Job\TaskFileEventJob; +use Kanboard\Job\TaskLinkEventJob; use Pimple\Container; use Pimple\ServiceProviderInterface; @@ -44,6 +45,10 @@ class JobProvider implements ServiceProviderInterface return new TaskFileEventJob($c); }); + $container['taskLinkEventJob'] = $container->factory(function ($c) { + return new TaskLinkEventJob($c); + }); + $container['projectFileEventJob'] = $container->factory(function ($c) { return new ProjectFileEventJob($c); }); diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php index 7de24e49..7cc68b26 100644 --- a/app/Subscriber/NotificationSubscriber.php +++ b/app/Subscriber/NotificationSubscriber.php @@ -3,6 +3,7 @@ namespace Kanboard\Subscriber; use Kanboard\Event\GenericEvent; +use Kanboard\Model\TaskLinkModel; use Kanboard\Model\TaskModel; use Kanboard\Model\CommentModel; use Kanboard\Model\SubtaskModel; @@ -31,6 +32,8 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn CommentModel::EVENT_DELETE => 'handleEvent', CommentModel::EVENT_USER_MENTION => 'handleEvent', TaskFileModel::EVENT_CREATE => 'handleEvent', + TaskLinkModel::EVENT_CREATE_UPDATE => 'handleEvent', + TaskLinkModel::EVENT_DELETE => 'handleEvent', ); } diff --git a/app/Template/event/task_internal_link_create_update.php b/app/Template/event/task_internal_link_create_update.php new file mode 100644 index 00000000..de257977 --- /dev/null +++ b/app/Template/event/task_internal_link_create_update.php @@ -0,0 +1,16 @@ +

    + text->e($author), + $this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) + ) ?> + dt->datetime($date_creation) ?> +

    +
    +

    + url->link(t('#%d', $task_link['opposite_task_id']), 'TaskViewController', 'show', array('task_id' => $task_link['opposite_task_id'])), + $this->text->e($task_link['label']) + ) ?> +

    +
    diff --git a/app/Template/event/task_internal_link_delete.php b/app/Template/event/task_internal_link_delete.php new file mode 100644 index 00000000..e537bf81 --- /dev/null +++ b/app/Template/event/task_internal_link_delete.php @@ -0,0 +1,16 @@ +

    + text->e($author), + $this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) + ) ?> + dt->datetime($date_creation) ?> +

    +
    +

    + text->e($task_link['label']), + $this->url->link(t('#%d', $task_link['opposite_task_id']), 'TaskViewController', 'show', array('task_id' => $task_link['opposite_task_id'])) + ) ?> +

    +
    diff --git a/app/Template/notification/task_file_create.php b/app/Template/notification/task_file_create.php index feab8dd2..c19f7279 100644 --- a/app/Template/notification/task_file_create.php +++ b/app/Template/notification/task_file_create.php @@ -2,4 +2,4 @@

    -render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> \ No newline at end of file +render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> diff --git a/app/Template/notification/task_internal_link_create_update.php b/app/Template/notification/task_internal_link_create_update.php new file mode 100644 index 00000000..73cad84d --- /dev/null +++ b/app/Template/notification/task_internal_link_create_update.php @@ -0,0 +1,11 @@ +

    text->e($task['title']) ?> (#)

    + +

    + url->link(t('#%d', $task_link['opposite_task_id']), 'TaskViewController', 'show', array('task_id' => $task_link['opposite_task_id'])), + $this->text->e($task_link['label']) + ) ?> +

    + +render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> diff --git a/app/Template/notification/task_internal_link_delete.php b/app/Template/notification/task_internal_link_delete.php new file mode 100644 index 00000000..bb54e0a7 --- /dev/null +++ b/app/Template/notification/task_internal_link_delete.php @@ -0,0 +1,11 @@ +

    text->e($task['title']) ?> (#)

    + +

    + text->e($task_link['label']), + $this->url->link(t('#%d', $task_link['opposite_task_id']), 'TaskViewController', 'show', array('task_id' => $task_link['opposite_task_id'])) + ) ?> +

    + +render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> diff --git a/tests/units/Action/TaskAssignCategoryLinkTest.php b/tests/units/Action/TaskAssignCategoryLinkTest.php index d7e68f72..b9d7e9d9 100644 --- a/tests/units/Action/TaskAssignCategoryLinkTest.php +++ b/tests/units/Action/TaskAssignCategoryLinkTest.php @@ -2,12 +2,12 @@ require_once __DIR__.'/../Base.php'; +use Kanboard\EventBuilder\TaskLinkEventBuilder; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; use Kanboard\Model\TaskLinkModel; use Kanboard\Model\CategoryModel; -use Kanboard\Event\TaskLinkEvent; use Kanboard\Action\TaskAssignCategoryLink; class TaskAssignCategoryLinkTest extends Base @@ -18,6 +18,7 @@ class TaskAssignCategoryLinkTest extends Base $taskFinderModel = new TaskFinderModel($this->container); $projectModel = new ProjectModel($this->container); $categoryModel = new CategoryModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $action = new TaskAssignCategoryLink($this->container); $action->setProjectId(1); @@ -27,13 +28,12 @@ class TaskAssignCategoryLinkTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); $this->assertEquals(1, $categoryModel->create(array('name' => 'C1', 'project_id' => 1))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 2)); - $event = new TaskLinkEvent(array( - 'project_id' => 1, - 'task_id' => 1, - 'opposite_task_id' => 2, - 'link_id' => 2, - )); + $event = TaskLinkEventBuilder::getInstance($this->container) + ->withTaskLinkId(1) + ->build(); $this->assertTrue($action->execute($event, TaskLinkModel::EVENT_CREATE_UPDATE)); @@ -44,51 +44,58 @@ class TaskAssignCategoryLinkTest extends Base public function testWhenLinkDontMatch() { $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); $projectModel = new ProjectModel($this->container); $categoryModel = new CategoryModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $action = new TaskAssignCategoryLink($this->container); $action->setProjectId(1); $action->setParam('category_id', 1); - $action->setParam('link_id', 1); + $action->setParam('link_id', 2); $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); $this->assertEquals(1, $categoryModel->create(array('name' => 'C1', 'project_id' => 1))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); - $event = new TaskLinkEvent(array( - 'project_id' => 1, - 'task_id' => 1, - 'opposite_task_id' => 2, - 'link_id' => 2, - )); + $event = TaskLinkEventBuilder::getInstance($this->container) + ->withTaskLinkId(1) + ->build(); $this->assertFalse($action->execute($event, TaskLinkModel::EVENT_CREATE_UPDATE)); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(0, $task['category_id']); } public function testThatExistingCategoryWillNotChange() { $taskCreationModel = new TaskCreationModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); $projectModel = new ProjectModel($this->container); $categoryModel = new CategoryModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $action = new TaskAssignCategoryLink($this->container); $action->setProjectId(1); - $action->setParam('category_id', 2); + $action->setParam('category_id', 1); $action->setParam('link_id', 2); $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); $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('title' => 'T1', 'project_id' => 1, 'category_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 2)); - $event = new TaskLinkEvent(array( - 'project_id' => 1, - 'task_id' => 1, - 'opposite_task_id' => 2, - 'link_id' => 2, - )); + $event = TaskLinkEventBuilder::getInstance($this->container) + ->withTaskLinkId(1) + ->build(); $this->assertFalse($action->execute($event, TaskLinkModel::EVENT_CREATE_UPDATE)); + + $task = $taskFinderModel->getById(1); + $this->assertEquals(1, $task['category_id']); } } diff --git a/tests/units/Action/TaskAssignColorLinkTest.php b/tests/units/Action/TaskAssignColorLinkTest.php index 07d0969b..27364bc9 100644 --- a/tests/units/Action/TaskAssignColorLinkTest.php +++ b/tests/units/Action/TaskAssignColorLinkTest.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../Base.php'; -use Kanboard\Event\GenericEvent; +use Kanboard\EventBuilder\TaskLinkEventBuilder; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\TaskFinderModel; use Kanboard\Model\ProjectModel; @@ -13,42 +13,55 @@ class TaskAssignColorLinkTest extends Base { public function testChangeColor() { - $projectModel = new ProjectModel($this->container); $taskCreationModel = new TaskCreationModel($this->container); $taskFinderModel = new TaskFinderModel($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' => 1)); + $projectModel = new ProjectModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $action = new TaskAssignColorLink($this->container); $action->setProjectId(1); + $action->setParam('link_id', 2); $action->setParam('color_id', 'red'); - $action->setParam('link_id', 1); + + $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 2)); + + $event = TaskLinkEventBuilder::getInstance($this->container) + ->withTaskLinkId(1) + ->build(); $this->assertTrue($action->execute($event, TaskLinkModel::EVENT_CREATE_UPDATE)); $task = $taskFinderModel->getById(1); - $this->assertNotEmpty($task); $this->assertEquals('red', $task['color_id']); } public function testWithWrongLink() { - $projectModel = new ProjectModel($this->container); $taskCreationModel = new TaskCreationModel($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)); + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $action = new TaskAssignColorLink($this->container); $action->setProjectId(1); + $action->setParam('link_id', 2); $action->setParam('color_id', 'red'); - $action->setParam('link_id', 1); + + $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'T1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); + + $event = TaskLinkEventBuilder::getInstance($this->container) + ->withTaskLinkId(1) + ->build(); $this->assertFalse($action->execute($event, TaskLinkModel::EVENT_CREATE_UPDATE)); + + $task = $taskFinderModel->getById(1); + $this->assertEquals('yellow', $task['color_id']); } } diff --git a/tests/units/EventBuilder/TaskLinkEventBuilderTest.php b/tests/units/EventBuilder/TaskLinkEventBuilderTest.php new file mode 100644 index 00000000..7364d651 --- /dev/null +++ b/tests/units/EventBuilder/TaskLinkEventBuilderTest.php @@ -0,0 +1,70 @@ +container); + $taskLinkEventBuilder->withTaskLinkId(42); + $this->assertNull($taskLinkEventBuilder->build()); + } + + public function testBuild() + { + $taskLinkModel = new TaskLinkModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskLinkEventBuilder = new TaskLinkEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'task 1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'task 2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); + + $event = $taskLinkEventBuilder->withTaskLinkId(1)->build(); + + $this->assertInstanceOf('Kanboard\Event\TaskLinkEvent', $event); + $this->assertNotEmpty($event['task_link']); + $this->assertNotEmpty($event['task']); + } + + public function testBuildTitle() + { + $taskLinkModel = new TaskLinkModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskLinkEventBuilder = new TaskLinkEventBuilder($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'task 1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'task 2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); + + $eventData = $taskLinkEventBuilder->withTaskLinkId(1)->build(); + + $title = $taskLinkEventBuilder->buildTitleWithAuthor('Foobar', TaskLinkModel::EVENT_CREATE_UPDATE, $eventData->getAll()); + $this->assertEquals('Foobar set a new internal link for the task #1', $title); + + $title = $taskLinkEventBuilder->buildTitleWithAuthor('Foobar', TaskLinkModel::EVENT_DELETE, $eventData->getAll()); + $this->assertEquals('Foobar removed an internal link for the task #1', $title); + + $title = $taskLinkEventBuilder->buildTitleWithAuthor('Foobar', 'not found', $eventData->getAll()); + $this->assertSame('', $title); + + $title = $taskLinkEventBuilder->buildTitleWithoutAuthor(TaskLinkModel::EVENT_CREATE_UPDATE, $eventData->getAll()); + $this->assertEquals('A new internal link for the task #1 have been defined', $title); + + $title = $taskLinkEventBuilder->buildTitleWithoutAuthor(TaskLinkModel::EVENT_DELETE, $eventData->getAll()); + $this->assertEquals('Internal link removed for the task #1', $title); + + $title = $taskLinkEventBuilder->buildTitleWithoutAuthor('not found', $eventData->getAll()); + $this->assertSame('', $title); + } +} diff --git a/tests/units/Job/TaskLinkEventJobTest.php b/tests/units/Job/TaskLinkEventJobTest.php new file mode 100644 index 00000000..1949316a --- /dev/null +++ b/tests/units/Job/TaskLinkEventJobTest.php @@ -0,0 +1,65 @@ +container); + $taskLinkEventJob->withParams(123, 'foobar'); + + $this->assertSame(array(123, 'foobar'), $taskLinkEventJob->getJobParams()); + } + + public function testWithMissingLink() + { + $this->container['dispatcher']->addListener(TaskLinkModel::EVENT_CREATE_UPDATE, function() {}); + + $taskLinkEventJob = new TaskLinkEventJob($this->container); + $taskLinkEventJob->execute(42, TaskLinkModel::EVENT_CREATE_UPDATE); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertEmpty($called); + } + + public function testTriggerCreationEvents() + { + $this->container['dispatcher']->addListener(TaskLinkModel::EVENT_CREATE_UPDATE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'task 1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'task 2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskLinkModel::EVENT_CREATE_UPDATE.'.closure', $called); + } + + public function testTriggerDeleteEvents() + { + $this->container['dispatcher']->addListener(TaskLinkModel::EVENT_DELETE, function() {}); + + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'task 1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'task 2', 'project_id' => 1))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); + $this->assertTrue($taskLinkModel->remove(1)); + + $called = $this->container['dispatcher']->getCalledListeners(); + $this->assertArrayHasKey(TaskLinkModel::EVENT_DELETE.'.closure', $called); + } +} diff --git a/tests/units/Model/NotificationModelTest.php b/tests/units/Model/NotificationModelTest.php index 889f3349..0bd9db6e 100644 --- a/tests/units/Model/NotificationModelTest.php +++ b/tests/units/Model/NotificationModelTest.php @@ -7,6 +7,7 @@ use Kanboard\Model\TaskCreationModel; use Kanboard\Model\SubtaskModel; use Kanboard\Model\CommentModel; use Kanboard\Model\TaskFileModel; +use Kanboard\Model\TaskLinkModel; use Kanboard\Model\TaskModel; use Kanboard\Model\ProjectModel; use Kanboard\Model\NotificationModel; @@ -23,47 +24,38 @@ class NotificationModelTest extends Base $subtaskModel = new SubtaskModel($this->container); $commentModel = new CommentModel($this->container); $taskFileModel = new TaskFileModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); $this->assertEquals(1, $subtaskModel->create(array('title' => 'test', 'task_id' => 1))); $this->assertEquals(1, $commentModel->create(array('comment' => 'test', 'task_id' => 1, 'user_id' => 1))); $this->assertEquals(1, $taskFileModel->create(1, 'test', 'blah', 123)); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); $task = $taskFinderModel->getDetails(1); $subtask = $subtaskModel->getById(1, true); $comment = $commentModel->getById(1); $file = $commentModel->getById(1); + $tasklink = $taskLinkModel->getById(1); - $this->assertNotEmpty($task); - $this->assertNotEmpty($subtask); - $this->assertNotEmpty($comment); - $this->assertNotEmpty($file); - - foreach (NotificationSubscriber::getSubscribedEvents() as $event_name => $values) { - $title = $notificationModel->getTitleWithoutAuthor($event_name, array( - 'task' => $task, - 'comment' => $comment, - 'subtask' => $subtask, - 'file' => $file, - 'changes' => array() - )); - - $this->assertNotEmpty($title); - - $title = $notificationModel->getTitleWithAuthor('foobar', $event_name, array( + foreach (NotificationSubscriber::getSubscribedEvents() as $eventName => $values) { + $eventData = array( 'task' => $task, 'comment' => $comment, 'subtask' => $subtask, 'file' => $file, + 'task_link' => $tasklink, 'changes' => array() - )); + ); - $this->assertNotEmpty($title); + $this->assertNotEmpty($notificationModel->getTitleWithoutAuthor($eventName, $eventData)); + $this->assertNotEmpty($notificationModel->getTitleWithAuthor('Foobar', $eventName, $eventData)); } $this->assertNotEmpty($notificationModel->getTitleWithoutAuthor(TaskModel::EVENT_OVERDUE, array('tasks' => array(array('id' => 1))))); - $this->assertNotEmpty($notificationModel->getTitleWithoutAuthor('unkown', array())); + $this->assertNotEmpty($notificationModel->getTitleWithoutAuthor('unknown', array())); } public function testGetTaskIdFromEvent() @@ -75,6 +67,7 @@ class NotificationModelTest extends Base $subtaskModel = new SubtaskModel($this->container); $commentModel = new CommentModel($this->container); $taskFileModel = new TaskFileModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); @@ -86,18 +79,20 @@ class NotificationModelTest extends Base $subtask = $subtaskModel->getById(1, true); $comment = $commentModel->getById(1); $file = $commentModel->getById(1); + $tasklink = $taskLinkModel->getById(1); $this->assertNotEmpty($task); $this->assertNotEmpty($subtask); $this->assertNotEmpty($comment); $this->assertNotEmpty($file); - foreach (NotificationSubscriber::getSubscribedEvents() as $event_name => $values) { - $task_id = $notificationModel->getTaskIdFromEvent($event_name, array( + foreach (NotificationSubscriber::getSubscribedEvents() as $eventName => $values) { + $task_id = $notificationModel->getTaskIdFromEvent($eventName, array( 'task' => $task, 'comment' => $comment, 'subtask' => $subtask, 'file' => $file, + 'task_link' => $tasklink, 'changes' => array() )); diff --git a/tests/units/Model/TaskLinkModelTest.php b/tests/units/Model/TaskLinkModelTest.php index 78590891..01a7888b 100644 --- a/tests/units/Model/TaskLinkModelTest.php +++ b/tests/units/Model/TaskLinkModelTest.php @@ -9,6 +9,34 @@ use Kanboard\Model\ProjectModel; class TaskLinkModelTest extends Base { + public function testGeyById() + { + $taskLinkModel = new TaskLinkModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A'))); + $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B'))); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 6)); + + $taskLink = $taskLinkModel->getById(1); + $this->assertEquals(1, $taskLink['id']); + $this->assertEquals(1, $taskLink['task_id']); + $this->assertEquals(2, $taskLink['opposite_task_id']); + $this->assertEquals(6, $taskLink['link_id']); + $this->assertEquals(7, $taskLink['opposite_link_id']); + $this->assertEquals('is a child of', $taskLink['label']); + + $taskLink = $taskLinkModel->getById(2); + $this->assertEquals(2, $taskLink['id']); + $this->assertEquals(2, $taskLink['task_id']); + $this->assertEquals(1, $taskLink['opposite_task_id']); + $this->assertEquals(7, $taskLink['link_id']); + $this->assertEquals(6, $taskLink['opposite_link_id']); + $this->assertEquals('is a parent of', $taskLink['label']); + } + // Check postgres issue: "Cardinality violation: 7 ERROR: more than one row returned by a subquery used as an expression" public function testGetTaskWithMultipleMilestoneLink() { diff --git a/tests/units/Notification/MailNotificationTest.php b/tests/units/Notification/MailNotificationTest.php new file mode 100644 index 00000000..6579d9bc --- /dev/null +++ b/tests/units/Notification/MailNotificationTest.php @@ -0,0 +1,117 @@ +container); + $projectModel = new ProjectModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $commentModel = new CommentModel($this->container); + $fileModel = new TaskFileModel($this->container); + $taskLinkModel = new TaskLinkModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'test', 'task_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('comment' => 'test', 'task_id' => 1, 'user_id' => 1))); + $this->assertEquals(1, $fileModel->create(1, 'test', 'blah', 123)); + $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); + + $task = $taskFinderModel->getDetails(1); + $subtask = $subtaskModel->getById(1, true); + $comment = $commentModel->getById(1); + $file = $commentModel->getById(1); + $tasklink = $taskLinkModel->getById(1); + + $this->assertNotEmpty($task); + $this->assertNotEmpty($subtask); + $this->assertNotEmpty($comment); + $this->assertNotEmpty($file); + + foreach (NotificationSubscriber::getSubscribedEvents() as $eventName => $values) { + $eventData = array( + 'task' => $task, + 'comment' => $comment, + 'subtask' => $subtask, + 'file' => $file, + 'task_link' => $tasklink, + 'changes' => array() + ); + $this->assertNotEmpty($mailNotification->getMailContent($eventName, $eventData)); + $this->assertNotEmpty($mailNotification->getMailSubject($eventName, $eventData)); + } + } + + public function testSendWithEmailAddress() + { + $mailNotification = new MailNotification($this->container); + $projectModel = new ProjectModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $userModel = new UserModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertTrue($userModel->update(array('id' => 1, 'email' => 'test@localhost'))); + + $this->container['emailClient'] = $this + ->getMockBuilder('\Kanboard\Core\Mail\Client') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('send')) + ->getMock(); + + $this->container['emailClient'] + ->expects($this->once()) + ->method('send') + ->with( + $this->equalTo('test@localhost'), + $this->equalTo('admin'), + $this->equalTo('[test][New task] test (#1)'), + $this->stringContains('test') + ); + + $mailNotification->notifyUser($userModel->getById(1), TaskModel::EVENT_CREATE, array('task' => $taskFinderModel->getDetails(1))); + } + + public function testSendWithoutEmailAddress() + { + $mailNotification = new MailNotification($this->container); + $projectModel = new ProjectModel($this->container); + $taskFinderModel = new TaskFinderModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $userModel = new UserModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + + $this->container['emailClient'] = $this + ->getMockBuilder('\Kanboard\Core\Mail\Client') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('send')) + ->getMock(); + + $this->container['emailClient'] + ->expects($this->never()) + ->method('send'); + + $mailNotification->notifyUser($userModel->getById(1), TaskModel::EVENT_CREATE, array('task' => $taskFinderModel->getDetails(1))); + } +} diff --git a/tests/units/Notification/MailTest.php b/tests/units/Notification/MailTest.php deleted file mode 100644 index 9f077ac8..00000000 --- a/tests/units/Notification/MailTest.php +++ /dev/null @@ -1,117 +0,0 @@ -container); - $p = new ProjectModel($this->container); - $tf = new TaskFinderModel($this->container); - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $c = new CommentModel($this->container); - $f = new TaskFileModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'test', 'task_id' => 1))); - $this->assertEquals(1, $c->create(array('comment' => 'test', 'task_id' => 1, 'user_id' => 1))); - $this->assertEquals(1, $f->create(1, 'test', 'blah', 123)); - - $task = $tf->getDetails(1); - $subtask = $s->getById(1, true); - $comment = $c->getById(1); - $file = $c->getById(1); - - $this->assertNotEmpty($task); - $this->assertNotEmpty($subtask); - $this->assertNotEmpty($comment); - $this->assertNotEmpty($file); - - foreach (NotificationSubscriber::getSubscribedEvents() as $event => $values) { - $this->assertNotEmpty($en->getMailContent($event, array( - 'task' => $task, - 'comment' => $comment, - 'subtask' => $subtask, - 'file' => $file, - 'changes' => array()) - )); - - $this->assertNotEmpty($en->getMailSubject($event, array( - 'task' => $task, - 'comment' => $comment, - 'subtask' => $subtask, - 'file' => $file, - 'changes' => array()) - )); - } - } - - public function testSendWithEmailAddress() - { - $en = new MailNotification($this->container); - $p = new ProjectModel($this->container); - $tf = new TaskFinderModel($this->container); - $tc = new TaskCreationModel($this->container); - $u = new UserModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - $this->assertTrue($u->update(array('id' => 1, 'email' => 'test@localhost'))); - - $this->container['emailClient'] = $this - ->getMockBuilder('\Kanboard\Core\Mail\Client') - ->setConstructorArgs(array($this->container)) - ->setMethods(array('send')) - ->getMock(); - - $this->container['emailClient'] - ->expects($this->once()) - ->method('send') - ->with( - $this->equalTo('test@localhost'), - $this->equalTo('admin'), - $this->equalTo('[test][New task] test (#1)'), - $this->stringContains('test') - ); - - $en->notifyUser($u->getById(1), TaskModel::EVENT_CREATE, array('task' => $tf->getDetails(1))); - } - - public function testSendWithoutEmailAddress() - { - $en = new MailNotification($this->container); - $p = new ProjectModel($this->container); - $tf = new TaskFinderModel($this->container); - $tc = new TaskCreationModel($this->container); - $u = new UserModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - - $this->container['emailClient'] = $this - ->getMockBuilder('\Kanboard\Core\Mail\Client') - ->setConstructorArgs(array($this->container)) - ->setMethods(array('send')) - ->getMock(); - - $this->container['emailClient'] - ->expects($this->never()) - ->method('send'); - - $en->notifyUser($u->getById(1), TaskModel::EVENT_CREATE, array('task' => $tf->getDetails(1))); - } -} diff --git a/tests/units/Notification/WebhookNotificationTest.php b/tests/units/Notification/WebhookNotificationTest.php new file mode 100644 index 00000000..6fbc349c --- /dev/null +++ b/tests/units/Notification/WebhookNotificationTest.php @@ -0,0 +1,29 @@ +container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $this->container['dispatcher']->addSubscriber(new NotificationSubscriber($this->container)); + + $configModel->save(array('webhook_url' => 'http://localhost/?task-creation')); + + $this->container['httpClient'] + ->expects($this->once()) + ->method('postJson') + ->with($this->stringContains('http://localhost/?task-creation&token='), $this->anything()); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test'))); + $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); + } +} diff --git a/tests/units/Notification/WebhookTest.php b/tests/units/Notification/WebhookTest.php deleted file mode 100644 index 5a9eb1c7..00000000 --- a/tests/units/Notification/WebhookTest.php +++ /dev/null @@ -1,29 +0,0 @@ -container); - $p = new ProjectModel($this->container); - $tc = new TaskCreationModel($this->container); - $this->container['dispatcher']->addSubscriber(new NotificationSubscriber($this->container)); - - $c->save(array('webhook_url' => 'http://localhost/?task-creation')); - - $this->container['httpClient'] - ->expects($this->once()) - ->method('postJson') - ->with($this->stringContains('http://localhost/?task-creation&token='), $this->anything()); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'test'))); - } -} -- cgit v1.2.3 From d4606f69f6b0517f45f19d511a46004ae5dc7a5b Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 23 Jul 2016 15:15:11 -0400 Subject: Minor cleanup --- .scrutinizer.yml | 11 ----------- app/Core/Base.php | 7 +++---- app/EventBuilder/EventIteratorBuilder.php | 4 ++++ config.default.php | 8 ++++---- 4 files changed, 11 insertions(+), 19 deletions(-) delete mode 100644 .scrutinizer.yml (limited to 'app/Core') diff --git a/.scrutinizer.yml b/.scrutinizer.yml deleted file mode 100644 index 25ef09c4..00000000 --- a/.scrutinizer.yml +++ /dev/null @@ -1,11 +0,0 @@ -filter: - paths: - - app/* - excluded_paths: - - app/Schema/* - - app/Template/* - - app/Locale/* - - app/Library/* - - app/constants.php - - app/common.php - - app/check_setup.php diff --git a/app/Core/Base.php b/app/Core/Base.php index 20a2d391..6931d93a 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -185,10 +185,10 @@ abstract class Base } /** - * Load automatically models + * Load automatically dependencies * * @access public - * @param string $name Model name + * @param string $name Class name * @return mixed */ public function __get($name) @@ -206,7 +206,6 @@ abstract class Base */ public static function getInstance(Container $container) { - $self = new static($container); - return $self; + return new static($container); } } diff --git a/app/EventBuilder/EventIteratorBuilder.php b/app/EventBuilder/EventIteratorBuilder.php index afa146b6..ba821753 100644 --- a/app/EventBuilder/EventIteratorBuilder.php +++ b/app/EventBuilder/EventIteratorBuilder.php @@ -15,6 +15,10 @@ class EventIteratorBuilder implements Iterator { private $builders = array(); /** + * Set builder + * + * @access public + * @param BaseEventBuilder $builder * @return $this */ public function withBuilder(BaseEventBuilder $builder) diff --git a/config.default.php b/config.default.php index a9fd7d99..d0e93a8e 100644 --- a/config.default.php +++ b/config.default.php @@ -11,16 +11,16 @@ define('DEBUG', false); define('LOG_DRIVER', ''); // Log filename if the log driver is "file" -define('LOG_FILE', __DIR__.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'debug.log'); +define('LOG_FILE', DATA_DIR.DIRECTORY_SEPARATOR.'debug.log'); // Plugins directory -define('PLUGINS_DIR', 'plugins'); +define('PLUGINS_DIR', ROOT_DIR.DIRECTORY_SEPARATOR.'plugins'); // Folder for uploaded files -define('FILES_DIR', 'data'.DIRECTORY_SEPARATOR.'files'); +define('FILES_DIR', DATA_DIR.DIRECTORY_SEPARATOR.'files'); // E-mail address for the "From" header (notifications) -define('MAIL_FROM', 'notifications@kanboard.local'); +define('MAIL_FROM', 'replace-me@kanboard.local'); // Mail transport available: "smtp", "sendmail", "mail" (PHP mail function), "postmark", "mailgun", "sendgrid" define('MAIL_TRANSPORT', 'mail'); -- cgit v1.2.3 From adb5023cfc075ce5d6f73a4ba5b4ab51f6c500c0 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 23 Jul 2016 20:30:06 -0400 Subject: Add unit test for ProjectMetricJob --- app/Core/Base.php | 1 + app/ServiceProvider/JobProvider.php | 5 +++ app/Subscriber/ProjectDailySummarySubscriber.php | 7 +--- tests/units/Job/ProjectMetricJobTest.php | 47 ++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 tests/units/Job/ProjectMetricJobTest.php (limited to 'app/Core') diff --git a/app/Core/Base.php b/app/Core/Base.php index 6931d93a..41f5d2e0 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -157,6 +157,7 @@ use Pimple\Container; * @property \Kanboard\Job\TaskLinkEventJob $taskLinkEventJob * @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob * @property \Kanboard\Job\NotificationJob $notificationJob + * @property \Kanboard\Job\ProjectMetricJob $projectMetricJob * @property \Psr\Log\LoggerInterface $logger * @property \PicoDb\Database $db * @property \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher diff --git a/app/ServiceProvider/JobProvider.php b/app/ServiceProvider/JobProvider.php index 5b42794b..2194b11c 100644 --- a/app/ServiceProvider/JobProvider.php +++ b/app/ServiceProvider/JobProvider.php @@ -5,6 +5,7 @@ namespace Kanboard\ServiceProvider; use Kanboard\Job\CommentEventJob; use Kanboard\Job\NotificationJob; use Kanboard\Job\ProjectFileEventJob; +use Kanboard\Job\ProjectMetricJob; use Kanboard\Job\SubtaskEventJob; use Kanboard\Job\TaskEventJob; use Kanboard\Job\TaskFileEventJob; @@ -57,6 +58,10 @@ class JobProvider implements ServiceProviderInterface return new NotificationJob($c); }); + $container['projectMetricJob'] = $container->factory(function ($c) { + return new ProjectMetricJob($c); + }); + return $container; } } diff --git a/app/Subscriber/ProjectDailySummarySubscriber.php b/app/Subscriber/ProjectDailySummarySubscriber.php index 7e3c11c3..eaa9d468 100644 --- a/app/Subscriber/ProjectDailySummarySubscriber.php +++ b/app/Subscriber/ProjectDailySummarySubscriber.php @@ -3,7 +3,6 @@ namespace Kanboard\Subscriber; use Kanboard\Event\TaskEvent; -use Kanboard\Job\ProjectMetricJob; use Kanboard\Model\TaskModel; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -22,9 +21,7 @@ class ProjectDailySummarySubscriber extends BaseSubscriber implements EventSubsc public function execute(TaskEvent $event) { - if (isset($event['project_id'])) { - $this->logger->debug('Subscriber executed: '.__METHOD__); - $this->queueManager->push(ProjectMetricJob::getInstance($this->container)->withParams($event['project_id'])); - } + $this->logger->debug('Subscriber executed: '.__METHOD__); + $this->queueManager->push($this->projectMetricJob->withParams($event['task']['project_id'])); } } diff --git a/tests/units/Job/ProjectMetricJobTest.php b/tests/units/Job/ProjectMetricJobTest.php new file mode 100644 index 00000000..e5b0474d --- /dev/null +++ b/tests/units/Job/ProjectMetricJobTest.php @@ -0,0 +1,47 @@ +container); + $projectMetricJob->withParams(123); + + $this->assertSame( + array(123), + $projectMetricJob->getJobParams() + ); + } + + public function testJob() + { + $this->container['projectDailyColumnStatsModel'] = $this + ->getMockBuilder('\Kanboard\Model\ProjectDailyColumnStatsModel') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('updateTotals')) + ->getMock(); + + $this->container['projectDailyStatsModel'] = $this + ->getMockBuilder('\Kanboard\Model\ProjectDailyStatsModel') + ->setConstructorArgs(array($this->container)) + ->setMethods(array('updateTotals')) + ->getMock(); + + $this->container['projectDailyColumnStatsModel'] + ->expects($this->once()) + ->method('updateTotals') + ->with(42, date('Y-m-d')); + + $this->container['projectDailyStatsModel'] + ->expects($this->once()) + ->method('updateTotals') + ->with(42, date('Y-m-d')); + + $job = new ProjectMetricJob($this->container); + $job->execute(42); + } +} -- cgit v1.2.3 From 2a7ca0405cdafe26578326c12cdd6b072e8d90ae Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 23 Jul 2016 21:14:33 -0400 Subject: Create new class SubtaskPositionModel --- app/Controller/SubtaskController.php | 2 +- app/Core/Base.php | 1 + app/Model/SubtaskModel.php | 33 ----------- app/Model/SubtaskPositionModel.php | 47 ++++++++++++++++ app/ServiceProvider/ClassProvider.php | 1 + tests/units/Model/SubtaskModelTest.php | 65 ---------------------- tests/units/Model/SubtaskPositionModelTest.php | 77 ++++++++++++++++++++++++++ 7 files changed, 127 insertions(+), 99 deletions(-) create mode 100644 app/Model/SubtaskPositionModel.php create mode 100644 tests/units/Model/SubtaskPositionModelTest.php (limited to 'app/Core') diff --git a/app/Controller/SubtaskController.php b/app/Controller/SubtaskController.php index 93dab5cd..7502d84f 100644 --- a/app/Controller/SubtaskController.php +++ b/app/Controller/SubtaskController.php @@ -168,7 +168,7 @@ class SubtaskController extends BaseController $values = $this->request->getJson(); if (! empty($values) && $this->helper->user->hasProjectAccess('SubtaskController', 'movePosition', $project_id)) { - $result = $this->subtaskModel->changePosition($task_id, $values['subtask_id'], $values['position']); + $result = $this->subtaskPositionModel->changePosition($task_id, $values['subtask_id'], $values['position']); $this->response->json(array('result' => $result)); } else { throw new AccessForbiddenException(); diff --git a/app/Core/Base.php b/app/Core/Base.php index 41f5d2e0..0230b671 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -90,6 +90,7 @@ use Pimple\Container; * @property \Kanboard\Model\ProjectTaskPriorityModel $projectTaskPriorityModel * @property \Kanboard\Model\RememberMeSessionModel $rememberMeSessionModel * @property \Kanboard\Model\SubtaskModel $subtaskModel + * @property \Kanboard\Model\SubtaskPositionModel $subtaskPositionModel * @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel * @property \Kanboard\Model\SwimlaneModel $swimlaneModel * @property \Kanboard\Model\TagDuplicationModel $tagDuplicationModel diff --git a/app/Model/SubtaskModel.php b/app/Model/SubtaskModel.php index f3fc72ba..5a4e87a2 100644 --- a/app/Model/SubtaskModel.php +++ b/app/Model/SubtaskModel.php @@ -272,39 +272,6 @@ class SubtaskModel extends Base return $this->db->table(self::TABLE)->eq('task_id', $task_id)->update(array('status' => self::STATUS_DONE)); } - /** - * Save subtask position - * - * @access public - * @param integer $task_id - * @param integer $subtask_id - * @param integer $position - * @return boolean - */ - public function changePosition($task_id, $subtask_id, $position) - { - if ($position < 1 || $position > $this->db->table(self::TABLE)->eq('task_id', $task_id)->count()) { - return false; - } - - $subtask_ids = $this->db->table(self::TABLE)->eq('task_id', $task_id)->neq('id', $subtask_id)->asc('position')->findAllByColumn('id'); - $offset = 1; - $results = array(); - - foreach ($subtask_ids as $current_subtask_id) { - if ($offset == $position) { - $offset++; - } - - $results[] = $this->db->table(self::TABLE)->eq('id', $current_subtask_id)->update(array('position' => $offset)); - $offset++; - } - - $results[] = $this->db->table(self::TABLE)->eq('id', $subtask_id)->update(array('position' => $position)); - - return !in_array(false, $results, true); - } - /** * Change the status of subtask * diff --git a/app/Model/SubtaskPositionModel.php b/app/Model/SubtaskPositionModel.php new file mode 100644 index 00000000..3c26465d --- /dev/null +++ b/app/Model/SubtaskPositionModel.php @@ -0,0 +1,47 @@ + $this->db->table(SubtaskModel::TABLE)->eq('task_id', $task_id)->count()) { + return false; + } + + $subtask_ids = $this->db->table(SubtaskModel::TABLE)->eq('task_id', $task_id)->neq('id', $subtask_id)->asc('position')->findAllByColumn('id'); + $offset = 1; + $results = array(); + + foreach ($subtask_ids as $current_subtask_id) { + if ($offset == $position) { + $offset++; + } + + $results[] = $this->db->table(SubtaskModel::TABLE)->eq('id', $current_subtask_id)->update(array('position' => $offset)); + $offset++; + } + + $results[] = $this->db->table(SubtaskModel::TABLE)->eq('id', $subtask_id)->update(array('position' => $position)); + + return !in_array(false, $results, true); + } +} diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index e32c0d43..d1415d8c 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -60,6 +60,7 @@ class ClassProvider implements ServiceProviderInterface 'ProjectUserRoleModel', 'RememberMeSessionModel', 'SubtaskModel', + 'SubtaskPositionModel', 'SubtaskTimeTrackingModel', 'SwimlaneModel', 'TagDuplicationModel', diff --git a/tests/units/Model/SubtaskModelTest.php b/tests/units/Model/SubtaskModelTest.php index 7e438651..3b25bb3b 100644 --- a/tests/units/Model/SubtaskModelTest.php +++ b/tests/units/Model/SubtaskModelTest.php @@ -229,71 +229,6 @@ class SubtaskModelTest extends Base $this->assertEquals(2, $subtasks[1]['position']); } - public function testChangePosition() - { - $taskCreationModel = new TaskCreationModel($this->container); - $subtaskModel = new SubtaskModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); - $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1))); - $this->assertEquals(3, $subtaskModel->create(array('title' => 'subtask #3', 'task_id' => 1))); - - $subtasks = $subtaskModel->getAll(1); - $this->assertEquals(1, $subtasks[0]['position']); - $this->assertEquals(1, $subtasks[0]['id']); - $this->assertEquals(2, $subtasks[1]['position']); - $this->assertEquals(2, $subtasks[1]['id']); - $this->assertEquals(3, $subtasks[2]['position']); - $this->assertEquals(3, $subtasks[2]['id']); - - $this->assertTrue($subtaskModel->changePosition(1, 3, 2)); - - $subtasks = $subtaskModel->getAll(1); - $this->assertEquals(1, $subtasks[0]['position']); - $this->assertEquals(1, $subtasks[0]['id']); - $this->assertEquals(2, $subtasks[1]['position']); - $this->assertEquals(3, $subtasks[1]['id']); - $this->assertEquals(3, $subtasks[2]['position']); - $this->assertEquals(2, $subtasks[2]['id']); - - $this->assertTrue($subtaskModel->changePosition(1, 2, 1)); - - $subtasks = $subtaskModel->getAll(1); - $this->assertEquals(1, $subtasks[0]['position']); - $this->assertEquals(2, $subtasks[0]['id']); - $this->assertEquals(2, $subtasks[1]['position']); - $this->assertEquals(1, $subtasks[1]['id']); - $this->assertEquals(3, $subtasks[2]['position']); - $this->assertEquals(3, $subtasks[2]['id']); - - $this->assertTrue($subtaskModel->changePosition(1, 2, 2)); - - $subtasks = $subtaskModel->getAll(1); - $this->assertEquals(1, $subtasks[0]['position']); - $this->assertEquals(1, $subtasks[0]['id']); - $this->assertEquals(2, $subtasks[1]['position']); - $this->assertEquals(2, $subtasks[1]['id']); - $this->assertEquals(3, $subtasks[2]['position']); - $this->assertEquals(3, $subtasks[2]['id']); - - $this->assertTrue($subtaskModel->changePosition(1, 1, 3)); - - $subtasks = $subtaskModel->getAll(1); - $this->assertEquals(1, $subtasks[0]['position']); - $this->assertEquals(2, $subtasks[0]['id']); - $this->assertEquals(2, $subtasks[1]['position']); - $this->assertEquals(3, $subtasks[1]['id']); - $this->assertEquals(3, $subtasks[2]['position']); - $this->assertEquals(1, $subtasks[2]['id']); - - $this->assertFalse($subtaskModel->changePosition(1, 2, 0)); - $this->assertFalse($subtaskModel->changePosition(1, 2, 4)); - } - public function testConvertToTask() { $taskCreationModel = new TaskCreationModel($this->container); diff --git a/tests/units/Model/SubtaskPositionModelTest.php b/tests/units/Model/SubtaskPositionModelTest.php new file mode 100644 index 00000000..92412392 --- /dev/null +++ b/tests/units/Model/SubtaskPositionModelTest.php @@ -0,0 +1,77 @@ +container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskPositionModel = new SubtaskPositionModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1))); + $this->assertEquals(3, $subtaskModel->create(array('title' => 'subtask #3', 'task_id' => 1))); + + $subtasks = $subtaskModel->getAll(1); + $this->assertEquals(1, $subtasks[0]['position']); + $this->assertEquals(1, $subtasks[0]['id']); + $this->assertEquals(2, $subtasks[1]['position']); + $this->assertEquals(2, $subtasks[1]['id']); + $this->assertEquals(3, $subtasks[2]['position']); + $this->assertEquals(3, $subtasks[2]['id']); + + $this->assertTrue($subtaskPositionModel->changePosition(1, 3, 2)); + + $subtasks = $subtaskModel->getAll(1); + $this->assertEquals(1, $subtasks[0]['position']); + $this->assertEquals(1, $subtasks[0]['id']); + $this->assertEquals(2, $subtasks[1]['position']); + $this->assertEquals(3, $subtasks[1]['id']); + $this->assertEquals(3, $subtasks[2]['position']); + $this->assertEquals(2, $subtasks[2]['id']); + + $this->assertTrue($subtaskPositionModel->changePosition(1, 2, 1)); + + $subtasks = $subtaskModel->getAll(1); + $this->assertEquals(1, $subtasks[0]['position']); + $this->assertEquals(2, $subtasks[0]['id']); + $this->assertEquals(2, $subtasks[1]['position']); + $this->assertEquals(1, $subtasks[1]['id']); + $this->assertEquals(3, $subtasks[2]['position']); + $this->assertEquals(3, $subtasks[2]['id']); + + $this->assertTrue($subtaskPositionModel->changePosition(1, 2, 2)); + + $subtasks = $subtaskModel->getAll(1); + $this->assertEquals(1, $subtasks[0]['position']); + $this->assertEquals(1, $subtasks[0]['id']); + $this->assertEquals(2, $subtasks[1]['position']); + $this->assertEquals(2, $subtasks[1]['id']); + $this->assertEquals(3, $subtasks[2]['position']); + $this->assertEquals(3, $subtasks[2]['id']); + + $this->assertTrue($subtaskPositionModel->changePosition(1, 1, 3)); + + $subtasks = $subtaskModel->getAll(1); + $this->assertEquals(1, $subtasks[0]['position']); + $this->assertEquals(2, $subtasks[0]['id']); + $this->assertEquals(2, $subtasks[1]['position']); + $this->assertEquals(3, $subtasks[1]['id']); + $this->assertEquals(3, $subtasks[2]['position']); + $this->assertEquals(1, $subtasks[2]['id']); + + $this->assertFalse($subtaskPositionModel->changePosition(1, 2, 0)); + $this->assertFalse($subtaskPositionModel->changePosition(1, 2, 4)); + } +} -- cgit v1.2.3 From f216e345ba2ad7486037c393c0475a1371ca2b00 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 23 Jul 2016 21:22:24 -0400 Subject: Create new class SubtaskTaskConversionModel --- app/Controller/SubtaskConverterController.php | 2 +- app/Core/Base.php | 1 + app/Model/SubtaskModel.php | 27 -------------- app/Model/SubtaskTaskConversionModel.php | 41 ++++++++++++++++++++++ app/ServiceProvider/ClassProvider.php | 1 + tests/units/Model/SubtaskModelTest.php | 24 ------------- .../units/Model/SubtaskTaskConversionModelTest.php | 37 +++++++++++++++++++ 7 files changed, 81 insertions(+), 52 deletions(-) create mode 100644 app/Model/SubtaskTaskConversionModel.php create mode 100644 tests/units/Model/SubtaskTaskConversionModelTest.php (limited to 'app/Core') diff --git a/app/Controller/SubtaskConverterController.php b/app/Controller/SubtaskConverterController.php index 65bcd2da..404c50d0 100644 --- a/app/Controller/SubtaskConverterController.php +++ b/app/Controller/SubtaskConverterController.php @@ -26,7 +26,7 @@ class SubtaskConverterController extends BaseController $project = $this->getProject(); $subtask = $this->getSubtask(); - $task_id = $this->subtaskModel->convertToTask($project['id'], $subtask['id']); + $task_id = $this->subtaskTaskConversionModel->convertToTask($project['id'], $subtask['id']); if ($task_id !== false) { $this->flash->success(t('Subtask converted to task successfully.')); diff --git a/app/Core/Base.php b/app/Core/Base.php index 0230b671..8b9bf085 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -91,6 +91,7 @@ use Pimple\Container; * @property \Kanboard\Model\RememberMeSessionModel $rememberMeSessionModel * @property \Kanboard\Model\SubtaskModel $subtaskModel * @property \Kanboard\Model\SubtaskPositionModel $subtaskPositionModel + * @property \Kanboard\Model\SubtaskTaskConversionModel $subtaskTaskConversionModel * @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel * @property \Kanboard\Model\SwimlaneModel $swimlaneModel * @property \Kanboard\Model\TagDuplicationModel $tagDuplicationModel diff --git a/app/Model/SubtaskModel.php b/app/Model/SubtaskModel.php index 5a4e87a2..2ac6095c 100644 --- a/app/Model/SubtaskModel.php +++ b/app/Model/SubtaskModel.php @@ -368,31 +368,4 @@ class SubtaskModel extends Base } }); } - - /** - * Convert a subtask to a task - * - * @access public - * @param integer $project_id - * @param integer $subtask_id - * @return integer - */ - public function convertToTask($project_id, $subtask_id) - { - $subtask = $this->getById($subtask_id); - - $task_id = $this->taskCreationModel->create(array( - 'project_id' => $project_id, - 'title' => $subtask['title'], - 'time_estimated' => $subtask['time_estimated'], - 'time_spent' => $subtask['time_spent'], - 'owner_id' => $subtask['user_id'], - )); - - if ($task_id !== false) { - $this->remove($subtask_id); - } - - return $task_id; - } } diff --git a/app/Model/SubtaskTaskConversionModel.php b/app/Model/SubtaskTaskConversionModel.php new file mode 100644 index 00000000..8bf83d76 --- /dev/null +++ b/app/Model/SubtaskTaskConversionModel.php @@ -0,0 +1,41 @@ +subtaskModel->getById($subtask_id); + + $task_id = $this->taskCreationModel->create(array( + 'project_id' => $project_id, + 'title' => $subtask['title'], + 'time_estimated' => $subtask['time_estimated'], + 'time_spent' => $subtask['time_spent'], + 'owner_id' => $subtask['user_id'], + )); + + if ($task_id !== false) { + $this->subtaskModel->remove($subtask_id); + } + + return $task_id; + } +} diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index d1415d8c..ad69d5fb 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -61,6 +61,7 @@ class ClassProvider implements ServiceProviderInterface 'RememberMeSessionModel', 'SubtaskModel', 'SubtaskPositionModel', + 'SubtaskTaskConversionModel', 'SubtaskTimeTrackingModel', 'SwimlaneModel', 'TagDuplicationModel', diff --git a/tests/units/Model/SubtaskModelTest.php b/tests/units/Model/SubtaskModelTest.php index 3b25bb3b..d270e177 100644 --- a/tests/units/Model/SubtaskModelTest.php +++ b/tests/units/Model/SubtaskModelTest.php @@ -229,30 +229,6 @@ class SubtaskModelTest extends Base $this->assertEquals(2, $subtasks[1]['position']); } - public function testConvertToTask() - { - $taskCreationModel = new TaskCreationModel($this->container); - $taskFinderModel = new TaskFinderModel($this->container); - $subtaskModel = new SubtaskModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1, 'user_id' => 1, 'time_spent' => 2, 'time_estimated' => 3))); - $task_id = $subtaskModel->convertToTask(1, 1); - - $this->assertNotFalse($task_id); - $this->assertEmpty($subtaskModel->getById(1)); - - $task = $taskFinderModel->getById($task_id); - $this->assertEquals('subtask #1', $task['title']); - $this->assertEquals(1, $task['project_id']); - $this->assertEquals(1, $task['owner_id']); - $this->assertEquals(2, $task['time_spent']); - $this->assertEquals(3, $task['time_estimated']); - } - public function testGetProjectId() { $taskCreationModel = new TaskCreationModel($this->container); diff --git a/tests/units/Model/SubtaskTaskConversionModelTest.php b/tests/units/Model/SubtaskTaskConversionModelTest.php new file mode 100644 index 00000000..51a623b2 --- /dev/null +++ b/tests/units/Model/SubtaskTaskConversionModelTest.php @@ -0,0 +1,37 @@ +container); + $taskFinderModel = new TaskFinderModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + $subtaskConversion = new SubtaskTaskConversionModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1, 'user_id' => 1, 'time_spent' => 2, 'time_estimated' => 3))); + $task_id = $subtaskConversion->convertToTask(1, 1); + + $this->assertNotFalse($task_id); + $this->assertEmpty($subtaskModel->getById(1)); + + $task = $taskFinderModel->getById($task_id); + $this->assertEquals('subtask #1', $task['title']); + $this->assertEquals(1, $task['project_id']); + $this->assertEquals(1, $task['owner_id']); + $this->assertEquals(2, $task['time_spent']); + $this->assertEquals(3, $task['time_estimated']); + } +} -- cgit v1.2.3 From 24555080fd3ca8607f0a798b5a0e4be98ff131f8 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 23 Jul 2016 21:48:59 -0400 Subject: Create new class SubtaskStatusModel --- app/Controller/SubtaskRestrictionController.php | 2 +- app/Controller/SubtaskStatusController.php | 2 +- app/Core/Base.php | 1 + app/Model/SubtaskModel.php | 184 +++++----------- app/Model/SubtaskStatusModel.php | 85 ++++++++ app/Model/TaskStatusModel.php | 2 +- app/ServiceProvider/ClassProvider.php | 1 + app/Subscriber/BootstrapSubscriber.php | 2 +- tests/units/Model/SubtaskModelTest.php | 110 ---------- tests/units/Model/SubtaskStatusModelTest.php | 123 +++++++++++ tests/units/Model/SubtaskTimeTrackingModelTest.php | 240 +++++++++++++++++++++ tests/units/Model/SubtaskTimeTrackingTest.php | 240 --------------------- 12 files changed, 506 insertions(+), 486 deletions(-) create mode 100644 app/Model/SubtaskStatusModel.php create mode 100644 tests/units/Model/SubtaskStatusModelTest.php create mode 100644 tests/units/Model/SubtaskTimeTrackingModelTest.php delete mode 100644 tests/units/Model/SubtaskTimeTrackingTest.php (limited to 'app/Core') diff --git a/app/Controller/SubtaskRestrictionController.php b/app/Controller/SubtaskRestrictionController.php index 084fc0d9..cb642e1c 100644 --- a/app/Controller/SubtaskRestrictionController.php +++ b/app/Controller/SubtaskRestrictionController.php @@ -27,7 +27,7 @@ class SubtaskRestrictionController extends BaseController SubtaskModel::STATUS_TODO => t('Todo'), SubtaskModel::STATUS_DONE => t('Done'), ), - 'subtask_inprogress' => $this->subtaskModel->getSubtaskInProgress($this->userSession->getId()), + 'subtask_inprogress' => $this->subtaskStatusModel->getSubtaskInProgress($this->userSession->getId()), 'subtask' => $subtask, 'task' => $task, ))); diff --git a/app/Controller/SubtaskStatusController.php b/app/Controller/SubtaskStatusController.php index 699951fe..d4d356c3 100644 --- a/app/Controller/SubtaskStatusController.php +++ b/app/Controller/SubtaskStatusController.php @@ -20,7 +20,7 @@ class SubtaskStatusController extends BaseController $task = $this->getTask(); $subtask = $this->getSubtask(); - $status = $this->subtaskModel->toggleStatus($subtask['id']); + $status = $this->subtaskStatusModel->toggleStatus($subtask['id']); if ($this->request->getIntegerParam('refresh-table') === 0) { $subtask['status'] = $status; diff --git a/app/Core/Base.php b/app/Core/Base.php index 8b9bf085..563013bd 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -91,6 +91,7 @@ use Pimple\Container; * @property \Kanboard\Model\RememberMeSessionModel $rememberMeSessionModel * @property \Kanboard\Model\SubtaskModel $subtaskModel * @property \Kanboard\Model\SubtaskPositionModel $subtaskPositionModel + * @property \Kanboard\Model\SubtaskStatusModel $subtaskStatusModel * @property \Kanboard\Model\SubtaskTaskConversionModel $subtaskTaskConversionModel * @property \Kanboard\Model\SubtaskTimeTrackingModel $subtaskTimeTrackingModel * @property \Kanboard\Model\SwimlaneModel $swimlaneModel diff --git a/app/Model/SubtaskModel.php b/app/Model/SubtaskModel.php index 2ac6095c..568e27a4 100644 --- a/app/Model/SubtaskModel.php +++ b/app/Model/SubtaskModel.php @@ -21,25 +21,13 @@ class SubtaskModel extends Base const TABLE = 'subtasks'; /** - * Task "done" status - * - * @var integer - */ - const STATUS_DONE = 2; - - /** - * Task "in progress" status - * - * @var integer - */ - const STATUS_INPROGRESS = 1; - - /** - * Task "todo" status + * Subtask status * * @var integer */ const STATUS_TODO = 0; + const STATUS_INPROGRESS = 1; + const STATUS_DONE = 2; /** * Events @@ -81,26 +69,6 @@ class SubtaskModel extends Base ); } - /** - * Add subtask status status to the resultset - * - * @access public - * @param array $subtasks Subtasks - * @return array - */ - public function addStatusName(array $subtasks) - { - $status = $this->getStatusList(); - - foreach ($subtasks as &$subtask) { - $subtask['status_name'] = $status[$subtask['status']]; - $subtask['timer_start_date'] = isset($subtask['timer_start_date']) ? $subtask['timer_start_date'] : 0; - $subtask['is_timer_started'] = ! empty($subtask['timer_start_date']); - } - - return $subtasks; - } - /** * Get the query to fetch subtasks assigned to a user * @@ -176,35 +144,6 @@ class SubtaskModel extends Base return $this->db->table(self::TABLE)->eq('id', $subtask_id)->findOne(); } - /** - * Prepare data before insert/update - * - * @access public - * @param array $values Form values - */ - public function prepare(array &$values) - { - $this->helper->model->removeFields($values, array('another_subtask')); - $this->helper->model->resetFields($values, array('time_estimated', 'time_spent')); - } - - /** - * Prepare data before insert - * - * @access public - * @param array $values Form values - */ - public function prepareCreation(array &$values) - { - $this->prepare($values); - - $values['position'] = $this->getLastPosition($values['task_id']) + 1; - $values['status'] = isset($values['status']) ? $values['status'] : self::STATUS_TODO; - $values['time_estimated'] = isset($values['time_estimated']) ? $values['time_estimated'] : 0; - $values['time_spent'] = isset($values['time_spent']) ? $values['time_spent'] : 0; - $values['user_id'] = isset($values['user_id']) ? $values['user_id'] : 0; - } - /** * Get the position of the last column for a given project * @@ -260,74 +199,6 @@ class SubtaskModel extends Base return $result; } - /** - * Close all subtasks of a task - * - * @access public - * @param integer $task_id - * @return boolean - */ - public function closeAll($task_id) - { - return $this->db->table(self::TABLE)->eq('task_id', $task_id)->update(array('status' => self::STATUS_DONE)); - } - - /** - * Change the status of subtask - * - * @access public - * @param integer $subtask_id - * @return boolean|integer - */ - public function toggleStatus($subtask_id) - { - $subtask = $this->getById($subtask_id); - $status = ($subtask['status'] + 1) % 3; - - $values = array( - 'id' => $subtask['id'], - 'status' => $status, - 'task_id' => $subtask['task_id'], - ); - - if (empty($subtask['user_id']) && $this->userSession->isLogged()) { - $values['user_id'] = $this->userSession->getId(); - } - - return $this->update($values) ? $status : false; - } - - /** - * Get the subtask in progress for this user - * - * @access public - * @param integer $user_id - * @return array - */ - public function getSubtaskInProgress($user_id) - { - return $this->db->table(self::TABLE) - ->eq('status', self::STATUS_INPROGRESS) - ->eq('user_id', $user_id) - ->findOne(); - } - - /** - * Return true if the user have a subtask in progress - * - * @access public - * @param integer $user_id - * @return boolean - */ - public function hasSubtaskInProgress($user_id) - { - return $this->configModel->get('subtask_restriction') == 1 && - $this->db->table(self::TABLE) - ->eq('status', self::STATUS_INPROGRESS) - ->eq('user_id', $user_id) - ->exists(); - } - /** * Remove * @@ -368,4 +239,53 @@ class SubtaskModel extends Base } }); } + + /** + * Prepare data before insert/update + * + * @access protected + * @param array $values Form values + */ + protected function prepare(array &$values) + { + $this->helper->model->removeFields($values, array('another_subtask')); + $this->helper->model->resetFields($values, array('time_estimated', 'time_spent')); + } + + /** + * Prepare data before insert + * + * @access protected + * @param array $values Form values + */ + protected function prepareCreation(array &$values) + { + $this->prepare($values); + + $values['position'] = $this->getLastPosition($values['task_id']) + 1; + $values['status'] = isset($values['status']) ? $values['status'] : self::STATUS_TODO; + $values['time_estimated'] = isset($values['time_estimated']) ? $values['time_estimated'] : 0; + $values['time_spent'] = isset($values['time_spent']) ? $values['time_spent'] : 0; + $values['user_id'] = isset($values['user_id']) ? $values['user_id'] : 0; + } + + /** + * Add subtask status status to the resultset + * + * @access public + * @param array $subtasks Subtasks + * @return array + */ + public function addStatusName(array $subtasks) + { + $status = $this->getStatusList(); + + foreach ($subtasks as &$subtask) { + $subtask['status_name'] = $status[$subtask['status']]; + $subtask['timer_start_date'] = isset($subtask['timer_start_date']) ? $subtask['timer_start_date'] : 0; + $subtask['is_timer_started'] = ! empty($subtask['timer_start_date']); + } + + return $subtasks; + } } diff --git a/app/Model/SubtaskStatusModel.php b/app/Model/SubtaskStatusModel.php new file mode 100644 index 00000000..26cbb67d --- /dev/null +++ b/app/Model/SubtaskStatusModel.php @@ -0,0 +1,85 @@ +db->table(SubtaskModel::TABLE) + ->eq('status', SubtaskModel::STATUS_INPROGRESS) + ->eq('user_id', $user_id) + ->findOne(); + } + + /** + * Return true if the user have a subtask in progress + * + * @access public + * @param integer $user_id + * @return boolean + */ + public function hasSubtaskInProgress($user_id) + { + return $this->configModel->get('subtask_restriction') == 1 && + $this->db->table(SubtaskModel::TABLE) + ->eq('status', SubtaskModel::STATUS_INPROGRESS) + ->eq('user_id', $user_id) + ->exists(); + } + + /** + * Change the status of subtask + * + * @access public + * @param integer $subtask_id + * @return boolean|integer + */ + public function toggleStatus($subtask_id) + { + $subtask = $this->subtaskModel->getById($subtask_id); + $status = ($subtask['status'] + 1) % 3; + + $values = array( + 'id' => $subtask['id'], + 'status' => $status, + 'task_id' => $subtask['task_id'], + ); + + if (empty($subtask['user_id']) && $this->userSession->isLogged()) { + $values['user_id'] = $this->userSession->getId(); + } + + return $this->subtaskModel->update($values) ? $status : false; + } + + /** + * Close all subtasks of a task + * + * @access public + * @param integer $task_id + * @return boolean + */ + public function closeAll($task_id) + { + return $this->db + ->table(SubtaskModel::TABLE) + ->eq('task_id', $task_id) + ->update(array('status' => SubtaskModel::STATUS_DONE)); + } +} diff --git a/app/Model/TaskStatusModel.php b/app/Model/TaskStatusModel.php index ea304beb..dc114698 100644 --- a/app/Model/TaskStatusModel.php +++ b/app/Model/TaskStatusModel.php @@ -45,7 +45,7 @@ class TaskStatusModel extends Base */ public function close($task_id) { - $this->subtaskModel->closeAll($task_id); + $this->subtaskStatusModel->closeAll($task_id); return $this->changeStatus($task_id, TaskModel::STATUS_CLOSED, time(), TaskModel::EVENT_CLOSE); } diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index ad69d5fb..9a71148b 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -61,6 +61,7 @@ class ClassProvider implements ServiceProviderInterface 'RememberMeSessionModel', 'SubtaskModel', 'SubtaskPositionModel', + 'SubtaskStatusModel', 'SubtaskTaskConversionModel', 'SubtaskTimeTrackingModel', 'SwimlaneModel', diff --git a/app/Subscriber/BootstrapSubscriber.php b/app/Subscriber/BootstrapSubscriber.php index 7d12e9ae..3618f30f 100644 --- a/app/Subscriber/BootstrapSubscriber.php +++ b/app/Subscriber/BootstrapSubscriber.php @@ -21,7 +21,7 @@ class BootstrapSubscriber extends BaseSubscriber implements EventSubscriberInter $this->actionManager->attachEvents(); if ($this->userSession->isLogged()) { - $this->sessionStorage->hasSubtaskInProgress = $this->subtaskModel->hasSubtaskInProgress($this->userSession->getId()); + $this->sessionStorage->hasSubtaskInProgress = $this->subtaskStatusModel->hasSubtaskInProgress($this->userSession->getId()); } } diff --git a/tests/units/Model/SubtaskModelTest.php b/tests/units/Model/SubtaskModelTest.php index d270e177..23183d22 100644 --- a/tests/units/Model/SubtaskModelTest.php +++ b/tests/units/Model/SubtaskModelTest.php @@ -5,7 +5,6 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Model\TaskCreationModel; use Kanboard\Model\SubtaskModel; use Kanboard\Model\ProjectModel; -use Kanboard\Model\TaskFinderModel; class SubtaskModelTest extends Base { @@ -74,115 +73,6 @@ class SubtaskModelTest extends Base $this->assertEmpty($subtask); } - public function testToggleStatusWithoutSession() - { - $taskCreationModel = new TaskCreationModel($this->container); - $subtaskModel = new SubtaskModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtaskModel->toggleStatus(1)); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_DONE, $subtaskModel->toggleStatus(1)); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtaskModel->toggleStatus(1)); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - } - - public function testToggleStatusWithSession() - { - $taskCreationModel = new TaskCreationModel($this->container); - $subtaskModel = new SubtaskModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); - $this->assertEquals(0, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - // Set the current logged user - $this->container['sessionStorage']->user = array('id' => 1); - - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtaskModel->toggleStatus(1)); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); - $this->assertEquals(1, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_DONE, $subtaskModel->toggleStatus(1)); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); - $this->assertEquals(1, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtaskModel->toggleStatus(1)); - - $subtask = $subtaskModel->getById(1); - $this->assertNotEmpty($subtask); - $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); - $this->assertEquals(1, $subtask['user_id']); - $this->assertEquals(1, $subtask['task_id']); - } - - public function testCloseAll() - { - $taskCreationModel = new TaskCreationModel($this->container); - $subtaskModel = new SubtaskModel($this->container); - $projectModel = new ProjectModel($this->container); - - $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); - $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); - - $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); - $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1))); - - $this->assertTrue($subtaskModel->closeAll(1)); - - $subtasks = $subtaskModel->getAll(1); - $this->assertNotEmpty($subtasks); - - foreach ($subtasks as $subtask) { - $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); - } - } - public function testDuplicate() { $taskCreationModel = new TaskCreationModel($this->container); diff --git a/tests/units/Model/SubtaskStatusModelTest.php b/tests/units/Model/SubtaskStatusModelTest.php new file mode 100644 index 00000000..af4c3955 --- /dev/null +++ b/tests/units/Model/SubtaskStatusModelTest.php @@ -0,0 +1,123 @@ +container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskStatusModel = new SubtaskStatusModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtaskStatusModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtaskStatusModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtaskStatusModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + } + + public function testToggleStatusWithSession() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + $subtaskStatusModel = new SubtaskStatusModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); + $this->assertEquals(0, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + // Set the current logged user + $this->container['sessionStorage']->user = array('id' => 1); + + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtaskStatusModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']); + $this->assertEquals(1, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtaskStatusModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); + $this->assertEquals(1, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtaskStatusModel->toggleStatus(1)); + + $subtask = $subtaskModel->getById(1); + $this->assertNotEmpty($subtask); + $this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']); + $this->assertEquals(1, $subtask['user_id']); + $this->assertEquals(1, $subtask['task_id']); + } + + public function testCloseAll() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $projectModel = new ProjectModel($this->container); + $subtaskStatusModel = new SubtaskStatusModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1))); + + $this->assertTrue($subtaskStatusModel->closeAll(1)); + + $subtasks = $subtaskModel->getAll(1); + $this->assertNotEmpty($subtasks); + + foreach ($subtasks as $subtask) { + $this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']); + } + } +} diff --git a/tests/units/Model/SubtaskTimeTrackingModelTest.php b/tests/units/Model/SubtaskTimeTrackingModelTest.php new file mode 100644 index 00000000..cfee5b14 --- /dev/null +++ b/tests/units/Model/SubtaskTimeTrackingModelTest.php @@ -0,0 +1,240 @@ +container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); + + $this->assertFalse($subtaskTimeTrackingModel->hasTimer(1, 1)); + $this->assertTrue($subtaskTimeTrackingModel->logStartTime(1, 1)); + $this->assertTrue($subtaskTimeTrackingModel->hasTimer(1, 1)); + $this->assertFalse($subtaskTimeTrackingModel->logStartTime(1, 1)); + $this->assertTrue($subtaskTimeTrackingModel->logEndTime(1, 1)); + $this->assertFalse($subtaskTimeTrackingModel->hasTimer(1, 1)); + } + + public function testGetTimerStatus() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->container['sessionStorage']->user = array('id' => 1); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1, 'user_id' => 1))); + + // Nothing started + $subtasks = $subtaskModel->getAll(1); + $this->assertNotEmpty($subtasks); + $this->assertEquals(0, $subtasks[0]['timer_start_date']); + $this->assertFalse($subtasks[0]['is_timer_started']); + + $subtask = $subtaskModel->getById(1, true); + $this->assertNotEmpty($subtask); + $this->assertEquals(0, $subtask['timer_start_date']); + $this->assertFalse($subtask['is_timer_started']); + + // Start the clock + $this->assertTrue($subtaskTimeTrackingModel->logStartTime(1, 1)); + + $subtasks = $subtaskModel->getAll(1); + $this->assertNotEmpty($subtasks); + $this->assertEquals(time(), $subtasks[0]['timer_start_date'], '', 3); + $this->assertTrue($subtasks[0]['is_timer_started']); + + $subtask = $subtaskModel->getById(1, true); + $this->assertNotEmpty($subtask); + $this->assertEquals(time(), $subtask['timer_start_date'], '', 3); + $this->assertTrue($subtask['is_timer_started']); + + // Stop the clock + $this->assertTrue($subtaskTimeTrackingModel->logEndTime(1, 1)); + $subtasks = $subtaskModel->getAll(1); + $this->assertNotEmpty($subtasks); + $this->assertEquals(0, $subtasks[0]['timer_start_date']); + $this->assertFalse($subtasks[0]['is_timer_started']); + + $subtask = $subtaskModel->getById(1, true); + $this->assertNotEmpty($subtask); + $this->assertEquals(0, $subtask['timer_start_date']); + $this->assertFalse($subtask['is_timer_started']); + } + + public function testLogStartTime() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); + + $this->assertTrue($subtaskTimeTrackingModel->logStartTime(1, 1)); + + $timesheet = $subtaskTimeTrackingModel->getUserTimesheet(1); + $this->assertNotEmpty($timesheet); + $this->assertCount(1, $timesheet); + $this->assertNotEmpty($timesheet[0]['start']); + $this->assertEmpty($timesheet[0]['end']); + $this->assertEquals(1, $timesheet[0]['user_id']); + $this->assertEquals(1, $timesheet[0]['subtask_id']); + } + + public function testLogStartEnd() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); + + // No start time + $this->assertTrue($subtaskTimeTrackingModel->logEndTime(1, 1)); + $timesheet = $subtaskTimeTrackingModel->getUserTimesheet(1); + $this->assertEmpty($timesheet); + + // Log start and end time + $this->assertTrue($subtaskTimeTrackingModel->logStartTime(1, 1)); + sleep(1); + $this->assertTrue($subtaskTimeTrackingModel->logEndTime(1, 1)); + + $timesheet = $subtaskTimeTrackingModel->getUserTimesheet(1); + $this->assertNotEmpty($timesheet); + $this->assertCount(1, $timesheet); + $this->assertNotEmpty($timesheet[0]['start']); + $this->assertNotEmpty($timesheet[0]['end']); + $this->assertEquals(1, $timesheet[0]['user_id']); + $this->assertEquals(1, $timesheet[0]['subtask_id']); + $this->assertNotEquals($timesheet[0]['start'], $timesheet[0]['end']); + } + + public function testCalculateSubtaskTime() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_spent' => 2.2, 'time_estimated' => 3.3))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_spent' => 1.1, 'time_estimated' => 4.4))); + + $time = $subtaskTimeTrackingModel->calculateSubtaskTime(1); + $this->assertCount(2, $time); + $this->assertEquals(3.3, $time['time_spent'], 'Total spent', 0.01); + $this->assertEquals(7.7, $time['time_estimated'], 'Total estimated', 0.01); + } + + public function testUpdateSubtaskTimeSpent() + { + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_spent' => 2.2))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1))); + + $this->assertTrue($subtaskTimeTrackingModel->logStartTime(1, 1)); + $this->assertTrue($subtaskTimeTrackingModel->logStartTime(2, 1)); + + // Fake start time + $this->container['db']->table(SubtaskTimeTrackingModel::TABLE)->update(array('start' => time() - 3600)); + + $this->assertTrue($subtaskTimeTrackingModel->logEndTime(1, 1)); + $this->assertTrue($subtaskTimeTrackingModel->logEndTime(2, 1)); + + $timesheet = $subtaskTimeTrackingModel->getUserTimesheet(1); + $this->assertNotEmpty($timesheet); + $this->assertCount(2, $timesheet); + $this->assertEquals(3600, $timesheet[0]['end'] - $timesheet[0]['start'], 'Wrong timestamps', 1); + $this->assertEquals(3600, $timesheet[1]['end'] - $timesheet[1]['start'], 'Wrong timestamps', 1); + + $time = $subtaskTimeTrackingModel->calculateSubtaskTime(1); + $this->assertEquals(4.2, $time['time_spent'], 'Total spent', 0.01); + $this->assertEquals(0, $time['time_estimated'], 'Total estimated', 0.01); + + $time = $subtaskTimeTrackingModel->calculateSubtaskTime(2); + $this->assertEquals(0, $time['time_spent'], 'Total spent', 0.01); + $this->assertEquals(0, $time['time_estimated'], 'Total estimated', 0.01); + } + + public function testUpdateTaskTimeTracking() + { + $taskFinderModel = new TaskFinderModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskTimeTrackingModel = new SubtaskTimeTrackingModel($this->container); + $projectModel = new ProjectModel($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'test 2', 'project_id' => 1, 'time_estimated' => 1.5, 'time_spent' => 0.5))); + $this->assertEquals(3, $taskCreationModel->create(array('title' => 'test 3', 'project_id' => 1, 'time_estimated' => 4, 'time_spent' => 2))); + + $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1, 'time_spent' => 2.2))); + $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_estimated' => 1))); + + $this->assertEquals(3, $subtaskModel->create(array('title' => 'subtask #3', 'task_id' => 2, 'time_spent' => 3.4))); + $this->assertEquals(4, $subtaskModel->create(array('title' => 'subtask #4', 'task_id' => 2, 'time_estimated' => 1.25))); + + $this->assertEquals(5, $subtaskModel->create(array('title' => 'subtask #5', 'task_id' => 3, 'time_spent' => 8))); + + $subtaskTimeTrackingModel->updateTaskTimeTracking(1); + $subtaskTimeTrackingModel->updateTaskTimeTracking(2); + $subtaskTimeTrackingModel->updateTaskTimeTracking(3); + + $task = $taskFinderModel->getById(1); + $this->assertNotEmpty($task); + $this->assertEquals(2.2, $task['time_spent'], 'Total spent', 0.01); + $this->assertEquals(1, $task['time_estimated'], 'Total estimated', 0.01); + + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(3.4, $task['time_spent'], 'Total spent', 0.01); + $this->assertEquals(1.25, $task['time_estimated'], 'Total estimated', 0.01); + + $task = $taskFinderModel->getById(3); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['time_estimated']); + $this->assertEquals(8, $task['time_spent']); + + $this->assertTrue($subtaskModel->remove(3)); + $this->assertTrue($subtaskModel->remove(4)); + + $subtaskTimeTrackingModel->updateTaskTimeTracking(2); + + $task = $taskFinderModel->getById(2); + $this->assertNotEmpty($task); + $this->assertEquals(0, $task['time_estimated']); + $this->assertEquals(0, $task['time_spent']); + } +} diff --git a/tests/units/Model/SubtaskTimeTrackingTest.php b/tests/units/Model/SubtaskTimeTrackingTest.php deleted file mode 100644 index d5ae62ae..00000000 --- a/tests/units/Model/SubtaskTimeTrackingTest.php +++ /dev/null @@ -1,240 +0,0 @@ -container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); - - $this->assertFalse($st->hasTimer(1, 1)); - $this->assertTrue($st->logStartTime(1, 1)); - $this->assertTrue($st->hasTimer(1, 1)); - $this->assertFalse($st->logStartTime(1, 1)); - $this->assertTrue($st->logEndTime(1, 1)); - $this->assertFalse($st->hasTimer(1, 1)); - } - - public function testGetTimerStatus() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->container['sessionStorage']->user = array('id' => 1); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1, 'user_id' => 1))); - - // Nothing started - $subtasks = $s->getAll(1); - $this->assertNotEmpty($subtasks); - $this->assertEquals(0, $subtasks[0]['timer_start_date']); - $this->assertFalse($subtasks[0]['is_timer_started']); - - $subtask = $s->getById(1, true); - $this->assertNotEmpty($subtask); - $this->assertEquals(0, $subtask['timer_start_date']); - $this->assertFalse($subtask['is_timer_started']); - - // Start the clock - $this->assertTrue($st->logStartTime(1, 1)); - - $subtasks = $s->getAll(1); - $this->assertNotEmpty($subtasks); - $this->assertEquals(time(), $subtasks[0]['timer_start_date'], '', 3); - $this->assertTrue($subtasks[0]['is_timer_started']); - - $subtask = $s->getById(1, true); - $this->assertNotEmpty($subtask); - $this->assertEquals(time(), $subtask['timer_start_date'], '', 3); - $this->assertTrue($subtask['is_timer_started']); - - // Stop the clock - $this->assertTrue($st->logEndTime(1, 1)); - $subtasks = $s->getAll(1); - $this->assertNotEmpty($subtasks); - $this->assertEquals(0, $subtasks[0]['timer_start_date']); - $this->assertFalse($subtasks[0]['is_timer_started']); - - $subtask = $s->getById(1, true); - $this->assertNotEmpty($subtask); - $this->assertEquals(0, $subtask['timer_start_date']); - $this->assertFalse($subtask['is_timer_started']); - } - - public function testLogStartTime() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); - - $this->assertTrue($st->logStartTime(1, 1)); - - $timesheet = $st->getUserTimesheet(1); - $this->assertNotEmpty($timesheet); - $this->assertCount(1, $timesheet); - $this->assertNotEmpty($timesheet[0]['start']); - $this->assertEmpty($timesheet[0]['end']); - $this->assertEquals(1, $timesheet[0]['user_id']); - $this->assertEquals(1, $timesheet[0]['subtask_id']); - } - - public function testLogStartEnd() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'user_id' => 1))); - - // No start time - $this->assertTrue($st->logEndTime(1, 1)); - $timesheet = $st->getUserTimesheet(1); - $this->assertEmpty($timesheet); - - // Log start and end time - $this->assertTrue($st->logStartTime(1, 1)); - sleep(1); - $this->assertTrue($st->logEndTime(1, 1)); - - $timesheet = $st->getUserTimesheet(1); - $this->assertNotEmpty($timesheet); - $this->assertCount(1, $timesheet); - $this->assertNotEmpty($timesheet[0]['start']); - $this->assertNotEmpty($timesheet[0]['end']); - $this->assertEquals(1, $timesheet[0]['user_id']); - $this->assertEquals(1, $timesheet[0]['subtask_id']); - $this->assertNotEquals($timesheet[0]['start'], $timesheet[0]['end']); - } - - public function testCalculateSubtaskTime() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_spent' => 2.2, 'time_estimated' => 3.3))); - $this->assertEquals(2, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_spent' => 1.1, 'time_estimated' => 4.4))); - - $time = $st->calculateSubtaskTime(1); - $this->assertCount(2, $time); - $this->assertEquals(3.3, $time['time_spent'], 'Total spent', 0.01); - $this->assertEquals(7.7, $time['time_estimated'], 'Total estimated', 0.01); - } - - public function testUpdateSubtaskTimeSpent() - { - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_spent' => 2.2))); - $this->assertEquals(2, $s->create(array('title' => 'subtask #2', 'task_id' => 1))); - - $this->assertTrue($st->logStartTime(1, 1)); - $this->assertTrue($st->logStartTime(2, 1)); - - // Fake start time - $this->container['db']->table(SubtaskTimeTrackingModel::TABLE)->update(array('start' => time() - 3600)); - - $this->assertTrue($st->logEndTime(1, 1)); - $this->assertTrue($st->logEndTime(2, 1)); - - $timesheet = $st->getUserTimesheet(1); - $this->assertNotEmpty($timesheet); - $this->assertCount(2, $timesheet); - $this->assertEquals(3600, $timesheet[0]['end'] - $timesheet[0]['start'], 'Wrong timestamps', 1); - $this->assertEquals(3600, $timesheet[1]['end'] - $timesheet[1]['start'], 'Wrong timestamps', 1); - - $time = $st->calculateSubtaskTime(1); - $this->assertEquals(4.2, $time['time_spent'], 'Total spent', 0.01); - $this->assertEquals(0, $time['time_estimated'], 'Total estimated', 0.01); - - $time = $st->calculateSubtaskTime(2); - $this->assertEquals(0, $time['time_spent'], 'Total spent', 0.01); - $this->assertEquals(0, $time['time_estimated'], 'Total estimated', 0.01); - } - - public function testUpdateTaskTimeTracking() - { - $tf = new TaskFinderModel($this->container); - $tc = new TaskCreationModel($this->container); - $s = new SubtaskModel($this->container); - $st = new SubtaskTimeTrackingModel($this->container); - $p = new ProjectModel($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test1'))); - - $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1))); - $this->assertEquals(2, $tc->create(array('title' => 'test 2', 'project_id' => 1, 'time_estimated' => 1.5, 'time_spent' => 0.5))); - $this->assertEquals(3, $tc->create(array('title' => 'test 3', 'project_id' => 1, 'time_estimated' => 4, 'time_spent' => 2))); - - $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1, 'time_spent' => 2.2))); - $this->assertEquals(2, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_estimated' => 1))); - - $this->assertEquals(3, $s->create(array('title' => 'subtask #3', 'task_id' => 2, 'time_spent' => 3.4))); - $this->assertEquals(4, $s->create(array('title' => 'subtask #4', 'task_id' => 2, 'time_estimated' => 1.25))); - - $this->assertEquals(5, $s->create(array('title' => 'subtask #5', 'task_id' => 3, 'time_spent' => 8))); - - $st->updateTaskTimeTracking(1); - $st->updateTaskTimeTracking(2); - $st->updateTaskTimeTracking(3); - - $task = $tf->getById(1); - $this->assertNotEmpty($task); - $this->assertEquals(2.2, $task['time_spent'], 'Total spent', 0.01); - $this->assertEquals(1, $task['time_estimated'], 'Total estimated', 0.01); - - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(3.4, $task['time_spent'], 'Total spent', 0.01); - $this->assertEquals(1.25, $task['time_estimated'], 'Total estimated', 0.01); - - $task = $tf->getById(3); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['time_estimated']); - $this->assertEquals(8, $task['time_spent']); - - $this->assertTrue($s->remove(3)); - $this->assertTrue($s->remove(4)); - - $st->updateTaskTimeTracking(2); - - $task = $tf->getById(2); - $this->assertNotEmpty($task); - $this->assertEquals(0, $task['time_estimated']); - $this->assertEquals(0, $task['time_spent']); - } -} -- cgit v1.2.3 From 51b2193fc43a25f309a8510b64027d40bf21e12d Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 24 Jul 2016 12:09:41 -0400 Subject: Move dashboard pagination into separate classes --- app/Controller/DashboardController.php | 72 ++------------------ app/Controller/UserListController.php | 7 +- app/Core/Base.php | 4 ++ app/Model/ProjectDuplicationModel.php | 2 +- app/Model/ProjectModel.php | 2 +- app/Model/TaskFinderModel.php | 86 ++++++++++++------------ app/Pagination/ProjectPagination.php | 35 ++++++++++ app/Pagination/SubtaskPagination.php | 36 ++++++++++ app/Pagination/TaskPagination.php | 35 ++++++++++ app/Pagination/UserPagination.php | 32 +++++++++ app/ServiceProvider/ClassProvider.php | 6 ++ app/Template/dashboard/projects.php | 4 +- app/Template/dashboard/subtasks.php | 4 +- app/Template/dashboard/tasks.php | 8 +-- tests/units/Model/TaskFinderModelTest.php | 2 +- tests/units/Pagination/ProjectPaginationTest.php | 35 ++++++++++ tests/units/Pagination/SubtaskPaginationTest.php | 36 ++++++++++ tests/units/Pagination/TaskPaginationTest.php | 30 +++++++++ tests/units/Pagination/UserPaginationTest.php | 27 ++++++++ 19 files changed, 337 insertions(+), 126 deletions(-) create mode 100644 app/Pagination/ProjectPagination.php create mode 100644 app/Pagination/SubtaskPagination.php create mode 100644 app/Pagination/TaskPagination.php create mode 100644 app/Pagination/UserPagination.php create mode 100644 tests/units/Pagination/ProjectPaginationTest.php create mode 100644 tests/units/Pagination/SubtaskPaginationTest.php create mode 100644 tests/units/Pagination/TaskPaginationTest.php create mode 100644 tests/units/Pagination/UserPaginationTest.php (limited to 'app/Core') diff --git a/app/Controller/DashboardController.php b/app/Controller/DashboardController.php index 44874546..0133499f 100644 --- a/app/Controller/DashboardController.php +++ b/app/Controller/DashboardController.php @@ -2,9 +2,6 @@ namespace Kanboard\Controller; -use Kanboard\Model\ProjectModel; -use Kanboard\Model\SubtaskModel; - /** * Dashboard Controller * @@ -13,63 +10,6 @@ use Kanboard\Model\SubtaskModel; */ class DashboardController extends BaseController { - /** - * Get project pagination - * - * @access private - * @param integer $user_id - * @param string $action - * @param integer $max - * @return \Kanboard\Core\Paginator - */ - private function getProjectPaginator($user_id, $action, $max) - { - return $this->paginator - ->setUrl('DashboardController', $action, array('pagination' => 'projects', 'user_id' => $user_id)) - ->setMax($max) - ->setOrder(ProjectModel::TABLE.'.name') - ->setQuery($this->projectModel->getQueryColumnStats($this->projectPermissionModel->getActiveProjectIds($user_id))) - ->calculateOnlyIf($this->request->getStringParam('pagination') === 'projects'); - } - - /** - * Get task pagination - * - * @access private - * @param integer $user_id - * @param string $action - * @param integer $max - * @return \Kanboard\Core\Paginator - */ - private function getTaskPaginator($user_id, $action, $max) - { - return $this->paginator - ->setUrl('DashboardController', $action, array('pagination' => 'tasks', 'user_id' => $user_id)) - ->setMax($max) - ->setOrder('tasks.id') - ->setQuery($this->taskFinderModel->getUserQuery($user_id)) - ->calculateOnlyIf($this->request->getStringParam('pagination') === 'tasks'); - } - - /** - * Get subtask pagination - * - * @access private - * @param integer $user_id - * @param string $action - * @param integer $max - * @return \Kanboard\Core\Paginator - */ - private function getSubtaskPaginator($user_id, $action, $max) - { - return $this->paginator - ->setUrl('DashboardController', $action, array('pagination' => 'subtasks', 'user_id' => $user_id)) - ->setMax($max) - ->setOrder('tasks.id') - ->setQuery($this->subtaskModel->getUserQuery($user_id, array(SubTaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS))) - ->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks'); - } - /** * Dashboard overview * @@ -81,9 +21,9 @@ class DashboardController extends BaseController $this->response->html($this->helper->layout->dashboard('dashboard/show', array( 'title' => t('Dashboard'), - 'project_paginator' => $this->getProjectPaginator($user['id'], 'show', 10), - 'task_paginator' => $this->getTaskPaginator($user['id'], 'show', 10), - 'subtask_paginator' => $this->getSubtaskPaginator($user['id'], 'show', 10), + 'project_paginator' => $this->projectPagination->getDashboardPaginator($user['id'], 'show', 10), + 'task_paginator' => $this->taskPagination->getDashboardPaginator($user['id'], 'show', 10), + 'subtask_paginator' => $this->subtaskPagination->getDashboardPaginator($user['id'], 'show', 10), 'user' => $user, ))); } @@ -99,7 +39,7 @@ class DashboardController extends BaseController $this->response->html($this->helper->layout->dashboard('dashboard/tasks', array( 'title' => t('My tasks'), - 'paginator' => $this->getTaskPaginator($user['id'], 'tasks', 50), + 'paginator' => $this->taskPagination->getDashboardPaginator($user['id'], 'tasks', 50), 'user' => $user, ))); } @@ -115,7 +55,7 @@ class DashboardController extends BaseController $this->response->html($this->helper->layout->dashboard('dashboard/subtasks', array( 'title' => t('My subtasks'), - 'paginator' => $this->getSubtaskPaginator($user['id'], 'subtasks', 50), + 'paginator' => $this->subtaskPagination->getDashboardPaginator($user['id'], 'subtasks', 50), 'user' => $user, ))); } @@ -131,7 +71,7 @@ class DashboardController extends BaseController $this->response->html($this->helper->layout->dashboard('dashboard/projects', array( 'title' => t('My projects'), - 'paginator' => $this->getProjectPaginator($user['id'], 'projects', 25), + 'paginator' => $this->projectPagination->getDashboardPaginator($user['id'], 'projects', 25), 'user' => $user, ))); } diff --git a/app/Controller/UserListController.php b/app/Controller/UserListController.php index 31fcdd44..888583fa 100644 --- a/app/Controller/UserListController.php +++ b/app/Controller/UserListController.php @@ -17,12 +17,7 @@ class UserListController extends BaseController */ public function show() { - $paginator = $this->paginator - ->setUrl('UserListController', 'show') - ->setMax(30) - ->setOrder('username') - ->setQuery($this->userModel->getQuery()) - ->calculate(); + $paginator = $this->userPagination->getListingPaginator(); $this->response->html($this->helper->layout->app('user_list/show', array( 'title' => t('Users').' ('.$paginator->getTotal().')', diff --git a/app/Core/Base.php b/app/Core/Base.php index 563013bd..68604785 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -122,6 +122,10 @@ use Pimple\Container; * @property \Kanboard\Model\UserNotificationFilterModel $userNotificationFilterModel * @property \Kanboard\Model\UserUnreadNotificationModel $userUnreadNotificationModel * @property \Kanboard\Model\UserMetadataModel $userMetadataModel + * @property \Kanboard\Pagination\TaskPagination $taskPagination + * @property \Kanboard\Pagination\SubtaskPagination $subtaskPagination + * @property \Kanboard\Pagination\ProjectPagination $projectPagination + * @property \Kanboard\Pagination\UserPagination $userPagination * @property \Kanboard\Validator\ActionValidator $actionValidator * @property \Kanboard\Validator\AuthValidator $authValidator * @property \Kanboard\Validator\ColumnValidator $columnValidator diff --git a/app/Model/ProjectDuplicationModel.php b/app/Model/ProjectDuplicationModel.php index 94b83c80..d32fa367 100644 --- a/app/Model/ProjectDuplicationModel.php +++ b/app/Model/ProjectDuplicationModel.php @@ -159,7 +159,7 @@ class ProjectDuplicationModel extends Base } /** - * Make sure that the creator of the duplicated project is alsp owner + * Make sure that the creator of the duplicated project is also owner * * @access private * @param integer $dst_project_id diff --git a/app/Model/ProjectModel.php b/app/Model/ProjectModel.php index 850531c9..d2019b72 100644 --- a/app/Model/ProjectModel.php +++ b/app/Model/ProjectModel.php @@ -318,7 +318,7 @@ class ProjectModel extends Base public function getQueryColumnStats(array $project_ids) { if (empty($project_ids)) { - return $this->db->table(ProjectModel::TABLE)->limit(0); + return $this->db->table(ProjectModel::TABLE)->eq(ProjectModel::TABLE.'.id', 0); } return $this->db diff --git a/app/Model/TaskFinderModel.php b/app/Model/TaskFinderModel.php index 7268052c..924f339b 100644 --- a/app/Model/TaskFinderModel.php +++ b/app/Model/TaskFinderModel.php @@ -63,19 +63,19 @@ class TaskFinderModel extends Base return $this->db ->table(TaskModel::TABLE) ->columns( - 'tasks.id', - 'tasks.title', - 'tasks.date_due', - 'tasks.date_creation', - 'tasks.project_id', - 'tasks.color_id', - 'tasks.priority', - 'tasks.time_spent', - 'tasks.time_estimated', - 'tasks.is_active', - 'tasks.creator_id', - 'projects.name AS project_name', - 'columns.title AS column_title' + TaskModel::TABLE.'.id', + TaskModel::TABLE.'.title', + TaskModel::TABLE.'.date_due', + TaskModel::TABLE.'.date_creation', + TaskModel::TABLE.'.project_id', + TaskModel::TABLE.'.color_id', + TaskModel::TABLE.'.priority', + TaskModel::TABLE.'.time_spent', + TaskModel::TABLE.'.time_estimated', + TaskModel::TABLE.'.is_active', + TaskModel::TABLE.'.creator_id', + ProjectModel::TABLE.'.name AS project_name', + ColumnModel::TABLE.'.title AS column_title' ) ->join(ProjectModel::TABLE, 'id', 'project_id') ->join(ColumnModel::TABLE, 'id', 'column_id') @@ -103,36 +103,36 @@ class TaskFinderModel extends Base '(SELECT COUNT(*) FROM '.TaskLinkModel::TABLE.' WHERE '.TaskLinkModel::TABLE.'.task_id = tasks.id) AS nb_links', '(SELECT COUNT(*) FROM '.TaskExternalLinkModel::TABLE.' WHERE '.TaskExternalLinkModel::TABLE.'.task_id = tasks.id) AS nb_external_links', '(SELECT DISTINCT 1 FROM '.TaskLinkModel::TABLE.' WHERE '.TaskLinkModel::TABLE.'.task_id = tasks.id AND '.TaskLinkModel::TABLE.'.link_id = 9) AS is_milestone', - 'tasks.id', - 'tasks.reference', - 'tasks.title', - 'tasks.description', - 'tasks.date_creation', - 'tasks.date_modification', - 'tasks.date_completed', - 'tasks.date_started', - 'tasks.date_due', - 'tasks.color_id', - 'tasks.project_id', - 'tasks.column_id', - 'tasks.swimlane_id', - 'tasks.owner_id', - 'tasks.creator_id', - 'tasks.position', - 'tasks.is_active', - 'tasks.score', - 'tasks.category_id', - 'tasks.priority', - 'tasks.date_moved', - 'tasks.recurrence_status', - 'tasks.recurrence_trigger', - 'tasks.recurrence_factor', - 'tasks.recurrence_timeframe', - 'tasks.recurrence_basedate', - 'tasks.recurrence_parent', - 'tasks.recurrence_child', - 'tasks.time_estimated', - 'tasks.time_spent', + TaskModel::TABLE.'.id', + TaskModel::TABLE.'.reference', + TaskModel::TABLE.'.title', + TaskModel::TABLE.'.description', + TaskModel::TABLE.'.date_creation', + TaskModel::TABLE.'.date_modification', + TaskModel::TABLE.'.date_completed', + TaskModel::TABLE.'.date_started', + TaskModel::TABLE.'.date_due', + TaskModel::TABLE.'.color_id', + TaskModel::TABLE.'.project_id', + TaskModel::TABLE.'.column_id', + TaskModel::TABLE.'.swimlane_id', + TaskModel::TABLE.'.owner_id', + TaskModel::TABLE.'.creator_id', + TaskModel::TABLE.'.position', + TaskModel::TABLE.'.is_active', + TaskModel::TABLE.'.score', + TaskModel::TABLE.'.category_id', + TaskModel::TABLE.'.priority', + TaskModel::TABLE.'.date_moved', + TaskModel::TABLE.'.recurrence_status', + TaskModel::TABLE.'.recurrence_trigger', + TaskModel::TABLE.'.recurrence_factor', + TaskModel::TABLE.'.recurrence_timeframe', + TaskModel::TABLE.'.recurrence_basedate', + TaskModel::TABLE.'.recurrence_parent', + TaskModel::TABLE.'.recurrence_child', + TaskModel::TABLE.'.time_estimated', + TaskModel::TABLE.'.time_spent', UserModel::TABLE.'.username AS assignee_username', UserModel::TABLE.'.name AS assignee_name', UserModel::TABLE.'.email AS assignee_email', diff --git a/app/Pagination/ProjectPagination.php b/app/Pagination/ProjectPagination.php new file mode 100644 index 00000000..8f1fa87c --- /dev/null +++ b/app/Pagination/ProjectPagination.php @@ -0,0 +1,35 @@ +paginator + ->setUrl('DashboardController', $method, array('pagination' => 'projects', 'user_id' => $user_id)) + ->setMax($max) + ->setOrder(ProjectModel::TABLE.'.name') + ->setQuery($this->projectModel->getQueryColumnStats($this->projectPermissionModel->getActiveProjectIds($user_id))) + ->calculateOnlyIf($this->request->getStringParam('pagination') === 'projects'); + } +} diff --git a/app/Pagination/SubtaskPagination.php b/app/Pagination/SubtaskPagination.php new file mode 100644 index 00000000..f0cd6148 --- /dev/null +++ b/app/Pagination/SubtaskPagination.php @@ -0,0 +1,36 @@ +paginator + ->setUrl('DashboardController', $method, array('pagination' => 'subtasks', 'user_id' => $user_id)) + ->setMax($max) + ->setOrder(TaskModel::TABLE.'.id') + ->setQuery($this->subtaskModel->getUserQuery($user_id, array(SubtaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS))) + ->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks'); + } +} diff --git a/app/Pagination/TaskPagination.php b/app/Pagination/TaskPagination.php new file mode 100644 index 00000000..a395ab84 --- /dev/null +++ b/app/Pagination/TaskPagination.php @@ -0,0 +1,35 @@ +paginator + ->setUrl('DashboardController', $method, array('pagination' => 'tasks', 'user_id' => $user_id)) + ->setMax($max) + ->setOrder(TaskModel::TABLE.'.id') + ->setQuery($this->taskFinderModel->getUserQuery($user_id)) + ->calculateOnlyIf($this->request->getStringParam('pagination') === 'tasks'); + } +} diff --git a/app/Pagination/UserPagination.php b/app/Pagination/UserPagination.php new file mode 100644 index 00000000..430b7d2f --- /dev/null +++ b/app/Pagination/UserPagination.php @@ -0,0 +1,32 @@ +paginator + ->setUrl('UserListController', 'show') + ->setMax(30) + ->setOrder(UserModel::TABLE.'.username') + ->setQuery($this->userModel->getQuery()) + ->calculate(); + } +} diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 9a71148b..aab41c74 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -122,6 +122,12 @@ class ClassProvider implements ServiceProviderInterface 'TaskExport', 'TransitionExport', ), + 'Pagination' => array( + 'TaskPagination', + 'SubtaskPagination', + 'ProjectPagination', + 'UserPagination', + ), 'Core' => array( 'DateParser', 'Lexer', diff --git a/app/Template/dashboard/projects.php b/app/Template/dashboard/projects.php index 962e4d83..3a7f1d86 100644 --- a/app/Template/dashboard/projects.php +++ b/app/Template/dashboard/projects.php @@ -6,8 +6,8 @@ - - + + diff --git a/app/Template/dashboard/subtasks.php b/app/Template/dashboard/subtasks.php index 8e0aa3ce..ca550e4c 100644 --- a/app/Template/dashboard/subtasks.php +++ b/app/Template/dashboard/subtasks.php @@ -6,10 +6,10 @@
    order('Id', 'id') ?>order('', 'is_private') ?>order('Id', \Kanboard\Model\ProjectModel::TABLE.'.id') ?>order('', \Kanboard\Model\ProjectModel::TABLE.'.is_private') ?> order(t('Project'), \Kanboard\Model\ProjectModel::TABLE.'.name') ?>
    - + - + getCollection() as $subtask): ?> diff --git a/app/Template/dashboard/tasks.php b/app/Template/dashboard/tasks.php index b3257c33..d9cb4f9e 100644 --- a/app/Template/dashboard/tasks.php +++ b/app/Template/dashboard/tasks.php @@ -6,12 +6,12 @@
    order('Id', 'tasks.id') ?>order('Id', \Kanboard\Model\TaskModel::TABLE.'.id') ?> order(t('Project'), 'project_name') ?> order(t('Task'), 'task_name') ?>order(t('Subtask'), 'title') ?>order(t('Subtask'), \Kanboard\Model\SubtaskModel::TABLE.'.title') ?>
    - + - - + + - + getCollection() as $task): ?> diff --git a/tests/units/Model/TaskFinderModelTest.php b/tests/units/Model/TaskFinderModelTest.php index 72da3b6d..b2e2bd84 100644 --- a/tests/units/Model/TaskFinderModelTest.php +++ b/tests/units/Model/TaskFinderModelTest.php @@ -9,7 +9,7 @@ use Kanboard\Model\ProjectModel; class TaskFinderModelTest extends Base { - public function testGetTasksForDashboard() + public function testGetTasksForDashboardWithHiddenColumn() { $taskCreationModel = new TaskCreationModel($this->container); $taskFinderModel = new TaskFinderModel($this->container); diff --git a/tests/units/Pagination/ProjectPaginationTest.php b/tests/units/Pagination/ProjectPaginationTest.php new file mode 100644 index 00000000..35532d0d --- /dev/null +++ b/tests/units/Pagination/ProjectPaginationTest.php @@ -0,0 +1,35 @@ +container); + $projectUserRoleModel = new ProjectUserRoleModel($this->container); + $userModel = new UserModel($this->container); + $projectPagination = new ProjectPagination($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(2, $projectModel->create(array('name' => 'Project #2', 'is_private' => 1))); + $this->assertEquals(3, $projectModel->create(array('name' => 'Project #3'))); + $this->assertEquals(4, $projectModel->create(array('name' => 'Project #4', 'is_private' => 1))); + + $this->assertEquals(2, $userModel->create(array('username' => 'test'))); + $this->assertTrue($projectUserRoleModel->addUser(1, 2, Role::PROJECT_MANAGER)); + $this->assertTrue($projectUserRoleModel->addUser(2, 2, Role::PROJECT_MANAGER)); + + $this->assertCount(2, $projectPagination->getDashboardPaginator(2, 'projects', 5)->getCollection()); + $this->assertCount(0, $projectPagination->getDashboardPaginator(3, 'projects', 5)->getCollection()); + $this->assertCount(2, $projectPagination->getDashboardPaginator(2, 'projects', 5)->setOrder(ProjectModel::TABLE.'.id')->getCollection()); + $this->assertCount(2, $projectPagination->getDashboardPaginator(2, 'projects', 5)->setOrder(ProjectModel::TABLE.'.is_private')->getCollection()); + $this->assertCount(2, $projectPagination->getDashboardPaginator(2, 'projects', 5)->setOrder(ProjectModel::TABLE.'.name')->getCollection()); + } +} diff --git a/tests/units/Pagination/SubtaskPaginationTest.php b/tests/units/Pagination/SubtaskPaginationTest.php new file mode 100644 index 00000000..26a51a8b --- /dev/null +++ b/tests/units/Pagination/SubtaskPaginationTest.php @@ -0,0 +1,36 @@ +container); + $projectModel = new ProjectModel($this->container); + $subtaskModel = new SubtaskModel($this->container); + $subtaskPagination = new SubtaskPagination($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 1))); + $this->assertEquals(1, $subtaskModel->create(array('task_id' => 1, 'title' => 'subtask #1', 'user_id' => 1))); + $this->assertEquals(2, $subtaskModel->create(array('task_id' => 2, 'title' => 'subtask #1', 'user_id' => 1))); + $this->assertEquals(3, $subtaskModel->create(array('task_id' => 1, 'title' => 'subtask #1', 'user_id' => 1))); + $this->assertEquals(4, $subtaskModel->create(array('task_id' => 2, 'title' => 'subtask #1'))); + $this->assertEquals(5, $subtaskModel->create(array('task_id' => 1, 'title' => 'subtask #1'))); + + $this->assertCount(3, $subtaskPagination->getDashboardPaginator(1, 'subtasks', 5)->getCollection()); + $this->assertCount(0, $subtaskPagination->getDashboardPaginator(2, 'subtasks', 5)->getCollection()); + $this->assertCount(3, $subtaskPagination->getDashboardPaginator(1, 'subtasks', 5)->setOrder(TaskModel::TABLE.'.id')->getCollection()); + $this->assertCount(3, $subtaskPagination->getDashboardPaginator(1, 'subtasks', 5)->setOrder('project_name')->getCollection()); + $this->assertCount(3, $subtaskPagination->getDashboardPaginator(1, 'subtasks', 5)->setOrder('task_name')->getCollection()); + $this->assertCount(3, $subtaskPagination->getDashboardPaginator(1, 'subtasks', 5)->setOrder(SubtaskModel::TABLE.'.title')->getCollection()); + } +} diff --git a/tests/units/Pagination/TaskPaginationTest.php b/tests/units/Pagination/TaskPaginationTest.php new file mode 100644 index 00000000..027212e2 --- /dev/null +++ b/tests/units/Pagination/TaskPaginationTest.php @@ -0,0 +1,30 @@ +container); + $projectModel = new ProjectModel($this->container); + $taskPagination = new TaskPagination($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task #2', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 1))); + + $this->assertCount(1, $taskPagination->getDashboardPaginator(1, 'tasks', 5)->getCollection()); + $this->assertCount(0, $taskPagination->getDashboardPaginator(2, 'tasks', 5)->getCollection()); + $this->assertCount(1, $taskPagination->getDashboardPaginator(1, 'tasks', 5)->setOrder(TaskModel::TABLE.'.id')->getCollection()); + $this->assertCount(1, $taskPagination->getDashboardPaginator(1, 'tasks', 5)->setOrder('project_name')->getCollection()); + $this->assertCount(1, $taskPagination->getDashboardPaginator(1, 'tasks', 5)->setOrder(TaskModel::TABLE.'.title')->getCollection()); + $this->assertCount(1, $taskPagination->getDashboardPaginator(1, 'tasks', 5)->setOrder(TaskModel::TABLE.'.priority')->getCollection()); + $this->assertCount(1, $taskPagination->getDashboardPaginator(1, 'tasks', 5)->setOrder(TaskModel::TABLE.'.date_due')->getCollection()); + } +} diff --git a/tests/units/Pagination/UserPaginationTest.php b/tests/units/Pagination/UserPaginationTest.php new file mode 100644 index 00000000..c475aacd --- /dev/null +++ b/tests/units/Pagination/UserPaginationTest.php @@ -0,0 +1,27 @@ +container); + $userPagination = new UserPagination($this->container); + + $this->assertEquals(2, $userModel->create(array('username' => 'test1'))); + $this->assertEquals(3, $userModel->create(array('username' => 'test2'))); + + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('id')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('username')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('name')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('email')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('role')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('twofactor_activated')->setDirection('DESC')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('is_ldap_user')->getCollection()); + $this->assertCount(3, $userPagination->getListingPaginator()->setOrder('is_active')->getCollection()); + } +} -- cgit v1.2.3 From 92a5a0f8607e136e42e411a8b7aa9e948d3e3611 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 31 Jul 2016 11:28:33 -0400 Subject: Cleanup events and stuff before processing job in worker --- app/Console/WorkerCommand.php | 1 - app/Core/Action/ActionManager.php | 16 +++++++++++ app/Core/Queue/JobHandler.php | 14 +++++++++- tests/units/Base.php | 7 +++++ tests/units/Core/Action/ActionManagerTest.php | 40 +++++++++++++++++++++++---- 5 files changed, 71 insertions(+), 7 deletions(-) (limited to 'app/Core') diff --git a/app/Console/WorkerCommand.php b/app/Console/WorkerCommand.php index 86727a60..e332624b 100644 --- a/app/Console/WorkerCommand.php +++ b/app/Console/WorkerCommand.php @@ -23,7 +23,6 @@ class WorkerCommand extends BaseCommand protected function execute(InputInterface $input, OutputInterface $output) { - $this->dispatcher->dispatch('app.bootstrap'); $this->queueManager->listen(); } } diff --git a/app/Core/Action/ActionManager.php b/app/Core/Action/ActionManager.php index 1dfd820c..aec9ef02 100644 --- a/app/Core/Action/ActionManager.php +++ b/app/Core/Action/ActionManager.php @@ -139,4 +139,20 @@ class ActionManager extends Base return $this; } + + /** + * Remove all listeners for automated actions + * + * @access public + */ + public function removeEvents() + { + foreach ($this->dispatcher->getListeners() as $eventName => $listeners) { + foreach ($listeners as $listener) { + if (is_array($listener) && $listener[0] instanceof ActionBase) { + $this->dispatcher->removeListener($eventName, $listener); + } + } + } + } } diff --git a/app/Core/Queue/JobHandler.php b/app/Core/Queue/JobHandler.php index 326f3cef..11c1fb69 100644 --- a/app/Core/Queue/JobHandler.php +++ b/app/Core/Queue/JobHandler.php @@ -43,8 +43,8 @@ class JobHandler extends Base try { $className = $payload['class']; - $this->memoryCache->flush(); $this->prepareJobSession($payload['user_id']); + $this->prepareJobEnvironment(); if (DEBUG) { $this->logger->debug(__METHOD__.' Received job => '.$className.' ('.getmypid().')'); @@ -75,4 +75,16 @@ class JobHandler extends Base $this->userSession->initialize($user); } } + + /** + * Flush in-memory caching and specific events + * + * @access protected + */ + protected function prepareJobEnvironment() + { + $this->memoryCache->flush(); + $this->actionManager->removeEvents(); + $this->dispatcher->dispatch('app.bootstrap'); + } } diff --git a/tests/units/Base.php b/tests/units/Base.php index c471ee31..e44223ce 100644 --- a/tests/units/Base.php +++ b/tests/units/Base.php @@ -16,6 +16,11 @@ abstract class Base extends PHPUnit_Framework_TestCase { protected $container; + /** + * @var EventDispatcher + */ + protected $dispatcher; + public function setUp() { date_default_timezone_set('UTC'); @@ -49,6 +54,8 @@ abstract class Base extends PHPUnit_Framework_TestCase new Stopwatch ); + $this->dispatcher = $this->container['dispatcher']; + $this->container['db']->getStatementHandler()->withLogging(); $this->container['logger'] = new Logger(); diff --git a/tests/units/Core/Action/ActionManagerTest.php b/tests/units/Core/Action/ActionManagerTest.php index e7c2071f..4878c0c9 100644 --- a/tests/units/Core/Action/ActionManagerTest.php +++ b/tests/units/Core/Action/ActionManagerTest.php @@ -96,7 +96,7 @@ class ActionManagerTest extends Base $actions = $actionManager->getAvailableActions(); $actionManager->attachEvents(); - $this->assertEmpty($this->container['dispatcher']->getListeners()); + $this->assertEmpty($this->dispatcher->getListeners()); $this->assertEquals(1, $projectModel->create(array('name' =>'test'))); $this->assertEquals(1, $actionModel->create(array( @@ -107,7 +107,7 @@ class ActionManagerTest extends Base ))); $actionManager->attachEvents(); - $listeners = $this->container['dispatcher']->getListeners(TaskModel::EVENT_CREATE); + $listeners = $this->dispatcher->getListeners(TaskModel::EVENT_CREATE); $this->assertCount(1, $listeners); $this->assertInstanceOf(get_class($actionTaskAssignColorColumn), $listeners[0][0]); @@ -148,7 +148,7 @@ class ActionManagerTest extends Base $actionManager->attachEvents(); - $listeners = $this->container['dispatcher']->getListeners(TaskModel::EVENT_MOVE_COLUMN); + $listeners = $this->dispatcher->getListeners(TaskModel::EVENT_MOVE_COLUMN); $this->assertCount(1, $listeners); $this->assertInstanceOf(get_class($actionTaskAssignColorColumn), $listeners[0][0]); @@ -158,7 +158,6 @@ class ActionManagerTest extends Base public function testThatEachListenerAreDifferentInstance() { $projectModel = new ProjectModel($this->container); - $projectUserRoleModel = new ProjectUserRoleModel($this->container); $actionModel = new ActionModel($this->container); $actionTaskAssignColorColumn = new TaskAssignColorColumn($this->container); $actionManager = new ActionManager($this->container); @@ -183,7 +182,7 @@ class ActionManagerTest extends Base $actionManager->attachEvents(); - $listeners = $this->container['dispatcher']->getListeners(TaskModel::EVENT_MOVE_COLUMN); + $listeners = $this->dispatcher->getListeners(TaskModel::EVENT_MOVE_COLUMN); $this->assertCount(2, $listeners); $this->assertFalse($listeners[0][0] === $listeners[1][0]); @@ -193,4 +192,35 @@ class ActionManagerTest extends Base $this->assertEquals(1, $listeners[1][0]->getParam('column_id')); $this->assertEquals('red', $listeners[1][0]->getParam('color_id')); } + + public function testRemoveEvents() + { + $projectModel = new ProjectModel($this->container); + $actionModel = new ActionModel($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' =>'test'))); + $this->assertEquals(1, $actionModel->create(array( + 'project_id' => 1, + 'event_name' => TaskModel::EVENT_CREATE, + 'action_name' => key($actions), + 'params' => array('column_id' => 1, 'color_id' => 'red'), + ))); + + $actionManager->attachEvents(); + $this->dispatcher->addListener(TaskModel::EVENT_CREATE, function () {}); + + $listeners = $this->dispatcher->getListeners(TaskModel::EVENT_CREATE); + $this->assertCount(2, $listeners); + + $actionManager->removeEvents(); + + $listeners = $this->dispatcher->getListeners(TaskModel::EVENT_CREATE); + $this->assertCount(1, $listeners); + $this->assertNotInstanceOf(get_class($actionTaskAssignColorColumn), $listeners[0]); + } } -- cgit v1.2.3 From 74b2a1ffb43c704be64c7ac3215bdb2f29b12caf Mon Sep 17 00:00:00 2001 From: Thomas Lutz Date: Sun, 7 Aug 2016 17:30:17 +0200 Subject: fix selfsigned ssl certificates swift mail --- app/Core/Mail/Transport/Smtp.php | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app/Core') diff --git a/app/Core/Mail/Transport/Smtp.php b/app/Core/Mail/Transport/Smtp.php index 66f0a3aa..ec7eb541 100644 --- a/app/Core/Mail/Transport/Smtp.php +++ b/app/Core/Mail/Transport/Smtp.php @@ -24,6 +24,9 @@ class Smtp extends Mail $transport->setUsername(MAIL_SMTP_USERNAME); $transport->setPassword(MAIL_SMTP_PASSWORD); $transport->setEncryption(MAIL_SMTP_ENCRYPTION); + if (HTTP_VERIFY_SSL_CERTIFICATE === false) { + $transport->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false, 'verify_peer_name' => false,))); + } return $transport; } -- cgit v1.2.3 From 508a5eaf850c3146090763c4c62ac9a3f84c9594 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 7 Aug 2016 13:43:18 -0400 Subject: Re-indent code of PR #2560 --- app/Core/Mail/Transport/Smtp.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'app/Core') diff --git a/app/Core/Mail/Transport/Smtp.php b/app/Core/Mail/Transport/Smtp.php index ec7eb541..1f4e54ce 100644 --- a/app/Core/Mail/Transport/Smtp.php +++ b/app/Core/Mail/Transport/Smtp.php @@ -25,7 +25,13 @@ class Smtp extends Mail $transport->setPassword(MAIL_SMTP_PASSWORD); $transport->setEncryption(MAIL_SMTP_ENCRYPTION); if (HTTP_VERIFY_SSL_CERTIFICATE === false) { - $transport->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false, 'verify_peer_name' => false,))); + $transport->setStreamOptions(array( + 'ssl' => array( + 'allow_self_signed' => true, + 'verify_peer' => false, + 'verify_peer_name' => false, + ) + )); } return $transport; -- cgit v1.2.3 From 4ffaba2ba0dd6b5810adea1916080c3b645f3d29 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 13 Aug 2016 14:23:53 -0400 Subject: Add reference hooks --- ChangeLog | 1 + app/Core/Filter/LexerBuilder.php | 2 +- app/Core/Plugin/Hook.php | 17 ++++++++++ app/Formatter/BoardFormatter.php | 11 ++++--- app/Pagination/SubtaskPagination.php | 5 ++- app/Pagination/TaskPagination.php | 5 ++- doc/plugin-hooks.markdown | 25 +++++++++++++++ tests/units/Core/Plugin/HookTest.php | 62 ++++++++++++++++++++++-------------- 8 files changed, 97 insertions(+), 31 deletions(-) (limited to 'app/Core') diff --git a/ChangeLog b/ChangeLog index 68537a3a..25ce7eea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ Version 1.0.33 (unreleased) Improvements: +* Add "reference" hooks * Show project name in task forms * Convert vanilla CSS to SASS diff --git a/app/Core/Filter/LexerBuilder.php b/app/Core/Filter/LexerBuilder.php index 626d7614..e3ab725b 100644 --- a/app/Core/Filter/LexerBuilder.php +++ b/app/Core/Filter/LexerBuilder.php @@ -51,7 +51,7 @@ class LexerBuilder */ public function __construct() { - $this->lexer = new Lexer; + $this->lexer = new Lexer(); $this->queryBuilder = new QueryBuilder(); } diff --git a/app/Core/Plugin/Hook.php b/app/Core/Plugin/Hook.php index ade69150..ca197937 100644 --- a/app/Core/Plugin/Hook.php +++ b/app/Core/Plugin/Hook.php @@ -96,4 +96,21 @@ class Hook return null; } + + /** + * Hook with reference + * + * @access public + * @param string $hook + * @param mixed $param + * @return mixed + */ + public function reference($hook, &$param) + { + foreach ($this->getListeners($hook) as $listener) { + $listener($param); + } + + return $param; + } } diff --git a/app/Formatter/BoardFormatter.php b/app/Formatter/BoardFormatter.php index 350dde6c..df443a52 100644 --- a/app/Formatter/BoardFormatter.php +++ b/app/Formatter/BoardFormatter.php @@ -44,6 +44,13 @@ class BoardFormatter extends BaseFormatter implements FormatterInterface { $swimlanes = $this->swimlaneModel->getSwimlanes($this->projectId); $columns = $this->columnModel->getAll($this->projectId); + + if (empty($swimlanes) || empty($columns)) { + return array(); + } + + $this->hook->reference('formatter:board:query', $this->query); + $tasks = $this->query ->eq(TaskModel::TABLE.'.project_id', $this->projectId) ->asc(TaskModel::TABLE.'.position') @@ -52,10 +59,6 @@ class BoardFormatter extends BaseFormatter implements FormatterInterface $task_ids = array_column($tasks, 'id'); $tags = $this->taskTagModel->getTagsByTasks($task_ids); - if (empty($swimlanes) || empty($columns)) { - return array(); - } - return BoardSwimlaneFormatter::getInstance($this->container) ->withSwimlanes($swimlanes) ->withColumns($columns) diff --git a/app/Pagination/SubtaskPagination.php b/app/Pagination/SubtaskPagination.php index f0cd6148..c55d0fb4 100644 --- a/app/Pagination/SubtaskPagination.php +++ b/app/Pagination/SubtaskPagination.php @@ -26,11 +26,14 @@ class SubtaskPagination extends Base */ public function getDashboardPaginator($user_id, $method, $max) { + $query = $this->subtaskModel->getUserQuery($user_id, array(SubtaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS)); + $this->hook->reference('pagination:dashboard:subtask:query', $query); + return $this->paginator ->setUrl('DashboardController', $method, array('pagination' => 'subtasks', 'user_id' => $user_id)) ->setMax($max) ->setOrder(TaskModel::TABLE.'.id') - ->setQuery($this->subtaskModel->getUserQuery($user_id, array(SubtaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS))) + ->setQuery($query) ->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks'); } } diff --git a/app/Pagination/TaskPagination.php b/app/Pagination/TaskPagination.php index a395ab84..5fe986e7 100644 --- a/app/Pagination/TaskPagination.php +++ b/app/Pagination/TaskPagination.php @@ -25,11 +25,14 @@ class TaskPagination extends Base */ public function getDashboardPaginator($user_id, $method, $max) { + $query = $this->taskFinderModel->getUserQuery($user_id); + $this->hook->reference('pagination:dashboard:task:query', $query); + return $this->paginator ->setUrl('DashboardController', $method, array('pagination' => 'tasks', 'user_id' => $user_id)) ->setMax($max) ->setOrder(TaskModel::TABLE.'.id') - ->setQuery($this->taskFinderModel->getUserQuery($user_id)) + ->setQuery($query) ->calculateOnlyIf($this->request->getStringParam('pagination') === 'tasks'); } } diff --git a/doc/plugin-hooks.markdown b/doc/plugin-hooks.markdown index 787c62df..5e01e93a 100644 --- a/doc/plugin-hooks.markdown +++ b/doc/plugin-hooks.markdown @@ -115,6 +115,31 @@ List of asset Hooks: - `template:layout:css` - `template:layout:js` + +Reference hooks +--------------- + +Reference hooks are passing a variable by reference. + +Example: + +```php +$this->hook->on('formatter:board:query', function (\PicoDb\Table &query) { + $query->eq('color_id', 'red'); +}); +``` + +The code above will show only tasks in red on the board. + +List of reference hooks: + +| Hook | Description | +|--------------------------------------------|---------------------------------------------------------------| +| `formatter:board:query` | Alter database query before rendering board | +| `pagination:dashboard:task:query` | Alter database query for tasks pagination on the dashboard | +| `pagination:dashboard:subtask:query` | Alter database query for subtasks pagination on the dashboard | + + Template Hooks -------------- diff --git a/tests/units/Core/Plugin/HookTest.php b/tests/units/Core/Plugin/HookTest.php index d1c139b3..acadede0 100644 --- a/tests/units/Core/Plugin/HookTest.php +++ b/tests/units/Core/Plugin/HookTest.php @@ -8,89 +8,103 @@ class HookTest extends Base { public function testGetListeners() { - $h = new Hook; - $this->assertEmpty($h->getListeners('myhook')); + $hook = new Hook; + $this->assertEmpty($hook->getListeners('myhook')); - $h->on('myhook', 'A'); - $h->on('myhook', 'B'); + $hook->on('myhook', 'A'); + $hook->on('myhook', 'B'); - $this->assertEquals(array('A', 'B'), $h->getListeners('myhook')); + $this->assertEquals(array('A', 'B'), $hook->getListeners('myhook')); } public function testExists() { - $h = new Hook; - $this->assertFalse($h->exists('myhook')); + $hook = new Hook; + $this->assertFalse($hook->exists('myhook')); - $h->on('myhook', 'A'); + $hook->on('myhook', 'A'); - $this->assertTrue($h->exists('myhook')); + $this->assertTrue($hook->exists('myhook')); } public function testMergeWithNoBinding() { - $h = new Hook; + $hook = new Hook; $values = array('A', 'B'); - $result = $h->merge('myhook', $values, array('p' => 'c')); + $result = $hook->merge('myhook', $values, array('p' => 'c')); $this->assertEquals($values, $result); } public function testMergeWithBindings() { - $h = new Hook; + $hook = new Hook; $values = array('A', 'B'); $expected = array('A', 'B', 'c', 'D'); - $h->on('myhook', function ($p) { + $hook->on('myhook', function ($p) { return array($p); }); - $h->on('myhook', function () { + $hook->on('myhook', function () { return array('D'); }); - $result = $h->merge('myhook', $values, array('p' => 'c')); + $result = $hook->merge('myhook', $values, array('p' => 'c')); $this->assertEquals($expected, $result); $this->assertEquals($expected, $values); } public function testMergeWithBindingButReturningBadData() { - $h = new Hook; + $hook = new Hook; $values = array('A', 'B'); $expected = array('A', 'B'); - $h->on('myhook', function () { + $hook->on('myhook', function () { return 'string'; }); - $result = $h->merge('myhook', $values); + $result = $hook->merge('myhook', $values); $this->assertEquals($expected, $result); $this->assertEquals($expected, $values); } public function testFirstWithNoBinding() { - $h = new Hook; + $hook = new Hook; - $result = $h->first('myhook', array('p' => 2)); + $result = $hook->first('myhook', array('p' => 2)); $this->assertEquals(null, $result); } public function testFirstWithMultipleBindings() { - $h = new Hook; + $hook = new Hook; - $h->on('myhook', function ($p) { + $hook->on('myhook', function ($p) { return $p + 1; }); - $h->on('myhook', function ($p) { + $hook->on('myhook', function ($p) { return $p; }); - $result = $h->first('myhook', array('p' => 3)); + $result = $hook->first('myhook', array('p' => 3)); $this->assertEquals(4, $result); } + + public function testHookWithReference() + { + $hook = new Hook(); + + $hook->on('myhook', function (&$p) { + $p = 2; + }); + + $param = 123; + $result = $hook->reference('myhook', $param); + $this->assertSame(2, $result); + $this->assertSame(2, $param); + } } -- cgit v1.2.3
    order('Id', 'tasks.id') ?>order('Id', \Kanboard\Model\TaskModel::TABLE.'.id') ?> order(t('Project'), 'project_name') ?>order(t('Task'), 'title') ?>order(t('Priority'), 'tasks.priority') ?>order(t('Task'), \Kanboard\Model\TaskModel::TABLE.'.title') ?>order(t('Priority'), \Kanboard\Model\TaskModel::TABLE.'.priority') ?> order(t('Due date'), 'date_due') ?>order(t('Due date'), \Kanboard\Model\TaskModel::TABLE.'.date_due') ?> order(t('Column'), 'column_title') ?>