diff options
author | Frederic Guillot <fred@kanboard.net> | 2015-02-14 16:11:13 -0500 |
---|---|---|
committer | Frederic Guillot <fred@kanboard.net> | 2015-02-14 16:11:13 -0500 |
commit | f7e4c3928aba9cb7f5222cb4af67846312bbb435 (patch) | |
tree | 78f5854a0bdc538c977bad718a11d605a4caaca6 /app/Model | |
parent | 364382b1b58db8bf1bd2c8866e21c869a7a5d6d0 (diff) |
Refactoring/simplification of the pull-request about links
Diffstat (limited to 'app/Model')
-rw-r--r-- | app/Model/Acl.php | 2 | ||||
-rw-r--r-- | app/Model/Link.php | 427 | ||||
-rw-r--r-- | app/Model/ProjectPermission.php | 17 | ||||
-rw-r--r-- | app/Model/TaskDuplication.php | 1 | ||||
-rw-r--r-- | app/Model/TaskFilter.php | 32 | ||||
-rw-r--r-- | app/Model/TaskFinder.php | 24 | ||||
-rw-r--r-- | app/Model/TaskLink.php | 355 |
7 files changed, 231 insertions, 627 deletions
diff --git a/app/Model/Acl.php b/app/Model/Acl.php index b6c0e6b8..e713f2e1 100644 --- a/app/Model/Acl.php +++ b/app/Model/Acl.php @@ -38,6 +38,7 @@ class Acl extends Base 'project' => array('show', 'tasks', 'search', 'activity'), 'subtask' => '*', 'task' => '*', + 'tasklink' => '*', 'calendar' => array('show', 'events', 'save'), ); @@ -67,6 +68,7 @@ class Acl extends Base 'app' => array('dashboard'), 'user' => array('index', 'create', 'save', 'remove'), 'config' => '*', + 'link' => '*', 'project' => array('remove'), ); diff --git a/app/Model/Link.php b/app/Model/Link.php index eddf1c6c..87ba49c4 100644 --- a/app/Model/Link.php +++ b/app/Model/Link.php @@ -1,389 +1,209 @@ <?php + namespace Model; +use PDO; use SimpleValidator\Validator; use SimpleValidator\Validators; -use PDO; /** * Link model - * A link is made of one bidirectional (<->), or two sided (<- and ->) link labels. * * @package model - * @author Olivier Maridat + * @author Olivier Maridat + * @author Frederic Guillot */ class Link extends Base { - /** * SQL table name * * @var string */ - const TABLE = 'link'; - - const TABLE_LABEL = 'link_label'; - - /** - * Direction: left to right -> - * - * @var integer - */ - const BEHAVIOUR_LEFT2RIGTH = 0; - - /** - * Direction: right to left <- - * - * @var integer - */ - const BEHAVIOUR_RIGHT2LEFT = 1; - - /** - * Bidirectional <-> - * - * @var integer - */ - const BEHAVIOUR_BOTH = 2; + const TABLE = 'links'; /** - * Get a link by the id + * Get a link by id * * @access public - * @param integer $link_id - * Link id - * @param integer $project_id - * Specify a project id. Default: -1 to target all projects + * @param integer $link_id Link id * @return array */ - public function getById($link_id, $project_id = -1) + public function getById($link_id) { - return $this->db->table(self::TABLE) - ->eq(self::TABLE . '.link_id', $link_id) - ->in('project_id', array( - - 1, - $project_id - )) - ->join(self::TABLE_LABEL, 'link_id', 'link_id') - ->findAll(); + return $this->db->table(self::TABLE)->eq('id', $link_id)->findOne(); } /** - * Get the id of the inverse link label by a link label id + * Get a link by name * * @access public - * @param integer $link_id - * Link id - * @param integer $link_label_id - * Link label id - * @return integer + * @param string $label + * @return array */ - public function getInverseLinkLabelId($link_label_id) + public function getByLabel($label) { - $sql = 'SELECT - la2.id - FROM ' . self::TABLE_LABEL . ' la1 - JOIN '.self::TABLE_LABEL.' la2 ON la2.link_id = la1.link_id AND (la2.behaviour=2 OR la2.id != la1.id) - WHERE la1.id = ? - '; - $rq = $this->db->execute($sql, array( - $link_label_id - )); - return $rq->fetchColumn(0); + return $this->db->table(self::TABLE)->eq('label', $label)->findOne(); } /** - * Return all link labels for a given project + * Get the opposite link id * * @access public - * @param integer $project_id - * Specify a project id. Default: -1 to target all projects - * @return array + * @param integer $link_id Link id + * @return integer */ - public function getLinkLabels($project_id = -1) + public function getOppositeLinkId($link_id) { - return $this->db->table(self::TABLE_LABEL) - ->in(self::TABLE . '.project_id', array( - - 1, - $project_id - )) - ->join(self::TABLE, 'link_id', 'link_id') - ->asc(self::TABLE_LABEL.'.link_id', 'behaviour') - ->columns('id', self::TABLE . '.project_id', self::TABLE_LABEL.'.link_id', 'label', 'behaviour') - ->findAll(); + $link = $this->getById($link_id); + return $link['opposite_id'] ?: $link_id; } /** - * Return the list of all link labels - * Used to select a link label + * Get all links * * @access public - * @param integer $project_id - * Specify a project id. Default: -1 to target all projects * @return array */ - public function getLinkLabelList($project_id = -1) + public function getAll() { - $listing = $this->getLinkLabels($project_id); - $mergedListing = array(); - foreach ($listing as $link) { - $suffix = ''; - $prefix = ''; - if (self::BEHAVIOUR_BOTH == $link['behaviour'] || self::BEHAVIOUR_LEFT2RIGTH == $link['behaviour']) { - $suffix = ' »'; - } - if (self::BEHAVIOUR_BOTH == $link['behaviour'] || self::BEHAVIOUR_RIGHT2LEFT == $link['behaviour']) { - $prefix = '« '; - } - $mergedListing[$link['id']] = $prefix . t($link['label']) . $suffix; - } - $listing = $mergedListing; - return $listing; + return $this->db->table(self::TABLE)->findAll(); } /** - * Return the list of all links (label + inverse label) + * Get merged links * * @access public - * @param integer $project_id - * Specify a project id. Default: -1 to target all projects * @return array */ - public function getMergedList($project_id = -1) + public function getMergedList() { - $listing = $this->getLinkLabels($project_id); - $mergedListing = array(); - $current = null; - foreach ($listing as $link) { - if (self::BEHAVIOUR_BOTH == $link['behaviour'] || self::BEHAVIOUR_LEFT2RIGTH == $link['behaviour']) { - $current = $link; - } - else { - $current['label_inverse'] = $link['label']; - } - if (self::BEHAVIOUR_BOTH == $link['behaviour'] || self::BEHAVIOUR_RIGHT2LEFT == $link['behaviour']) { - $mergedListing[] = $current; - $current = null; - } - } - $listing = $mergedListing; - return $listing; + return $this->db + ->execute(' + SELECT + links.id, links.label, opposite.label as opposite_label + FROM links + LEFT JOIN links AS opposite ON opposite.id=links.opposite_id + ') + ->fetchAll(PDO::FETCH_ASSOC); } /** - * Prepare data before insert/update + * Get label list * * @access public - * @param array $values - * Form values + * @param integer $exclude_id Exclude this link + * @param booelan $prepend Prepend default value + * @return array */ - public function prepare(array &$values) + public function getList($exclude_id = 0, $prepend = true) { - // Prepare label 1 - $link = array( - 'project_id' => $values['project_id'] - ); - $label1 = array( - 'label' => @$values['label'][0], - 'behaviour' => (isset($values['behaviour'][0]) || !isset($values['label'][1]) || null == $values['label'][1]) ? self::BEHAVIOUR_BOTH : self::BEHAVIOUR_LEFT2RIGTH - ); - $label2 = array( - 'label' => @$values['label'][1], - 'behaviour' => self::BEHAVIOUR_RIGHT2LEFT - ); - if (isset($values['link_id'])) { - $link['link_id'] = $values['link_id']; - $label1['id'] = $values['id'][0]; - $label2['id'] = @$values['id'][1]; - $label1['link_id'] = $values['link_id']; - $label2['link_id'] = $values['link_id']; + $labels = $this->db->hashtable(self::TABLE)->neq('id', $exclude_id)->asc('id')->getAll('id', 'label'); + + foreach ($labels as &$value) { + $value = t($value); } - - $values = $link; - $values[] = $label1;
- $values[] = $label2; - return array( - $link, - $label1, - $label2 - ); + + return $prepend ? array('') + $labels : $labels; } /** - * Create a link + * Create a new link label * * @access public - * @param array $values - * Form values - * @return bool integer + * @param string $label + * @param string $opposite_label + * @return boolean */ - public function create(array $values) + public function create($label, $opposite_label = '') { - list ($link, $label1, $label2) = $this->prepare($values); - // Create link $this->db->startTransaction(); - $res = $this->db->table(self::TABLE)->save($link); - if (! $res) { - $this->db->cancelTransaction(); - return false; - } - - // Create label 1 - $label1['link_id'] = $this->db->getConnection()->lastInsertId(self::TABLE); - $res = $this->db->table(self::TABLE_LABEL)->save($label1); - if (! $res) { + + if (! $this->db->table(self::TABLE)->insert(array('label' => $label))) { $this->db->cancelTransaction(); return false; } - - // Create label 2 if any - if (null != $label2 && self::BEHAVIOUR_BOTH != $label1['behaviour']) { - $label2['link_id'] = $label1['link_id']; - $res = $this->db->table(self::TABLE_LABEL)->save($label2); - if (! $res) { - $this->db->cancelTransaction(); - return false; - } + + if ($opposite_label !== '') { + $this->createOpposite($opposite_label); } + $this->db->closeTransaction(); - return $res; + + return true; } /** - * Update a link + * Create the opposite label (executed inside create() method) * - * @access public - * @param array $values - * Form values - * @return bool + * @access private + * @param string $label */ - public function update(array $values) + private function createOpposite($label) { - list($link, $label1, $label2) = $this->prepare($values); - // Update link - $this->db->startTransaction(); - $res = $this->db->table(self::TABLE) - ->eq('link_id', $link['link_id']) - ->save($link); - if (! $res) { - $this->db->cancelTransaction(); - return false; - } - - // Update label 1 - $this->db->startTransaction(); - $res = $this->db->table(self::TABLE_LABEL) - ->eq('id', $label1['id']) - ->save($label1); - if (! $res) { - $this->db->cancelTransaction(); - return false; - } - - // Update label 2 (if label 1 not bidirectional) - if (null != $label2 && self::BEHAVIOUR_BOTH != $label1['behaviour']) { - // Create - if (! isset($label2['id']) || null == $label2['id']) { - unset($label2['id']); - $res = $this->db->table(self::TABLE_LABEL)->save($label2); - if (! $res) { - $this->db->cancelTransaction(); - return false; - } - $label2['id'] = $this->db->getConnection()->lastInsertId(self::TABLE_LABEL); - $this->taskLink->changeLinkLabel($link['link_id'], $label2['id'], true); - } - // Update - else { - $res = $this->db->table(self::TABLE_LABEL) - ->eq('id', $label2['id']) - ->save($label2); - if (! $res) { - $this->db->cancelTransaction(); - return false; - } - } - } - // Remove label 2 (if label 1 bidirectional) - else { - $this->taskLink->changeLinkLabel($link['link_id'], $label1['id']); - $this->db->table(self::TABLE_LABEL) - ->eq('link_id', $link['link_id']) - ->neq('id', $label1['id']) - ->remove(); - } - $this->db->closeTransaction(); - return $res; + $label_id = $this->db->getConnection()->getLastId(); + + $this->db + ->table(self::TABLE) + ->insert(array( + 'label' => $label, + 'opposite_id' => $label_id, + )); + + $this->db + ->table(self::TABLE) + ->eq('id', $label_id) + ->update(array( + 'opposite_id' => $this->db->getConnection()->getLastId() + )); } /** - * Remove a link + * Update a link * * @access public - * @param integer $link_id - * Link id - * @return bool + * @param array $values + * @return boolean */ - public function remove($link_id) + public function update(array $values) { - $this->db->startTransaction(); - if (! $this->db->table(self::TABLE) - ->eq('link_id', $link_id) - ->remove()) { - $this->db->cancelTransaction(); - return false; - } - $this->db->closeTransaction(); - return true; + return $this->db + ->table(self::TABLE) + ->eq('id', $values['id']) + ->update(array( + 'label' => $values['label'], + 'opposite_id' => $values['opposite_id'], + )); } /** - * Duplicate links from a project to another one, must be executed inside a transaction + * Remove a link a the relation to its opposite * - * @param integer $src_project_id - * Source project id - * @return integer $dst_project_id Destination project id + * @access public + * @param integer $link_id * @return boolean */ - public function duplicate($src_project_id, $dst_project_id) + public function remove($link_id) { - $labels = $this->db->table(self::TABLE_LABEL) - ->columns(self::TABLE_LABEL.'.link_id', 'label', 'behaviour') - ->eq('project_id', $src_project_id) - ->join(self::TABLE, 'link_id', 'link_id') - ->asc(self::TABLE_LABEL.'.link_id', 'behaviour') - ->findAll(); - - $this->db->startTransaction(); - $link = array('project_id' => $dst_project_id);
- if (! $this->db->table(self::TABLE)->save($link)) { - $this->db->cancelTransaction();
- return false;
- } - $link['id'] = $this->db->getConnection()->lastInsertId(self::TABLE); - - foreach ($labels as $label) { - $label['link_id'] = $link['id']; - if (! $this->db->table(self::TABLE_LABEL)->save($label)) { - $this->db->cancelTransaction(); - return false; - } - } - $this->db->closeTransaction(); - return true; + $this->db->table(self::TABLE)->eq('opposite_id', $link_id)->update(array('opposite_id' => 0)); + return $this->db->table(self::TABLE)->eq('id', $link_id)->remove(); } /** - * Validate link creation + * Validate creation * * @access public - * @param array $values - * Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors + * @param array $values Form values + * @return array $valid, $errors [0] = Success or not, [1] = List of errors */ public function validateCreation(array $values) { - $v = new Validator($values, $this->commonValidationRules()); - + $v = new Validator($values, array( + new Validators\Required('label', t('Field required')), + new Validators\Unique('label', t('This label must be unique'), $this->db->getConnection(), self::TABLE), + new Validators\NotEquals('label', 'opposite_label', t('The labels must be different')), + )); + return array( $v->execute(), $v->getErrors() @@ -391,47 +211,24 @@ class Link extends Base } /** - * Validate link modification + * Validate modification * * @access public - * @param array $values - * Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors + * @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('link_id', t('The id is required')), -// new Validators\Required('id[0]', t('The label id is required')) - ); - $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); - + $v = new Validator($values, array( + new Validators\Required('id', t('Field required')), + new Validators\Required('opposite_id', t('Field required')), + new Validators\Required('label', t('Field required')), + new Validators\Unique('label', t('This label must be unique'), $this->db->getConnection(), self::TABLE), + )); + return array( $v->execute(), $v->getErrors() ); } - - /** - * Common validation rules - * - * @access private - * @return array - */ - private function commonValidationRules() - { - // TODO Update simple-validator to support array in forms - return array( - new Validators\Required('project_id', t('The project id required')), - // new Validators\Required('label[0]', t('The link label is required')), - new Validators\Integer('project_id', t('The project id must be an integer')), - new Validators\Integer('link_id', t('The link id must be an integer')), -// new Validators\Integer('id[0]', t('The link label id must be an integer')), -// new Validators\Integer('id[1]', t('The link label id must be an integer')), -// new Validators\Integer('behaviour[0]', t('The link label id must be an integer')), -// new Validators\Integer('behaviour[1]', t('The link label id must be an integer')), -// new Validators\MaxLength('label[0]', t('The maximum length is %d characters', 200), 200), -// new Validators\MaxLength('label[1]', t('The maximum length is %d characters', 200), 200) - ); - } } diff --git a/app/Model/ProjectPermission.php b/app/Model/ProjectPermission.php index fb6316b6..cd892da4 100644 --- a/app/Model/ProjectPermission.php +++ b/app/Model/ProjectPermission.php @@ -338,6 +338,23 @@ class ProjectPermission extends Base } /** + * Return a list of active project ids where the user is member + * + * @access public + * @param integer $user_id User id + * @return []integer + */ + public function getActiveMemberProjectIds($user_id) + { + return $this->db + ->table(Project::TABLE) + ->eq('user_id', $user_id) + ->eq(Project::TABLE.'.is_active', Project::ACTIVE) + ->join(self::TABLE, 'project_id', 'id') + ->findAllByColumn('projects.id'); + } + + /** * Return a list of active projects where the user is member * * @access public diff --git a/app/Model/TaskDuplication.php b/app/Model/TaskDuplication.php index faa5467f..bd593dc1 100644 --- a/app/Model/TaskDuplication.php +++ b/app/Model/TaskDuplication.php @@ -159,7 +159,6 @@ class TaskDuplication extends Base if ($new_task_id) { $this->subtask->duplicate($task_id, $new_task_id); - $this->taskLink->duplicate($task_id, $new_task_id); } return $new_task_id; diff --git a/app/Model/TaskFilter.php b/app/Model/TaskFilter.php index b5a90154..31de2795 100644 --- a/app/Model/TaskFilter.php +++ b/app/Model/TaskFilter.php @@ -18,6 +18,24 @@ class TaskFilter extends Base return $this; } + public function excludeTasks(array $task_ids) + { + $this->query->notin('id', $task_ids); + return $this; + } + + public function filterByTitle($title) + { + $this->query->ilike('title', '%'.$title.'%'); + return $this; + } + + public function filterByProjects(array $project_ids) + { + $this->query->in('project_id', $project_ids); + return $this; + } + public function filterByProject($project_id) { if ($project_id > 0) { @@ -94,6 +112,20 @@ class TaskFilter extends Base return $this->query->findAll(); } + public function toAutoCompletion() + { + return $this->query->columns('id', 'title')->filter(function(array $results) { + + foreach ($results as &$result) { + $result['value'] = $result['title']; + $result['label'] = '#'.$result['id'].' - '.$result['title']; + } + + return $results; + + })->findAll(); + } + public function toCalendarEvents() { $events = array(); diff --git a/app/Model/TaskFinder.php b/app/Model/TaskFinder.php index cf756cd8..98ece4e1 100644 --- a/app/Model/TaskFinder.php +++ b/app/Model/TaskFinder.php @@ -3,7 +3,6 @@ namespace Model; use PDO; -use Model\TaskLink; /** * Task Finder model @@ -130,29 +129,6 @@ class TaskFinder extends Base ->asc('tasks.position') ->findAll(); } - - /** - * Get ids and names of all (limited by $limit) tasks for a given project and status - * - * @access public - * @param integer $project_id Project id - * @param integer $status_id Status id - * @param integer $exclude_id Exclude this task id in the result - * @param integer $limit Number of tasks to list - * @return array - */ - public function getList($project_id, $status_id = Task::STATUS_OPEN, $exclude_id=null, $limit=50) - { - $sql = $this->db - ->hashtable(Task::TABLE) - ->eq('project_id', $project_id) - ->eq('is_active', $status_id) - ->limit($limit); - if (null != $exclude_id) { - $sql->neq('id', $exclude_id); - } - return $sql->getAll('id', 'title'); - } /** * Get all tasks for a given project and status diff --git a/app/Model/TaskLink.php b/app/Model/TaskLink.php index 09f37d2e..c712e5a8 100644 --- a/app/Model/TaskLink.php +++ b/app/Model/TaskLink.php @@ -1,20 +1,19 @@ <?php + namespace Model; -use Core\Helper; use SimpleValidator\Validator; use SimpleValidator\Validators; -use PDO; /** * TaskLink model * * @package model - * @author Olivier Maridat + * @author Olivier Maridat + * @author Frederic Guillot */ class TaskLink extends Base { - /** * SQL table name * @@ -23,339 +22,121 @@ class TaskLink extends Base const TABLE = 'task_has_links'; /** - * Get a link by the task link id + * Get a task link * * @access public - * @param integer $task_link_id - * Task link id + * @param integer $task_link_id Task link id * @return array */ public function getById($task_link_id) { - $sql = 'SELECT - tl1.id AS id, - tl1.link_label_id AS link_label_id, - tl1.task_id AS task_id, - tl1.task_inverse_id AS task_inverse_id, - tl2.id AS task_link_inverse_id - FROM ' . self::TABLE . ' tl1 - LEFT JOIN ' . Link::TABLE_LABEL . ' l1 ON l1.id = tl1.link_label_id - LEFT JOIN ' . Link::TABLE_LABEL . ' l2 ON l2.link_id = l1.link_id - LEFT JOIN ' . self::TABLE . ' tl2 ON tl2.task_id = tl1.task_inverse_id - AND ( (l1.behaviour = 2 AND tl2.link_label_id = l1.id) OR (tl2.link_label_id = l2.id) ) - WHERE tl1.id = ? - '; - $rq = $this->db->execute($sql, array( - $task_link_id - )); - return $rq->fetch(); + return $this->db->table(self::TABLE)->eq('id', $task_link_id)->findOne(); } /** - * Get the id of the inverse task link by a task link id + * Get all links attached to a task * * @access public - * @param integer $link_id - * Task link id - * @return integer + * @param integer $task_id Task id + * @return array */ - public function getInverseTaskLinkId($task_link_id) + public function getLinks($task_id) { - $sql = 'SELECT - tl2.id - FROM ' . self::TABLE . ' tl1 - LEFT JOIN ' . Link::TABLE_LABEL . ' l1 ON l1.id = tl1.link_label_id - LEFT JOIN ' . Link::TABLE_LABEL . ' l2 ON l2.link_id = l1.link_id - LEFT JOIN ' . self::TABLE . ' tl2 ON tl2.task_id = tl1.task_inverse_id - AND ( (l1.behaviour = 2 AND tl2.link_label_id = l1.id) OR (tl2.link_label_id = l2.id) ) - WHERE tl1.id = ? - '; - $rq = $this->db->execute($sql, array( - $task_link_id - )); - return $rq->fetchColumn(0); + return $this->db + ->table(self::TABLE) + ->columns( + self::TABLE.'.id', + self::TABLE.'.opposite_task_id AS task_id', + Link::TABLE.'.label', + Task::TABLE.'.title', + Task::TABLE.'.is_active', + Task::TABLE.'.project_id' + ) + ->eq(self::TABLE.'.task_id', $task_id) + ->join(Link::TABLE, 'id', 'link_id') + ->join(Task::TABLE, 'id', 'opposite_task_id') + ->findAll(); } /** - * Return all links for a given task + * Create a new link * * @access public - * @param integer $task_id - * Task id - * @return array + * @param integer $task_id Task id + * @param integer $opposite_task_id Opposite task id + * @param integer $link_id Link id + * @return boolean */ - public function getAll($task_id) + public function create($task_id, $opposite_task_id, $link_id) { - $sql = 'SELECT - tl1.id, - l.label AS label, - t2.id AS task_inverse_id, - t2.project_id AS task_inverse_project_id, - t2.title AS task_inverse_title, - t2.is_active AS task_inverse_is_active, - t2cat.name AS task_inverse_category - FROM ' . self::TABLE . ' tl1 - LEFT JOIN ' . Link::TABLE_LABEL . ' l ON l.id = tl1.link_label_id - LEFT JOIN ' . Task::TABLE . ' t2 ON t2.id = tl1.task_inverse_id - LEFT JOIN ' . Category::TABLE . ' t2cat ON t2cat.id = t2.category_id - WHERE tl1.task_id = ? - ORDER BY l.label, t2cat.name, t2.id - '; - $rq = $this->db->execute($sql, array( - $task_id + $this->db->startTransaction(); + + // Create the original link + $this->db->table(self::TABLE)->insert(array( + 'task_id' => $task_id, + 'opposite_task_id' => $opposite_task_id, + 'link_id' => $link_id, )); - $res = $rq->fetchAll(PDO::FETCH_ASSOC); - return $res; - } - /** - * Prepare data before insert/update - * - * @access public - * @param array $values - * Form values - */ - public function prepare(array &$values) - { - $this->removeFields($values, array( - 'another_link' + $link_id = $this->link->getOppositeLinkId($link_id); + + // Create the opposite link + $this->db->table(self::TABLE)->insert(array( + 'task_id' => $opposite_task_id, + 'opposite_task_id' => $task_id, + 'link_id' => $link_id, )); - $taskLink1 = array( - 'link_label_id' => $values['link_label_id'], - 'task_id' => $values['task_id'], - 'task_inverse_id' => $values['task_inverse_id'] - ); - $taskLink2 = array( - 'link_label_id' => $this->link->getInverseLinkLabelId($taskLink1['link_label_id']), - 'task_id' => $values['task_inverse_id'], - 'task_inverse_id' => $values['task_id'] - ); - if (isset($values['id']) && isset($values['task_link_inverse_id'])) { - $taskLink1['id'] = $values['id']; - $taskLink2['id'] = $values['task_link_inverse_id']; - } - return array( - $taskLink1, - $taskLink2 - ); - } - /** - * Create a link - * - * @access public - * @param array $values - * Form values - * @return bool integer - */ - public function create(array $values) - { - list($taskLink1, $taskLink2) = $this->prepare($values); - $this->db->startTransaction(); - if (! $this->db->table(self::TABLE)->save($taskLink1)) { - $this->db->cancelTransaction(); - return false; - } - if (! $this->db->table(self::TABLE)->save($taskLink2)) { - $this->db->cancelTransaction(); - return false; - } $this->db->closeTransaction(); - return true; - } - /** - * Update a link - * - * @access public - * @param array $values - * Form values - * @return bool - */ - public function update(array $values) - { - list($taskLink1, $taskLink2) = $this->prepare($values); - $this->db->startTransaction(); - if (! $this->db->table(self::TABLE) - ->eq('id', $taskLink1['id']) - ->save($taskLink1)) { - $this->db->cancelTransaction(); - return false; - } - if (! $this->db->table(self::TABLE) - ->eq('id', $taskLink2['id']) - ->save($taskLink2)) { - $this->db->cancelTransaction(); - return false; - } - $this->db->closeTransaction(); return true; } /** - * Remove a link + * Remove a link between two tasks * * @access public - * @param integer $task_link_id - * Task Link id - * @return bool + * @param integer $task_link_id + * @return boolean */ public function remove($task_link_id) { - $task_link_inverse_id = $this->getInverseTaskLinkId($task_link_id); $this->db->startTransaction(); - if (! $this->db->table(self::TABLE) - ->eq('id', $task_link_id) - ->remove()) { - $this->db->cancelTransaction(); - return false; - } - if (! $this->db->table(self::TABLE) - ->eq('id', $task_link_inverse_id) - ->remove()) { - $this->db->cancelTransaction(); - return false; - } - $this->db->closeTransaction(); - return true; - } - /** - * Duplicate all links to another task - * - * @access public - * @param integer $src_task_id - * Source task id - * @param integer $dst_task_id - * Destination task id - * @return bool - */ - public function duplicate($src_task_id, $dst_task_id) - { - return $this->db->transaction(function ($db) use($src_task_id, $dst_task_id) - { - $links = $db->table(TaskLink::TABLE) - ->columns('link_label_id', 'task_id', 'task_inverse_id') - ->eq('task_id', $src_task_id) - ->asc('id') - ->findAll(); - foreach ($links as &$link) { - $link['task_id'] = $dst_task_id; - if (! $db->table(TaskLink::TABLE) - ->save($link)) { - return false; - } - } - - $links = $db->table(TaskLink::TABLE) - ->columns('link_label_id', 'task_id', 'task_inverse_id') - ->eq('task_inverse_id', $src_task_id) - ->asc('id') - ->findAll(); - foreach ($links as &$link) { - $link['task_inverse_id'] = $dst_task_id; - if (! $db->table(TaskLink::TABLE) - ->save($link)) { - return false; - } - } - }); - } + $link = $this->getById($task_link_id); + $link_id = $this->link->getOppositeLinkId($link['link_id']); + + $this->db->table(self::TABLE)->eq('id', $task_link_id)->remove(); + + $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(); + + $this->db->closeTransaction(); - /** - * Move a task link from a link label to an other - * - * @access public - * @param integer $link_id - * Link id - * @param integer $dst_link_label_id - * Destination link label id - * @return bool - */ - public function changeLinkLabel($link_id, $dst_link_label_id, $alternate=false) - { - $taskLinks = $this->db->table(Link::TABLE_LABEL) - ->eq('link_id', $link_id) - ->neq(Link::TABLE_LABEL.'.id', $dst_link_label_id) - ->join(self::TABLE, 'link_label_id', 'id') - ->asc(self::TABLE.'.id') - ->findAllByColumn(self::TABLE.'.id'); - foreach ($taskLinks as $i => $taskLinkId) { - if (null == $taskLinkId || ($alternate && 0 != $i % 2)) { - continue; - } - if (! $this->db->table(self::TABLE) - ->eq('id', $taskLinkId) - ->save(array('link_label_id' => $dst_link_label_id))) { - return false; - } - } return true; } /** - * Validate link creation + * Validate creation * * @access public - * @param array $values - * Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors + * @param array $values Form values + * @return array $valid, $errors [0] = Success or not, [1] = List of errors */ public function validateCreation(array $values) { - $v = new Validator($values, $this->commonValidationRules()); - $res = array( - $v->execute(), - $v->getErrors() - ); - return $res; - } + $v = new Validator($values, array( + new Validators\Required('task_id', t('Field required')), + new Validators\Required('link_id', t('Field required')), + new Validators\Required('title', t('Field required')), + )); - /** - * Validate link 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())); - $res = array( + return array( $v->execute(), $v->getErrors() ); - return $res; - } - - /** - * Common validation rules - * - * @access private - * @return array - */ - private function commonValidationRules() - { - return array( - new Validators\Required('link_label_id', t('The link type is required')), - new Validators\Required('task_id', t('The task id is required')), - new Validators\Required('task_inverse_id', t('The linked task id is required')), - new Validators\Integer('id', t('The id must be an integer')), - new Validators\Integer('link_label_id', t('The link id must be an integer')), - new Validators\Integer('task_id', t('The task id must be an integer')), - new Validators\Integer('task_inverse_id', t('The related task id must be an integer')), - new Validators\Integer('task_link_inverse_id', t('The related task link id must be an integer')), - new Validators\NotEquals('task_inverse_id', 'task_id', t('A task can not be linked to itself')), - new Validators\Exists('task_inverse_id', t('This linked task id doesn\'t exist'), $this->db->getConnection(), Task::TABLE, 'id'), - new Validators\Unique(array( - 'task_inverse_id', - 'link_label_id', - 'task_id' - ), t('The exact same link already exists'), $this->db->getConnection(), self::TABLE) - ); } } |