summaryrefslogtreecommitdiff
path: root/app/Model/Swimlane.php
diff options
context:
space:
mode:
Diffstat (limited to 'app/Model/Swimlane.php')
-rw-r--r--app/Model/Swimlane.php561
1 files changed, 561 insertions, 0 deletions
diff --git a/app/Model/Swimlane.php b/app/Model/Swimlane.php
new file mode 100644
index 00000000..3b78a406
--- /dev/null
+++ b/app/Model/Swimlane.php
@@ -0,0 +1,561 @@
+<?php
+
+namespace Model;
+
+use SimpleValidator\Validator;
+use SimpleValidator\Validators;
+
+/**
+ * Swimlanes
+ *
+ * @package model
+ * @author Frederic Guillot
+ */
+class Swimlane extends Base
+{
+ /**
+ * SQL table name
+ *
+ * @var string
+ */
+ const TABLE = 'swimlanes';
+
+ /**
+ * Value for active swimlanes
+ *
+ * @var integer
+ */
+ const ACTIVE = 1;
+
+ /**
+ * Value for inactive swimlanes
+ *
+ * @var integer
+ */
+ const INACTIVE = 0;
+
+ /**
+ * Get a swimlane by the id
+ *
+ * @access public
+ * @param integer $swimlane_id Swimlane id
+ * @return array
+ */
+ public function getById($swimlane_id)
+ {
+ return $this->db->table(self::TABLE)->eq('id', $swimlane_id)->findOne();
+ }
+
+ /**
+ * Get the swimlane name by the id
+ *
+ * @access public
+ * @param integer $swimlane_id Swimlane id
+ * @return string
+ */
+ public function getNameById($swimlane_id)
+ {
+ return $this->db->table(self::TABLE)->eq('id', $swimlane_id)->findOneColumn('name') ?: '';
+ }
+
+ /**
+ * Get a swimlane id by the project and the name
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param string $name Name
+ * @return integer
+ */
+ public function getIdByName($project_id, $name)
+ {
+ return (int) $this->db->table(self::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('name', $name)
+ ->findOneColumn('id');
+ }
+
+ /**
+ * Get a swimlane by the project and the name
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param string $name Swimlane name
+ * @return array
+ */
+ public function getByName($project_id, $name)
+ {
+ return $this->db->table(self::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('name', $name)
+ ->findOne();
+ }
+
+ /**
+ * Get default swimlane properties
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @return array
+ */
+ public function getDefault($project_id)
+ {
+ $result = $this->db->table(Project::TABLE)
+ ->eq('id', $project_id)
+ ->columns('id', 'default_swimlane', 'show_default_swimlane')
+ ->findOne();
+
+ if ($result['default_swimlane'] === 'Default swimlane') {
+ $result['default_swimlane'] = t($result['default_swimlane']);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Get all swimlanes for a given project
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @return array
+ */
+ public function getAll($project_id)
+ {
+ return $this->db->table(self::TABLE)
+ ->eq('project_id', $project_id)
+ ->orderBy('position', 'asc')
+ ->findAll();
+ }
+
+ /**
+ * Get the list of swimlanes by status
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param integer $status Status
+ * @return array
+ */
+ public function getAllByStatus($project_id, $status = self::ACTIVE)
+ {
+ $query = $this->db->table(self::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('is_active', $status);
+
+ if ($status == self::ACTIVE) {
+ $query->asc('position');
+ }
+ else {
+ $query->asc('name');
+ }
+
+ return $query->findAll();
+ }
+
+ /**
+ * Get active swimlanes
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @return array
+ */
+ public function getSwimlanes($project_id)
+ {
+ $swimlanes = $this->db->table(self::TABLE)
+ ->columns('id', 'name')
+ ->eq('project_id', $project_id)
+ ->eq('is_active', self::ACTIVE)
+ ->orderBy('position', 'asc')
+ ->findAll();
+
+ $default_swimlane = $this->db->table(Project::TABLE)
+ ->eq('id', $project_id)
+ ->eq('show_default_swimlane', 1)
+ ->findOneColumn('default_swimlane');
+
+ if ($default_swimlane) {
+
+ if ($default_swimlane === 'Default swimlane') {
+ $default_swimlane = t($default_swimlane);
+ }
+
+ array_unshift($swimlanes, array('id' => 0, 'name' => $default_swimlane));
+ }
+
+ return $swimlanes;
+ }
+
+ /**
+ * Get list of all swimlanes
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param boolean $prepend Prepend default value
+ * @param boolean $only_active Return only active swimlanes
+ * @return array
+ */
+ public function getList($project_id, $prepend = false, $only_active = false)
+ {
+ $swimlanes = array();
+ $default = $this->db->table(Project::TABLE)->eq('id', $project_id)->eq('show_default_swimlane', 1)->findOneColumn('default_swimlane');
+
+ if ($prepend) {
+ $swimlanes[-1] = t('All swimlanes');
+ }
+
+ if (! empty($default)) {
+ $swimlanes[0] = $default === 'Default swimlane' ? t($default) : $default;
+ }
+
+ return $swimlanes + $this->db->hashtable(self::TABLE)
+ ->eq('project_id', $project_id)
+ ->in('is_active', $only_active ? array(self::ACTIVE) : array(self::ACTIVE, self::INACTIVE))
+ ->orderBy('position', 'asc')
+ ->getAll('id', 'name');
+ }
+
+ /**
+ * Add a new swimlane
+ *
+ * @access public
+ * @param integer $project_id
+ * @param string $name
+ * @return integer|boolean
+ */
+ public function create($project_id, $name)
+ {
+ return $this->persist(self::TABLE, array(
+ 'project_id' => $project_id,
+ 'name' => $name,
+ 'position' => $this->getLastPosition($project_id),
+ ));
+ }
+
+ /**
+ * Rename a swimlane
+ *
+ * @access public
+ * @param integer $swimlane_id Swimlane id
+ * @param string $name Swimlane name
+ * @return bool
+ */
+ public function rename($swimlane_id, $name)
+ {
+ return $this->db->table(self::TABLE)
+ ->eq('id', $swimlane_id)
+ ->update(array('name' => $name));
+ }
+
+ /**
+ * Update the default swimlane
+ *
+ * @access public
+ * @param array $values Form values
+ * @return bool
+ */
+ public function updateDefault(array $values)
+ {
+ return $this->db
+ ->table(Project::TABLE)
+ ->eq('id', $values['id'])
+ ->update(array(
+ 'default_swimlane' => $values['default_swimlane'],
+ 'show_default_swimlane' => $values['show_default_swimlane'],
+ ));
+ }
+
+ /**
+ * Get the last position of a swimlane
+ *
+ * @access public
+ * @param integer $project_id
+ * @return integer
+ */
+ public function getLastPosition($project_id)
+ {
+ return $this->db->table(self::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('is_active', 1)
+ ->count() + 1;
+ }
+
+ /**
+ * Disable a swimlane
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param integer $swimlane_id Swimlane id
+ * @return bool
+ */
+ public function disable($project_id, $swimlane_id)
+ {
+ $result = $this->db
+ ->table(self::TABLE)
+ ->eq('id', $swimlane_id)
+ ->update(array(
+ 'is_active' => self::INACTIVE,
+ 'position' => 0,
+ ));
+
+ if ($result) {
+ // Re-order positions
+ $this->updatePositions($project_id);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Enable a swimlane
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param integer $swimlane_id Swimlane id
+ * @return bool
+ */
+ public function enable($project_id, $swimlane_id)
+ {
+ return $this->db
+ ->table(self::TABLE)
+ ->eq('id', $swimlane_id)
+ ->update(array(
+ 'is_active' => self::ACTIVE,
+ 'position' => $this->getLastPosition($project_id),
+ ));
+ }
+
+ /**
+ * Remove a swimlane
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param integer $swimlane_id Swimlane id
+ * @return bool
+ */
+ public function remove($project_id, $swimlane_id)
+ {
+ $this->db->startTransaction();
+
+ // Tasks should not be assigned anymore to this swimlane
+ $this->db->table(Task::TABLE)->eq('swimlane_id', $swimlane_id)->update(array('swimlane_id' => 0));
+
+ if (! $this->db->table(self::TABLE)->eq('id', $swimlane_id)->remove()) {
+ $this->db->cancelTransaction();
+ return false;
+ }
+
+ // Re-order positions
+ $this->updatePositions($project_id);
+
+ $this->db->closeTransaction();
+
+ return true;
+ }
+
+ /**
+ * Update swimlane positions after disabling or removing a swimlane
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @return boolean
+ */
+ public function updatePositions($project_id)
+ {
+ $position = 0;
+ $swimlanes = $this->db->table(self::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('is_active', 1)
+ ->asc('position')
+ ->findAllByColumn('id');
+
+ if (! $swimlanes) {
+ return false;
+ }
+
+ foreach ($swimlanes as $swimlane_id) {
+ $this->db->table(self::TABLE)
+ ->eq('id', $swimlane_id)
+ ->update(array('position' => ++$position));
+ }
+
+ return true;
+ }
+
+ /**
+ * Move a swimlane down, increment the position value
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param integer $swimlane_id Swimlane id
+ * @return boolean
+ */
+ public function moveDown($project_id, $swimlane_id)
+ {
+ $swimlanes = $this->db->hashtable(self::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('is_active', self::ACTIVE)
+ ->asc('position')
+ ->getAll('id', 'position');
+
+ $positions = array_flip($swimlanes);
+
+ if (isset($swimlanes[$swimlane_id]) && $swimlanes[$swimlane_id] < count($swimlanes)) {
+
+ $position = ++$swimlanes[$swimlane_id];
+ $swimlanes[$positions[$position]]--;
+
+ $this->db->startTransaction();
+ $this->db->table(self::TABLE)->eq('id', $swimlane_id)->update(array('position' => $position));
+ $this->db->table(self::TABLE)->eq('id', $positions[$position])->update(array('position' => $swimlanes[$positions[$position]]));
+ $this->db->closeTransaction();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Move a swimlane up, decrement the position value
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param integer $swimlane_id Swimlane id
+ * @return boolean
+ */
+ public function moveUp($project_id, $swimlane_id)
+ {
+ $swimlanes = $this->db->hashtable(self::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('is_active', self::ACTIVE)
+ ->asc('position')
+ ->getAll('id', 'position');
+
+ $positions = array_flip($swimlanes);
+
+ if (isset($swimlanes[$swimlane_id]) && $swimlanes[$swimlane_id] > 1) {
+
+ $position = --$swimlanes[$swimlane_id];
+ $swimlanes[$positions[$position]]++;
+
+ $this->db->startTransaction();
+ $this->db->table(self::TABLE)->eq('id', $swimlane_id)->update(array('position' => $position));
+ $this->db->table(self::TABLE)->eq('id', $positions[$position])->update(array('position' => $swimlanes[$positions[$position]]));
+ $this->db->closeTransaction();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Duplicate Swimlane to project
+ *
+ * @access public
+ * @param integer $project_from Project Template
+ * @param integer $project_to Project that receives the copy
+ * @return integer|boolean
+ */
+
+ public function duplicate($project_from, $project_to)
+ {
+ $swimlanes = $this->getAll($project_from);
+
+ foreach ($swimlanes as $swimlane) {
+
+ unset($swimlane['id']);
+ $swimlane['project_id'] = $project_to;
+
+ if (! $this->db->table(self::TABLE)->save($swimlane)) {
+ return false;
+ }
+ }
+
+ $default_swimlane = $this->getDefault($project_from);
+ $default_swimlane['id'] = $project_to;
+
+ $this->updateDefault($default_swimlane);
+
+ return true;
+ }
+
+ /**
+ * Validate 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 id is required')),
+ new Validators\Required('name', t('The name is required')),
+ );
+
+ $v = new Validator($values, array_merge($rules, $this->commonValidationRules()));
+
+ return array(
+ $v->execute(),
+ $v->getErrors()
+ );
+ }
+
+ /**
+ * Validate 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')),
+ new Validators\Required('name', t('The name is required')),
+ );
+
+ $v = new Validator($values, array_merge($rules, $this->commonValidationRules()));
+
+ return array(
+ $v->execute(),
+ $v->getErrors()
+ );
+ }
+
+ /**
+ * Validate default swimlane modification
+ *
+ * @access public
+ * @param array $values Form values
+ * @return array $valid, $errors [0] = Success or not, [1] = List of errors
+ */
+ public function validateDefaultModification(array $values)
+ {
+ $rules = array(
+ new Validators\Required('id', t('The id is required')),
+ new Validators\Required('default_swimlane', t('The name is required')),
+ );
+
+ $v = new Validator($values, array_merge($rules, $this->commonValidationRules()));
+
+ return array(
+ $v->execute(),
+ $v->getErrors()
+ );
+ }
+
+ /**
+ * Common validation rules
+ *
+ * @access private
+ * @return array
+ */
+ private function commonValidationRules()
+ {
+ return array(
+ new Validators\Integer('id', t('The id must be an integer')),
+ new Validators\Integer('project_id', t('The project id must be an integer')),
+ new Validators\MaxLength('name', t('The maximum length is %d characters', 50), 50)
+ );
+ }
+}