From 11a774e555786182dd634676811e3c58f316dad0 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 18 Feb 2017 20:21:48 -0500 Subject: Send tasks by email --- ChangeLog | 1 + app/Controller/TaskMailController.php | 55 ++++++++++++++++++++++++++ app/ServiceProvider/AuthenticationProvider.php | 2 + app/Template/task/dropdown.php | 3 ++ app/Template/task_mail/create.php | 17 ++++++++ app/Template/task_mail/email.php | 46 +++++++++++++++++++++ app/Validator/TaskValidator.php | 23 +++++++++++ tests/units/Validator/TaskValidatorTest.php | 17 ++++++++ 8 files changed, 164 insertions(+) create mode 100644 app/Controller/TaskMailController.php create mode 100644 app/Template/task_mail/create.php create mode 100644 app/Template/task_mail/email.php diff --git a/ChangeLog b/ChangeLog index e7b81e7a..85daac10 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ Version 1.0.40 (unreleased) New features: * Send comments by email +* Send tasks by email * Add Reply-To header to emails sent from Kanboard * Upload Sqlite database from user interface diff --git a/app/Controller/TaskMailController.php b/app/Controller/TaskMailController.php new file mode 100644 index 00000000..e95ddf03 --- /dev/null +++ b/app/Controller/TaskMailController.php @@ -0,0 +1,55 @@ +getProject(); + $task = $this->getTask(); + + $this->response->html($this->helper->layout->task('task_mail/create', array( + 'values' => $values, + 'errors' => $errors, + 'task' => $task, + 'project' => $project, + ))); + } + + public function send() + { + $task = $this->getTask(); + $values = $this->request->getValues(); + + list($valid, $errors) = $this->taskValidator->validateEmailCreation($values); + + if ($valid) { + $this->sendByEmail($values, $task); + $this->flash->success(t('Task sent by email successfully.')); + $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'), true); + } else { + $this->create($values, $errors); + } + } + + protected function sendByEmail(array $values, array $task) + { + $html = $this->template->render('task_mail/email', array( + 'task' => $task, + )); + + $this->emailClient->send( + $values['email'], + $values['email'], + $values['subject'], + $html + ); + } +} diff --git a/app/ServiceProvider/AuthenticationProvider.php b/app/ServiceProvider/AuthenticationProvider.php index d315daca..868696e0 100644 --- a/app/ServiceProvider/AuthenticationProvider.php +++ b/app/ServiceProvider/AuthenticationProvider.php @@ -85,6 +85,7 @@ class AuthenticationProvider implements ServiceProviderInterface $acl->add('ColumnController', '*', Role::PROJECT_MANAGER); $acl->add('CommentController', array('create', 'save', 'edit', 'update', 'confirm', 'remove'), Role::PROJECT_MEMBER); $acl->add('CommentListController', array('save'), Role::PROJECT_MEMBER); + $acl->add('CommentMailController', '*', Role::PROJECT_MEMBER); $acl->add('CustomFilterController', '*', Role::PROJECT_MEMBER); $acl->add('ExportController', '*', Role::PROJECT_MANAGER); $acl->add('TaskFileController', array('screenshot', 'create', 'save', 'remove', 'confirm'), Role::PROJECT_MEMBER); @@ -110,6 +111,7 @@ class AuthenticationProvider implements ServiceProviderInterface $acl->add('TaskExternalLinkController', '*', Role::PROJECT_MEMBER); $acl->add('TaskModificationController', '*', Role::PROJECT_MEMBER); $acl->add('TaskStatusController', '*', Role::PROJECT_MEMBER); + $acl->add('TaskMailController', '*', Role::PROJECT_MEMBER); $acl->add('UserAjaxController', array('mention'), Role::PROJECT_MEMBER); return $acl; diff --git a/app/Template/task/dropdown.php b/app/Template/task/dropdown.php index 21b04598..f35abc79 100644 --- a/app/Template/task/dropdown.php +++ b/app/Template/task/dropdown.php @@ -36,6 +36,9 @@
  • modal->small('clone', t('Move to another project'), 'TaskDuplicationController', 'move', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
  • +
  • + modal->small('paper-plane', t('Send by email'), 'TaskMailController', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?> +
  • projectRole->canRemoveTask($task)): ?>
  • modal->confirm('trash-o', t('Remove'), 'TaskSuppressionController', 'confirm', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?> diff --git a/app/Template/task_mail/create.php b/app/Template/task_mail/create.php new file mode 100644 index 00000000..9a1a26b3 --- /dev/null +++ b/app/Template/task_mail/create.php @@ -0,0 +1,17 @@ + +
    + form->csrf() ?> + + form->label(t('Email'), 'email') ?> + form->email('email', $values, $errors, array('autofocus', 'required', 'tabindex="1"')) ?> + + form->label(t('Subject'), 'subject') ?> + form->text('subject', $values, $errors, array('required', 'tabindex="2"')) ?> + + modal->submitButtons(array( + 'submitLabel' => t('Send by email'), + 'tabindex' => 3, + )) ?> +
    diff --git a/app/Template/task_mail/email.php b/app/Template/task_mail/email.php new file mode 100644 index 00000000..51f88178 --- /dev/null +++ b/app/Template/task_mail/email.php @@ -0,0 +1,46 @@ +

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

    + + + + +

    + text->markdown($task['description'], true) ?> + + +render('notification/footer', array('task' => $task, 'application_url' => $this->app->config('application_url'))) ?> \ No newline at end of file diff --git a/app/Validator/TaskValidator.php b/app/Validator/TaskValidator.php index 7ca377d9..f9441c8b 100644 --- a/app/Validator/TaskValidator.php +++ b/app/Validator/TaskValidator.php @@ -204,4 +204,27 @@ class TaskValidator extends BaseValidator $v->getErrors() ); } + + /** + * Validate task email creation + * + * @access public + * @param array $values Required parameters to save an action + * @return array $valid, $errors [0] = Success or not, [1] = List of errors + */ + public function validateEmailCreation(array $values) + { + $rules = array( + new Validators\Required('subject', t('This field is required')), + new Validators\Required('email', t('This field is required')), + new Validators\Email('email', t('Email address invalid')), + ); + + $v = new Validator($values, $rules); + + return array( + $v->execute(), + $v->getErrors() + ); + } } diff --git a/tests/units/Validator/TaskValidatorTest.php b/tests/units/Validator/TaskValidatorTest.php index e9d9ac09..0c7fead7 100644 --- a/tests/units/Validator/TaskValidatorTest.php +++ b/tests/units/Validator/TaskValidatorTest.php @@ -6,6 +6,23 @@ use Kanboard\Validator\TaskValidator; class TaskValidatorTest extends Base { + public function testValidationEmailCreation() + { + $taskValidator = new TaskValidator($this->container); + + $result = $taskValidator->validateEmailCreation(array('email' => 'test@localhost', 'subject' => 'test')); + $this->assertTrue($result[0]); + + $result = $taskValidator->validateEmailCreation(array('email' => 'test', 'subject' => 'test')); + $this->assertFalse($result[0]); + + $result = $taskValidator->validateEmailCreation(array('subject' => 'test')); + $this->assertFalse($result[0]); + + $result = $taskValidator->validateEmailCreation(array('email' => 'test@localhost')); + $this->assertFalse($result[0]); + } + public function testRequiredFields() { $taskValidator = new TaskValidator($this->container); -- cgit v1.2.3