diff options
Diffstat (limited to 'app/Model/Link.php')
-rw-r--r-- | app/Model/Link.php | 427 |
1 files changed, 112 insertions, 315 deletions
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) - ); - } } |