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 /app/Model | |
parent | 95e54d1d300809cb8656c52d029f797ba5961a04 (diff) |
Split Task model into smaller classes
Diffstat (limited to 'app/Model')
-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 |
6 files changed, 425 insertions, 345 deletions
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() + ); + } +} |