diff options
author | Frédéric Guillot <fred@kanboard.net> | 2014-09-20 11:58:27 +0200 |
---|---|---|
committer | Frédéric Guillot <fred@kanboard.net> | 2014-09-20 11:58:27 +0200 |
commit | 5f96af82f26967f4614b89322a82a59cb48bd2a3 (patch) | |
tree | 98f527458d27f325cec7419dbb033b8f9f5f8b20 | |
parent | 95e54d1d300809cb8656c52d029f797ba5961a04 (diff) |
Split Task model into smaller classes
-rw-r--r-- | app/Controller/Action.php | 4 | ||||
-rw-r--r-- | app/Controller/Base.php | 3 | ||||
-rw-r--r-- | app/Controller/Board.php | 4 | ||||
-rw-r--r-- | app/Controller/Project.php | 2 | ||||
-rw-r--r-- | app/Controller/Task.php | 22 | ||||
-rw-r--r-- | app/Model/Base.php | 4 | ||||
-rw-r--r-- | app/Model/Color.php | 31 | ||||
-rw-r--r-- | app/Model/DateParser.php | 85 | ||||
-rw-r--r-- | app/Model/Task.php | 348 | ||||
-rw-r--r-- | app/Model/TaskExport.php | 132 | ||||
-rw-r--r-- | app/Model/TaskValidator.php | 170 | ||||
-rw-r--r-- | jsonrpc.php | 10 | ||||
-rwxr-xr-x | kanboard | 5 | ||||
-rw-r--r-- | tests/units/DateParserTest.php | 32 | ||||
-rw-r--r-- | tests/units/TaskExportTest.php | 48 | ||||
-rw-r--r-- | tests/units/TaskTest.php | 54 |
16 files changed, 533 insertions, 421 deletions
diff --git a/app/Controller/Action.php b/app/Controller/Action.php index b2f80009..0bf8ff0c 100644 --- a/app/Controller/Action.php +++ b/app/Controller/Action.php @@ -29,7 +29,7 @@ class Action extends Base 'columns_list' => $this->board->getColumnsList($project['id']), 'users_list' => $this->project->getUsersList($project['id']), 'projects_list' => $this->project->getList(false), - 'colors_list' => $this->task->getColors(), + 'colors_list' => $this->color->getList(), 'categories_list' => $this->category->getList($project['id']), 'menu' => 'projects', 'title' => t('Automatic actions') @@ -53,7 +53,7 @@ class Action extends Base 'columns_list' => $this->board->getColumnsList($project['id']), 'users_list' => $this->project->getUsersList($project['id']), 'projects_list' => $this->project->getList(false), - 'colors_list' => $this->task->getColors(), + 'colors_list' => $this->color->getList(), 'categories_list' => $this->category->getList($project['id']), 'project' => $project, 'menu' => 'projects', diff --git a/app/Controller/Base.php b/app/Controller/Base.php index 93749ea6..383b22d1 100644 --- a/app/Controller/Base.php +++ b/app/Controller/Base.php @@ -19,6 +19,7 @@ use Model\LastLogin; * @property \Model\Action $action * @property \Model\Board $board * @property \Model\Category $category + * @property \Model\Color $color * @property \Model\Comment $comment * @property \Model\Config $config * @property \Model\File $file @@ -28,6 +29,8 @@ use Model\LastLogin; * @property \Model\SubTask $subTask * @property \Model\Task $task * @property \Model\TaskHistory $taskHistory + * @property \Model\TaskExport $taskExport + * @property \Model\TaskValidator $taskValidator * @property \Model\CommentHistory $commentHistory * @property \Model\SubtaskHistory $subtaskHistory * @property \Model\User $user diff --git a/app/Controller/Board.php b/app/Controller/Board.php index f643408d..e002ce3b 100644 --- a/app/Controller/Board.php +++ b/app/Controller/Board.php @@ -88,7 +88,7 @@ class Board extends Base $values = $this->request->getValues(); $this->checkProjectPermissions($values['project_id']); - list($valid,) = $this->task->validateAssigneeModification($values); + list($valid,) = $this->taskValidator->validateAssigneeModification($values); if ($valid && $this->task->update($values)) { $this->session->flash(t('Task updated successfully.')); @@ -142,7 +142,7 @@ class Board extends Base $values = $this->request->getValues(); $this->checkProjectPermissions($values['project_id']); - list($valid,) = $this->task->validateCategoryModification($values); + list($valid,) = $this->taskValidator->validateCategoryModification($values); if ($valid && $this->task->update($values)) { $this->session->flash(t('Task updated successfully.')); diff --git a/app/Controller/Project.php b/app/Controller/Project.php index ef9eac6b..2459f094 100644 --- a/app/Controller/Project.php +++ b/app/Controller/Project.php @@ -72,7 +72,7 @@ class Project extends Base $to = $this->request->getStringParam('to'); if ($from && $to) { - $data = $this->task->export($project['id'], $from, $to); + $data = $this->taskExport->export($project['id'], $from, $to); $this->response->forceDownload('Export_'.date('Y_m_d_H_i_S').'.csv'); $this->response->csv($data); } diff --git a/app/Controller/Task.php b/app/Controller/Task.php index ef55fb57..d958c248 100644 --- a/app/Controller/Task.php +++ b/app/Controller/Task.php @@ -37,7 +37,7 @@ class Task extends Base 'category_id' => $this->request->getIntegerParam('category_id'), ); - list($valid,) = $this->task->validateCreation($values); + list($valid,) = $this->taskValidator->validateCreation($values); if ($valid && $this->task->create($values)) { $this->response->text('OK'); @@ -72,7 +72,7 @@ class Task extends Base 'subtasks' => $this->subTask->getAll($task['id']), 'task' => $task, 'columns_list' => $this->board->getColumnsList($task['project_id']), - 'colors_list' => $this->task->getColors(), + 'colors_list' => $this->color->getList(), 'title' => $task['title'], 'no_layout' => true, 'auto_refresh' => true, @@ -96,7 +96,7 @@ class Task extends Base 'subtasks' => $this->subTask->getAll($task['id']), 'task' => $task, 'columns_list' => $this->board->getColumnsList($task['project_id']), - 'colors_list' => $this->task->getColors(), + 'colors_list' => $this->color->getList(), 'menu' => 'tasks', 'title' => $task['title'], ))); @@ -124,7 +124,7 @@ class Task extends Base 'projects_list' => $this->project->getListByStatus(ProjectModel::ACTIVE), 'columns_list' => $this->board->getColumnsList($project_id), 'users_list' => $this->project->getUsersList($project_id), - 'colors_list' => $this->task->getColors(), + 'colors_list' => $this->color->getList(), 'categories_list' => $this->category->getList($project_id), 'menu' => 'tasks', 'title' => t('New task') @@ -143,7 +143,7 @@ class Task extends Base $this->checkProjectPermissions($values['project_id']); - list($valid, $errors) = $this->task->validateCreation($values); + list($valid, $errors) = $this->taskValidator->validateCreation($values); if ($valid) { @@ -170,7 +170,7 @@ class Task extends Base 'projects_list' => $this->project->getListByStatus(ProjectModel::ACTIVE), 'columns_list' => $this->board->getColumnsList($values['project_id']), 'users_list' => $this->project->getUsersList($values['project_id']), - 'colors_list' => $this->task->getColors(), + 'colors_list' => $this->color->getList(), 'categories_list' => $this->category->getList($values['project_id']), 'menu' => 'tasks', 'title' => t('New task') @@ -200,7 +200,7 @@ class Task extends Base 'errors' => array(), 'task' => $task, 'users_list' => $this->project->getUsersList($task['project_id']), - 'colors_list' => $this->task->getColors(), + 'colors_list' => $this->color->getList(), 'categories_list' => $this->category->getList($task['project_id']), 'ajax' => $this->request->isAjax(), 'menu' => 'tasks', @@ -224,7 +224,7 @@ class Task extends Base $task = $this->getTask(); $values = $this->request->getValues(); - list($valid, $errors) = $this->task->validateModification($values); + list($valid, $errors) = $this->taskValidator->validateModification($values); if ($valid) { @@ -249,7 +249,7 @@ class Task extends Base 'task' => $task, 'columns_list' => $this->board->getColumnsList($values['project_id']), 'users_list' => $this->project->getUsersList($values['project_id']), - 'colors_list' => $this->task->getColors(), + 'colors_list' => $this->color->getList(), 'categories_list' => $this->category->getList($values['project_id']), 'menu' => 'tasks', 'title' => t('Edit a task') @@ -387,7 +387,7 @@ class Task extends Base $values = $this->request->getValues(); - list($valid, $errors) = $this->task->validateDescriptionCreation($values); + list($valid, $errors) = $this->taskValidator->validateDescriptionCreation($values); if ($valid) { @@ -465,7 +465,7 @@ class Task extends Base if ($this->request->isPost()) { $values = $this->request->getValues(); - list($valid, $errors) = $this->task->validateProjectModification($values); + list($valid, $errors) = $this->taskValidator->validateProjectModification($values); if ($valid) { $task_id = $this->task->{$action.'ToAnotherProject'}($values['project_id'], $task); diff --git a/app/Model/Base.php b/app/Model/Base.php index 9cf0b766..530ef6c2 100644 --- a/app/Model/Base.php +++ b/app/Model/Base.php @@ -19,14 +19,18 @@ use PicoDb\Database; * @property \Model\Board $board * @property \Model\Category $category * @property \Model\Comment $comment + * @property \Model\Color $color * @property \Model\Config $config + * @property \Model\DateParser $dateParser * @property \Model\File $file * @property \Model\LastLogin $lastLogin * @property \Model\Notification $notification * @property \Model\Project $project * @property \Model\SubTask $subTask * @property \Model\Task $task + * @property \Model\TaskExport $taskExport * @property \Model\TaskHistory $taskHistory + * @property \Model\TaskValidator $taskValidator * @property \Model\User $user * @property \Model\Webhook $webhook */ diff --git a/app/Model/Color.php b/app/Model/Color.php new file mode 100644 index 00000000..f414e837 --- /dev/null +++ b/app/Model/Color.php @@ -0,0 +1,31 @@ +<?php + +namespace Model; + +/** + * Color model (TODO: model for the future color picker) + * + * @package model + * @author Frederic Guillot + */ +class Color extends Base +{ + /** + * Get available colors + * + * @access public + * @return array + */ + public function getList() + { + return array( + 'yellow' => t('Yellow'), + 'blue' => t('Blue'), + 'green' => t('Green'), + 'purple' => t('Purple'), + 'red' => t('Red'), + 'orange' => t('Orange'), + 'grey' => t('Grey'), + ); + } +} diff --git a/app/Model/DateParser.php b/app/Model/DateParser.php new file mode 100644 index 00000000..b051fb6e --- /dev/null +++ b/app/Model/DateParser.php @@ -0,0 +1,85 @@ +<?php + +namespace Model; + +use DateTime; + +/** + * Date parser model + * + * @package model + * @author Frederic Guillot + */ +class DateParser extends Base +{ + /** + * Return a timestamp if the given date format is correct otherwise return 0 + * + * @access public + * @param string $value Date to parse + * @param string $format Date format + * @return integer + */ + public function getValidDate($value, $format) + { + $date = DateTime::createFromFormat($format, $value); + + if ($date !== false) { + $errors = DateTime::getLastErrors(); + if ($errors['error_count'] === 0 && $errors['warning_count'] === 0) { + $timestamp = $date->getTimestamp(); + return $timestamp > 0 ? $timestamp : 0; + } + } + + return 0; + } + + /** + * Parse a date ad return a unix timestamp, try different date formats + * + * @access public + * @param string $value Date to parse + * @return integer + */ + public function getTimestamp($value) + { + foreach ($this->getDateFormats() as $format) { + + $timestamp = $this->getValidDate($value, $format); + + if ($timestamp !== 0) { + return $timestamp; + } + } + + return 0; + } + + /** + * Return the list of supported date formats + * + * @access public + * @return array + */ + public function getDateFormats() + { + return array( + t('m/d/Y'), + 'Y-m-d', + 'Y_m_d', + ); + } + + /** + * For a given timestamp, reset the date to midnight + * + * @access public + * @param integer $timestamp Timestamp + * @return integer + */ + public function resetDateToMidnight($timestamp) + { + return mktime(0, 0, 0, date('m', $timestamp), date('d', $timestamp), date('Y', $timestamp)); + } +} diff --git a/app/Model/Task.php b/app/Model/Task.php index 84310d3c..eacf0b5b 100644 --- a/app/Model/Task.php +++ b/app/Model/Task.php @@ -2,9 +2,6 @@ namespace Model; -use SimpleValidator\Validator; -use SimpleValidator\Validators; -use DateTime; use PDO; /** @@ -44,24 +41,7 @@ class Task extends Base const EVENT_CREATE_UPDATE = 'task.create_update'; const EVENT_ASSIGNEE_CHANGE = 'task.assignee_change'; - /** - * Get available colors - * - * @access public - * @return array - */ - public function getColors() - { - return array( - 'yellow' => t('Yellow'), - 'blue' => t('Blue'), - 'green' => t('Green'), - 'purple' => t('Purple'), - 'red' => t('Red'), - 'orange' => t('Orange'), - 'grey' => t('Grey'), - ); - } + /** * Get a list of due tasks for all projects @@ -372,7 +352,7 @@ class Task extends Base } if (! empty($values['date_due']) && ! is_numeric($values['date_due'])) { - $values['date_due'] = $this->parseDate($values['date_due']); + $values['date_due'] = $this->dateParser->getTimestamp($values['date_due']); } // Force integer fields at 0 (for Postgresql) @@ -408,7 +388,7 @@ class Task extends Base } if (empty($values['color_id'])) { - $colors = $this->getColors(); + $colors = $this->color->getList(); $values['color_id'] = key($colors); } @@ -708,326 +688,4 @@ class Task extends Base return false; } - - /** - * Common validation rules - * - * @access private - * @return array - */ - private function commonValidationRules() - { - return array( - new Validators\Integer('id', t('This value must be an integer')), - new Validators\Integer('project_id', t('This value must be an integer')), - new Validators\Integer('column_id', t('This value must be an integer')), - new Validators\Integer('owner_id', t('This value must be an integer')), - new Validators\Integer('creator_id', t('This value must be an integer')), - new Validators\Integer('score', t('This value must be an integer')), - new Validators\Integer('category_id', t('This value must be an integer')), - new Validators\MaxLength('title', t('The maximum length is %d characters', 200), 200), - new Validators\Date('date_due', t('Invalid date'), $this->getDateFormats()), - ); - } - - /** - * Validate task creation - * - * @access public - * @param array $values Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateCreation(array $values) - { - $rules = array( - new Validators\Required('project_id', t('The project is required')), - new Validators\Required('title', t('The title is required')), - ); - - $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); - - return array( - $v->execute(), - $v->getErrors() - ); - } - - /** - * Validate description creation - * - * @access public - * @param array $values Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateDescriptionCreation(array $values) - { - $rules = array( - new Validators\Required('id', t('The id is required')), - new Validators\Required('description', t('The description is required')), - ); - - $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); - - return array( - $v->execute(), - $v->getErrors() - ); - } - - /** - * Validate task 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('The id is required')), - ); - - $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); - - return array( - $v->execute(), - $v->getErrors() - ); - } - - /** - * Validate assignee change - * - * @access public - * @param array $values Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateAssigneeModification(array $values) - { - $rules = array( - new Validators\Required('id', t('The id is required')), - new Validators\Required('project_id', t('The project is required')), - new Validators\Required('owner_id', t('This value is required')), - ); - - $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); - - return array( - $v->execute(), - $v->getErrors() - ); - } - - /** - * Validate category change - * - * @access public - * @param array $values Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateCategoryModification(array $values) - { - $rules = array( - new Validators\Required('id', t('The id is required')), - new Validators\Required('project_id', t('The project is required')), - new Validators\Required('category_id', t('This value is required')), - - ); - - $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); - - return array( - $v->execute(), - $v->getErrors() - ); - } - - /** - * Validate project modification - * - * @access public - * @param array $values Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateProjectModification(array $values) - { - $rules = array( - new Validators\Required('id', t('The id is required')), - new Validators\Required('project_id', t('The project is required')), - ); - - $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); - - return array( - $v->execute(), - $v->getErrors() - ); - } - - /** - * Return a timestamp if the given date format is correct otherwise return 0 - * - * @access public - * @param string $value Date to parse - * @param string $format Date format - * @return integer - */ - public function getValidDate($value, $format) - { - $date = DateTime::createFromFormat($format, $value); - - if ($date !== false) { - $errors = DateTime::getLastErrors(); - if ($errors['error_count'] === 0 && $errors['warning_count'] === 0) { - $timestamp = $date->getTimestamp(); - return $timestamp > 0 ? $timestamp : 0; - } - } - - return 0; - } - - /** - * Parse a date ad return a unix timestamp, try different date formats - * - * @access public - * @param string $value Date to parse - * @return integer - */ - public function parseDate($value) - { - foreach ($this->getDateFormats() as $format) { - - $timestamp = $this->getValidDate($value, $format); - - if ($timestamp !== 0) { - return $timestamp; - } - } - - return null; - } - - /** - * Return the list of supported date formats - * - * @access public - * @return array - */ - public function getDateFormats() - { - return array( - t('m/d/Y'), - 'Y-m-d', - 'Y_m_d', - ); - } - - /** - * For a given timestamp, reset the date to midnight - * - * @access public - * @param integer $timestamp Timestamp - * @return integer - */ - public function resetDateToMidnight($timestamp) - { - return mktime(0, 0, 0, date('m', $timestamp), date('d', $timestamp), date('Y', $timestamp)); - } - - /** - * Export a list of tasks for a given project and date range - * - * @access public - * @param integer $project_id Project id - * @param mixed $from Start date (timestamp or user formatted date) - * @param mixed $to End date (timestamp or user formatted date) - * @return array - */ - public function export($project_id, $from, $to) - { - $sql = ' - SELECT - tasks.id, - projects.name AS project_name, - tasks.is_active, - project_has_categories.name AS category_name, - columns.title AS column_title, - tasks.position, - tasks.color_id, - tasks.date_due, - creators.username AS creator_username, - users.username AS assignee_username, - tasks.score, - tasks.title, - tasks.date_creation, - tasks.date_modification, - tasks.date_completed - FROM tasks - LEFT JOIN users ON users.id = tasks.owner_id - LEFT JOIN users AS creators ON creators.id = tasks.creator_id - LEFT JOIN project_has_categories ON project_has_categories.id = tasks.category_id - LEFT JOIN columns ON columns.id = tasks.column_id - LEFT JOIN projects ON projects.id = tasks.project_id - WHERE tasks.date_creation >= ? AND tasks.date_creation <= ? AND tasks.project_id = ? - '; - - if (! is_numeric($from)) { - $from = $this->resetDateToMidnight($this->parseDate($from)); - } - - if (! is_numeric($to)) { - $to = $this->resetDateToMidnight(strtotime('+1 day', $this->parseDate($to))); - } - - $rq = $this->db->execute($sql, array($from, $to, $project_id)); - $tasks = $rq->fetchAll(PDO::FETCH_ASSOC); - - $columns = array( - e('Task Id'), - e('Project'), - e('Status'), - e('Category'), - e('Column'), - e('Position'), - e('Color'), - e('Due date'), - e('Creator'), - e('Assignee'), - e('Complexity'), - e('Title'), - e('Creation date'), - e('Modification date'), - e('Completion date'), - ); - - $results = array($columns); - - foreach ($tasks as &$task) { - $results[] = array_values($this->formatOutput($task)); - } - - return $results; - } - - /** - * Format the output of a task array - * - * @access public - * @param array $task Task properties - * @return array - */ - public function formatOutput(array &$task) - { - $colors = $this->getColors(); - $task['score'] = $task['score'] ?: ''; - $task['is_active'] = $task['is_active'] == self::STATUS_OPEN ? e('Open') : e('Closed'); - $task['color_id'] = $colors[$task['color_id']]; - $task['date_creation'] = date('Y-m-d', $task['date_creation']); - $task['date_due'] = $task['date_due'] ? date('Y-m-d', $task['date_due']) : ''; - $task['date_modification'] = $task['date_modification'] ? date('Y-m-d', $task['date_modification']) : ''; - $task['date_completed'] = $task['date_completed'] ? date('Y-m-d', $task['date_completed']) : ''; - - return $task; - } } diff --git a/app/Model/TaskExport.php b/app/Model/TaskExport.php new file mode 100644 index 00000000..815f5997 --- /dev/null +++ b/app/Model/TaskExport.php @@ -0,0 +1,132 @@ +<?php + +namespace Model; + +use PDO; + +/** + * Task Export model + * + * @package model + * @author Frederic Guillot + */ +class TaskExport extends Base +{ + /** + * Fetch tasks and return the prepared CSV + * + * @access public + * @param integer $project_id Project id + * @param mixed $from Start date (timestamp or user formatted date) + * @param mixed $to End date (timestamp or user formatted date) + * @return array + */ + public function export($project_id, $from, $to) + { + $tasks = $this->getTasks($project_id, $from, $to); + $results = array($this->getColumns()); + + foreach ($tasks as &$task) { + $results[] = array_values($this->formatOutput($task)); + } + + return $results; + } + + /** + * Get the list of tasks for a given project and date range + * + * @access public + * @param integer $project_id Project id + * @param mixed $from Start date (timestamp or user formatted date) + * @param mixed $to End date (timestamp or user formatted date) + * @return array + */ + public function getTasks($project_id, $from, $to) + { + $sql = ' + SELECT + tasks.id, + projects.name AS project_name, + tasks.is_active, + project_has_categories.name AS category_name, + columns.title AS column_title, + tasks.position, + tasks.color_id, + tasks.date_due, + creators.username AS creator_username, + users.username AS assignee_username, + tasks.score, + tasks.title, + tasks.date_creation, + tasks.date_modification, + tasks.date_completed + FROM tasks + LEFT JOIN users ON users.id = tasks.owner_id + LEFT JOIN users AS creators ON creators.id = tasks.creator_id + LEFT JOIN project_has_categories ON project_has_categories.id = tasks.category_id + LEFT JOIN columns ON columns.id = tasks.column_id + LEFT JOIN projects ON projects.id = tasks.project_id + WHERE tasks.date_creation >= ? AND tasks.date_creation <= ? AND tasks.project_id = ? + '; + + if (! is_numeric($from)) { + $from = $this->dateParser->resetDateToMidnight($this->dateParser->getTimestamp($from)); + } + + if (! is_numeric($to)) { + $to = $this->dateParser->resetDateToMidnight(strtotime('+1 day', $this->dateParser->getTimestamp($to))); + } + + $rq = $this->db->execute($sql, array($from, $to, $project_id)); + return $rq->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * Format the output of a task array + * + * @access public + * @param array $task Task properties + * @return array + */ + public function formatOutput(array &$task) + { + $colors = $this->color->getList(); + $task['score'] = $task['score'] ?: ''; + $task['is_active'] = $task['is_active'] == Task::STATUS_OPEN ? e('Open') : e('Closed'); + $task['color_id'] = $colors[$task['color_id']]; + $task['date_creation'] = date('Y-m-d', $task['date_creation']); + $task['date_due'] = $task['date_due'] ? date('Y-m-d', $task['date_due']) : ''; + $task['date_modification'] = $task['date_modification'] ? date('Y-m-d', $task['date_modification']) : ''; + $task['date_completed'] = $task['date_completed'] ? date('Y-m-d', $task['date_completed']) : ''; + + return $task; + } + + /** + * Get column titles + * + * @access public + * @return array + */ + public function getColumns() + { + return array( + e('Task Id'), + e('Project'), + e('Status'), + e('Category'), + e('Column'), + e('Position'), + e('Color'), + e('Due date'), + e('Creator'), + e('Assignee'), + e('Complexity'), + e('Title'), + e('Creation date'), + e('Modification date'), + e('Completion date'), + ); + } +} diff --git a/app/Model/TaskValidator.php b/app/Model/TaskValidator.php new file mode 100644 index 00000000..461c03d4 --- /dev/null +++ b/app/Model/TaskValidator.php @@ -0,0 +1,170 @@ +<?php + +namespace Model; + +use SimpleValidator\Validator; +use SimpleValidator\Validators; + +/** + * Task validator model + * + * @package model + * @author Frederic Guillot + */ +class TaskValidator extends Base +{ + /** + * Common validation rules + * + * @access private + * @return array + */ + private function commonValidationRules() + { + return array( + new Validators\Integer('id', t('This value must be an integer')), + new Validators\Integer('project_id', t('This value must be an integer')), + new Validators\Integer('column_id', t('This value must be an integer')), + new Validators\Integer('owner_id', t('This value must be an integer')), + new Validators\Integer('creator_id', t('This value must be an integer')), + new Validators\Integer('score', t('This value must be an integer')), + new Validators\Integer('category_id', t('This value must be an integer')), + new Validators\MaxLength('title', t('The maximum length is %d characters', 200), 200), + new Validators\Date('date_due', t('Invalid date'), $this->dateParser->getDateFormats()), + ); + } + + /** + * Validate task creation + * + * @access public + * @param array $values Form values + * @return array $valid, $errors [0] = Success or not, [1] = List of errors + */ + public function validateCreation(array $values) + { + $rules = array( + new Validators\Required('project_id', t('The project is required')), + new Validators\Required('title', t('The title is required')), + ); + + $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); + + return array( + $v->execute(), + $v->getErrors() + ); + } + + /** + * Validate description creation + * + * @access public + * @param array $values Form values + * @return array $valid, $errors [0] = Success or not, [1] = List of errors + */ + public function validateDescriptionCreation(array $values) + { + $rules = array( + new Validators\Required('id', t('The id is required')), + new Validators\Required('description', t('The description is required')), + ); + + $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); + + return array( + $v->execute(), + $v->getErrors() + ); + } + + /** + * Validate task 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('The id is required')), + ); + + $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); + + return array( + $v->execute(), + $v->getErrors() + ); + } + + /** + * Validate assignee change + * + * @access public + * @param array $values Form values + * @return array $valid, $errors [0] = Success or not, [1] = List of errors + */ + public function validateAssigneeModification(array $values) + { + $rules = array( + new Validators\Required('id', t('The id is required')), + new Validators\Required('project_id', t('The project is required')), + new Validators\Required('owner_id', t('This value is required')), + ); + + $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); + + return array( + $v->execute(), + $v->getErrors() + ); + } + + /** + * Validate category change + * + * @access public + * @param array $values Form values + * @return array $valid, $errors [0] = Success or not, [1] = List of errors + */ + public function validateCategoryModification(array $values) + { + $rules = array( + new Validators\Required('id', t('The id is required')), + new Validators\Required('project_id', t('The project is required')), + new Validators\Required('category_id', t('This value is required')), + + ); + + $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); + + return array( + $v->execute(), + $v->getErrors() + ); + } + + /** + * Validate project modification + * + * @access public + * @param array $values Form values + * @return array $valid, $errors [0] = Success or not, [1] = List of errors + */ + public function validateProjectModification(array $values) + { + $rules = array( + new Validators\Required('id', t('The id is required')), + new Validators\Required('project_id', t('The project is required')), + ); + + $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); + + return array( + $v->execute(), + $v->getErrors() + ); + } +} diff --git a/jsonrpc.php b/jsonrpc.php index 1f3cf650..a9c44747 100644 --- a/jsonrpc.php +++ b/jsonrpc.php @@ -6,6 +6,7 @@ use Core\Translator; use JsonRPC\Server; use Model\Project; use Model\Task; +use Model\TaskValidator; use Model\User; use Model\Config; use Model\Category; @@ -19,6 +20,7 @@ use Model\Notification; $config = new Config($registry); $project = new Project($registry); $task = new Task($registry); +$taskValidator = new TaskValidator($registry); $user = new User($registry); $category = new Category($registry); $comment = new Comment($registry); @@ -158,7 +160,7 @@ $server->register('allowUser', function($project_id, $user_id) use ($project) { /** * Task procedures */ -$server->register('createTask', function($title, $project_id, $color_id = '', $column_id = 0, $owner_id = 0, $creator_id = 0, $date_due = '', $description = '', $category_id = 0, $score = 0) use ($task) { +$server->register('createTask', function($title, $project_id, $color_id = '', $column_id = 0, $owner_id = 0, $creator_id = 0, $date_due = '', $description = '', $category_id = 0, $score = 0) use ($task, $taskValidator) { $values = array( 'title' => $title, @@ -173,7 +175,7 @@ $server->register('createTask', function($title, $project_id, $color_id = '', $c 'score' => $score, ); - list($valid,) = $task->validateCreation($values); + list($valid,) = $taskValidator->validateCreation($values); return $valid && $task->create($values) !== false; }); @@ -185,7 +187,7 @@ $server->register('getAllTasks', function($project_id, $status) use ($task) { return $task->getAll($project_id, $status); }); -$server->register('updateTask', function($id, $title = null, $project_id = null, $color_id = null, $column_id = null, $owner_id = null, $creator_id = null, $date_due = null, $description = null, $category_id = null, $score = null) use ($task) { +$server->register('updateTask', function($id, $title = null, $project_id = null, $color_id = null, $column_id = null, $owner_id = null, $creator_id = null, $date_due = null, $description = null, $category_id = null, $score = null) use ($task, $taskValidator) { $values = array( 'id' => $id, @@ -207,7 +209,7 @@ $server->register('updateTask', function($id, $title = null, $project_id = null, } } - list($valid) = $task->validateModification($values); + list($valid) = $taskValidator->validateModification($values); return $valid && $task->update($values); }); @@ -8,6 +8,7 @@ use Core\Tool; use Core\Translator; use Model\Config; use Model\Task; +use Model\TaskExport; use Model\Notification; $config = new Config($registry); @@ -40,8 +41,8 @@ $cli->register('export-csv', function() use ($cli, $registry) { $start_date = $GLOBALS['argv'][3]; $end_date = $GLOBALS['argv'][4]; - $taskModel = new Task($registry); - $data = $taskModel->export($project_id, $start_date, $end_date); + $taskExport = new TaskExport($registry); + $data = $taskExport->export($project_id, $start_date, $end_date); if (is_array($data)) { Tool::csv($data); diff --git a/tests/units/DateParserTest.php b/tests/units/DateParserTest.php new file mode 100644 index 00000000..68addf3f --- /dev/null +++ b/tests/units/DateParserTest.php @@ -0,0 +1,32 @@ +<?php + +require_once __DIR__.'/Base.php'; + +use Model\DateParser; + +class DateParserTest extends Base +{ + public function testValidDate() + { + $d = new DateParser($this->registry); + + $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('2014-03-05', 'Y-m-d'))); + $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('2014_03_05', 'Y_m_d'))); + $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('05/03/2014', 'd/m/Y'))); + $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('03/05/2014', 'm/d/Y'))); + $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('3/5/2014', 'm/d/Y'))); + $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('5/3/2014', 'd/m/Y'))); + $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('5/3/14', 'd/m/y'))); + $this->assertEquals(0, $d->getValidDate('5/3/14', 'd/m/Y')); + $this->assertEquals(0, $d->getValidDate('5-3-2014', 'd/m/Y')); + } + + public function testGetTimestamp() + { + $d = new DateParser($this->registry); + + $this->assertEquals('2014-03-05', date('Y-m-d', $d->getTimestamp('2014-03-05'))); + $this->assertEquals('2014-03-05', date('Y-m-d', $d->getTimestamp('2014_03_05'))); + $this->assertEquals('2014-03-05', date('Y-m-d', $d->getTimestamp('03/05/2014'))); + } +} diff --git a/tests/units/TaskExportTest.php b/tests/units/TaskExportTest.php new file mode 100644 index 00000000..ad0bbdc4 --- /dev/null +++ b/tests/units/TaskExportTest.php @@ -0,0 +1,48 @@ +<?php + +require_once __DIR__.'/Base.php'; + +use Model\Task; +use Model\TaskExport; +use Model\Project; +use Model\Category; +use Model\User; + +class TaskExportTest extends Base +{ + public function testExport() + { + $t = new Task($this->registry); + $p = new Project($this->registry); + $c = new Category($this->registry); + $e = new TaskExport($this->registry); + + $this->assertEquals(1, $p->create(array('name' => 'Export Project'))); + $this->assertNotFalse($c->create(array('name' => 'Category #1', 'project_id' => 1))); + $this->assertNotFalse($c->create(array('name' => 'Category #2', 'project_id' => 1))); + $this->assertNotFalse($c->create(array('name' => 'Category #3', 'project_id' => 1))); + + for ($i = 1; $i <= 100; $i++) { + + $task = array( + 'title' => 'Task #'.$i, + 'project_id' => 1, + 'column_id' => rand(1, 3), + 'creator_id' => rand(0, 1), + 'owner_id' => rand(0, 1), + 'color_id' => rand(0, 1) === 0 ? 'green' : 'purple', + 'category_id' => rand(0, 3), + 'date_due' => array_rand(array(0, date('Y-m-d'), date('Y-m-d', strtotime('+'.$i.'day')))), + 'score' => rand(0, 21) + ); + + $this->assertEquals($i, $t->create($task)); + } + + $rows = $e->export(1, strtotime('-1 day'), strtotime('+1 day')); + $this->assertEquals($i, count($rows)); + $this->assertEquals('Task Id', $rows[0][0]); + $this->assertEquals(1, $rows[1][0]); + $this->assertEquals('Task #'.($i - 1), $rows[$i - 1][11]); + } +} diff --git a/tests/units/TaskTest.php b/tests/units/TaskTest.php index ad9f4cb8..b5ba6c18 100644 --- a/tests/units/TaskTest.php +++ b/tests/units/TaskTest.php @@ -395,41 +395,6 @@ class TaskTest extends Base $this->assertEquals($task_per_column + 1, $t->countByColumnId(1, 4)); } - public function testExport() - { - $t = new Task($this->registry); - $p = new Project($this->registry); - $c = new Category($this->registry); - - $this->assertEquals(1, $p->create(array('name' => 'Export Project'))); - $this->assertNotFalse($c->create(array('name' => 'Category #1', 'project_id' => 1))); - $this->assertNotFalse($c->create(array('name' => 'Category #2', 'project_id' => 1))); - $this->assertNotFalse($c->create(array('name' => 'Category #3', 'project_id' => 1))); - - for ($i = 1; $i <= 100; $i++) { - - $task = array( - 'title' => 'Task #'.$i, - 'project_id' => 1, - 'column_id' => rand(1, 3), - 'creator_id' => rand(0, 1), - 'owner_id' => rand(0, 1), - 'color_id' => rand(0, 1) === 0 ? 'green' : 'purple', - 'category_id' => rand(0, 3), - 'date_due' => array_rand(array(0, date('Y-m-d'), date('Y-m-d', strtotime('+'.$i.'day')))), - 'score' => rand(0, 21) - ); - - $this->assertEquals($i, $t->create($task)); - } - - $rows = $t->export(1, strtotime('-1 day'), strtotime('+1 day')); - $this->assertEquals($i, count($rows)); - $this->assertEquals('Task Id', $rows[0][0]); - $this->assertEquals(1, $rows[1][0]); - $this->assertEquals('Task #'.($i - 1), $rows[$i - 1][11]); - } - public function testFilter() { $t = new Task($this->registry); @@ -499,25 +464,6 @@ class TaskTest extends Base $this->assertEquals(0, count($tasks)); } - public function testDateFormat() - { - $t = new Task($this->registry); - - $this->assertEquals('2014-03-05', date('Y-m-d', $t->getValidDate('2014-03-05', 'Y-m-d'))); - $this->assertEquals('2014-03-05', date('Y-m-d', $t->getValidDate('2014_03_05', 'Y_m_d'))); - $this->assertEquals('2014-03-05', date('Y-m-d', $t->getValidDate('05/03/2014', 'd/m/Y'))); - $this->assertEquals('2014-03-05', date('Y-m-d', $t->getValidDate('03/05/2014', 'm/d/Y'))); - $this->assertEquals('2014-03-05', date('Y-m-d', $t->getValidDate('3/5/2014', 'm/d/Y'))); - $this->assertEquals('2014-03-05', date('Y-m-d', $t->getValidDate('5/3/2014', 'd/m/Y'))); - $this->assertEquals('2014-03-05', date('Y-m-d', $t->getValidDate('5/3/14', 'd/m/y'))); - $this->assertEquals(0, $t->getValidDate('5/3/14', 'd/m/Y')); - $this->assertEquals(0, $t->getValidDate('5-3-2014', 'd/m/Y')); - - $this->assertEquals('2014-03-05', date('Y-m-d', $t->parseDate('2014-03-05'))); - $this->assertEquals('2014-03-05', date('Y-m-d', $t->parseDate('2014_03_05'))); - $this->assertEquals('2014-03-05', date('Y-m-d', $t->parseDate('03/05/2014'))); - } - public function testDuplicateToTheSameProject() { $t = new Task($this->registry); |