summaryrefslogtreecommitdiff
path: root/app/Model
diff options
context:
space:
mode:
authorFrederic Guillot <fred@kanboard.net>2015-02-14 16:11:13 -0500
committerFrederic Guillot <fred@kanboard.net>2015-02-14 16:11:13 -0500
commitf7e4c3928aba9cb7f5222cb4af67846312bbb435 (patch)
tree78f5854a0bdc538c977bad718a11d605a4caaca6 /app/Model
parent364382b1b58db8bf1bd2c8866e21c869a7a5d6d0 (diff)
Refactoring/simplification of the pull-request about links
Diffstat (limited to 'app/Model')
-rw-r--r--app/Model/Acl.php2
-rw-r--r--app/Model/Link.php427
-rw-r--r--app/Model/ProjectPermission.php17
-rw-r--r--app/Model/TaskDuplication.php1
-rw-r--r--app/Model/TaskFilter.php32
-rw-r--r--app/Model/TaskFinder.php24
-rw-r--r--app/Model/TaskLink.php355
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 = ' &raquo;';
- }
- if (self::BEHAVIOUR_BOTH == $link['behaviour'] || self::BEHAVIOUR_RIGHT2LEFT == $link['behaviour']) {
- $prefix = '&laquo; ';
- }
- $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)
- );
}
}