diff options
author | Frederic Guillot <fred@kanboard.net> | 2017-02-18 20:21:48 -0500 |
---|---|---|
committer | Frederic Guillot <fred@kanboard.net> | 2017-02-18 20:21:48 -0500 |
commit | 11a774e555786182dd634676811e3c58f316dad0 (patch) | |
tree | 4dd0092b45d15d1c6ae1db613e37eb9bb009c0ec | |
parent | 93c05371a882b3c07d16457479129e42a2999492 (diff) |
Send tasks by email
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | app/Controller/TaskMailController.php | 55 | ||||
-rw-r--r-- | app/ServiceProvider/AuthenticationProvider.php | 2 | ||||
-rw-r--r-- | app/Template/task/dropdown.php | 3 | ||||
-rw-r--r-- | app/Template/task_mail/create.php | 17 | ||||
-rw-r--r-- | app/Template/task_mail/email.php | 46 | ||||
-rw-r--r-- | app/Validator/TaskValidator.php | 23 | ||||
-rw-r--r-- | tests/units/Validator/TaskValidatorTest.php | 17 |
8 files changed, 164 insertions, 0 deletions
@@ -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 @@ +<?php + +namespace Kanboard\Controller; + +/** + * Class TaskMailController + * + * @package Kanboard\Controller + * @author Frederic Guillot + */ +class TaskMailController extends BaseController +{ + public function create(array $values = array(), array $errors = array()) + { + $project = $this->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 @@ <li> <?= $this->modal->small('clone', t('Move to another project'), 'TaskDuplicationController', 'move', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?> </li> + <li> + <?= $this->modal->small('paper-plane', t('Send by email'), 'TaskMailController', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?> + </li> <?php if ($this->projectRole->canRemoveTask($task)): ?> <li> <?= $this->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 @@ +<div class="page-header"> + <h2><?= $this->text->e($task['title']) ?> > <?= t('Send by email') ?></h2> +</div> +<form method="post" action="<?= $this->url->href('TaskMailController', 'send', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>" autocomplete="off"> + <?= $this->form->csrf() ?> + + <?= $this->form->label(t('Email'), 'email') ?> + <?= $this->form->email('email', $values, $errors, array('autofocus', 'required', 'tabindex="1"')) ?> + + <?= $this->form->label(t('Subject'), 'subject') ?> + <?= $this->form->text('subject', $values, $errors, array('required', 'tabindex="2"')) ?> + + <?= $this->modal->submitButtons(array( + 'submitLabel' => t('Send by email'), + 'tabindex' => 3, + )) ?> +</form> 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 @@ +<h2><?= $this->text->e($task['title']) ?> (#<?= $task['id'] ?>)</h2> + +<ul> + <li> + <?= t('Project: %s', $task['project_name']) ?> + </li> + <li> + <?= t('Created:').' '.$this->dt->datetime($task['date_creation']) ?> + </li> + <?php if ($task['date_due']): ?> + <li> + <strong><?= t('Due date:').' '.$this->dt->date($task['date_due']) ?></strong> + </li> + <?php endif ?> + <?php if (! empty($task['creator_username'])): ?> + <li> + <?= t('Created by %s', $task['creator_name'] ?: $task['creator_username']) ?> + </li> + <?php endif ?> + <li> + <strong> + <?php if (! empty($task['assignee_username'])): ?> + <?= t('Assigned to %s', $task['assignee_name'] ?: $task['assignee_username']) ?> + <?php else: ?> + <?= t('There is nobody assigned') ?> + <?php endif ?> + </strong> + </li> + <li> + <?= t('Column on the board:') ?> + <strong><?= $this->text->e($task['column_title']) ?></strong> + </li> + <li><?= t('Task position:').' '.$this->text->e($task['position']) ?></li> + <?php if (! empty($task['category_name'])): ?> + <li> + <?= t('Category:') ?> <strong><?= $this->text->e($task['category_name']) ?></strong> + </li> + <?php endif ?> +</ul> + +<?php if (! empty($task['description'])): ?> + <h2><?= t('Description') ?></h2> + <?= $this->text->markdown($task['description'], true) ?> +<?php endif ?> + +<?= $this->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); |