summaryrefslogtreecommitdiff
path: root/app/Model/TaskDuplication.php
diff options
context:
space:
mode:
Diffstat (limited to 'app/Model/TaskDuplication.php')
-rwxr-xr-xapp/Model/TaskDuplication.php248
1 files changed, 248 insertions, 0 deletions
diff --git a/app/Model/TaskDuplication.php b/app/Model/TaskDuplication.php
new file mode 100755
index 00000000..afcac4c7
--- /dev/null
+++ b/app/Model/TaskDuplication.php
@@ -0,0 +1,248 @@
+<?php
+
+namespace Model;
+
+use DateTime;
+use DateInterval;
+use Event\TaskEvent;
+
+/**
+ * Task Duplication
+ *
+ * @package model
+ * @author Frederic Guillot
+ */
+class TaskDuplication extends Base
+{
+ /**
+ * Fields to copy when duplicating a task
+ *
+ * @access private
+ * @var array
+ */
+ private $fields_to_duplicate = array(
+ 'title',
+ 'description',
+ 'date_due',
+ 'color_id',
+ 'project_id',
+ 'column_id',
+ 'owner_id',
+ 'score',
+ 'category_id',
+ 'time_estimated',
+ 'swimlane_id',
+ 'recurrence_status',
+ 'recurrence_trigger',
+ 'recurrence_factor',
+ 'recurrence_timeframe',
+ 'recurrence_basedate',
+ );
+
+ /**
+ * Duplicate a task to the same project
+ *
+ * @access public
+ * @param integer $task_id Task id
+ * @return boolean|integer Duplicated task id
+ */
+ public function duplicate($task_id)
+ {
+ return $this->save($task_id, $this->copyFields($task_id));
+ }
+
+ /**
+ * Duplicate recurring task
+ *
+ * @access public
+ * @param integer $task_id Task id
+ * @return boolean|integer Recurrence task id
+ */
+ public function duplicateRecurringTask($task_id)
+ {
+ $values = $this->copyFields($task_id);
+
+ if ($values['recurrence_status'] == Task::RECURRING_STATUS_PENDING) {
+
+ $values['recurrence_parent'] = $task_id;
+ $values['column_id'] = $this->board->getFirstColumn($values['project_id']);
+ $this->calculateRecurringTaskDueDate($values);
+
+ $recurring_task_id = $this->save($task_id, $values);
+
+ if ($recurring_task_id > 0) {
+
+ $parent_update = $this->db
+ ->table(Task::TABLE)
+ ->eq('id', $task_id)
+ ->update(array(
+ 'recurrence_status' => Task::RECURRING_STATUS_PROCESSED,
+ 'recurrence_child' => $recurring_task_id,
+ ));
+
+ if ($parent_update) {
+ return $recurring_task_id;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Duplicate a task to another project
+ *
+ * @access public
+ * @param integer $task_id Task id
+ * @param integer $project_id Project id
+ * @return boolean|integer Duplicated task id
+ */
+ public function duplicateToProject($task_id, $project_id)
+ {
+ $values = $this->copyFields($task_id);
+ $values['project_id'] = $project_id;
+ $values['column_id'] = $this->board->getFirstColumn($project_id);
+
+ $this->checkDestinationProjectValues($values);
+
+ return $this->save($task_id, $values);
+ }
+
+ /**
+ * Move a task to another project
+ *
+ * @access public
+ * @param integer $task_id Task id
+ * @param integer $project_id Project id
+ * @return boolean
+ */
+ public function moveToProject($task_id, $project_id)
+ {
+ $task = $this->taskFinder->getById($task_id);
+
+ $values = array();
+ $values['is_active'] = 1;
+ $values['project_id'] = $project_id;
+ $values['column_id'] = $this->board->getFirstColumn($project_id);
+ $values['position'] = $this->taskFinder->countByColumnId($project_id, $values['column_id']) + 1;
+ $values['owner_id'] = $task['owner_id'];
+ $values['category_id'] = $task['category_id'];
+ $values['swimlane_id'] = $task['swimlane_id'];
+
+ $this->checkDestinationProjectValues($values);
+
+ if ($this->db->table(Task::TABLE)->eq('id', $task['id'])->update($values)) {
+ $this->container['dispatcher']->dispatch(
+ Task::EVENT_MOVE_PROJECT,
+ new TaskEvent(array_merge($task, $values, array('task_id' => $task['id'])))
+ );
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if the assignee and the category are available in the destination project
+ *
+ * @access private
+ * @param array $values
+ */
+ private function checkDestinationProjectValues(&$values)
+ {
+ // Check if the assigned user is allowed for the destination project
+ if ($values['owner_id'] > 0 && ! $this->projectPermission->isUserAllowed($values['project_id'], $values['owner_id'])) {
+ $values['owner_id'] = 0;
+ }
+
+ // Check if the category exists for the destination project
+ if ($values['category_id'] > 0) {
+ $values['category_id'] = $this->category->getIdByName(
+ $values['project_id'],
+ $this->category->getNameById($values['category_id'])
+ );
+ }
+
+ // Check if the swimlane exists for the destination project
+ if ($values['swimlane_id'] > 0) {
+ $values['swimlane_id'] = $this->swimlane->getIdByName(
+ $values['project_id'],
+ $this->swimlane->getNameById($values['swimlane_id'])
+ );
+ }
+ }
+
+ /**
+ * Calculate new due date for new recurrence task
+ *
+ * @access public
+ * @param array $values Task fields
+ */
+ public function calculateRecurringTaskDueDate(array &$values)
+ {
+ if (! empty($values['date_due']) && $values['recurrence_factor'] != 0) {
+
+ if ($values['recurrence_basedate'] == Task::RECURRING_BASEDATE_TRIGGERDATE) {
+ $values['date_due'] = time();
+ }
+
+ $factor = abs($values['recurrence_factor']);
+ $subtract = $values['recurrence_factor'] < 0;
+
+ switch ($values['recurrence_timeframe']) {
+ case Task::RECURRING_TIMEFRAME_MONTHS:
+ $interval = 'P' . $factor . 'M';
+ break;
+ case Task::RECURRING_TIMEFRAME_YEARS:
+ $interval = 'P' . $factor . 'Y';
+ break;
+ default:
+ $interval = 'P' . $factor . 'D';
+ }
+
+ $date_due = new DateTime();
+ $date_due->setTimestamp($values['date_due']);
+
+ $subtract ? $date_due->sub(new DateInterval($interval)) : $date_due->add(new DateInterval($interval));
+
+ $values['date_due'] = $date_due->getTimestamp();
+ }
+ }
+
+ /**
+ * Duplicate fields for the new task
+ *
+ * @access private
+ * @param integer $task_id Task id
+ * @return array
+ */
+ private function copyFields($task_id)
+ {
+ $task = $this->taskFinder->getById($task_id);
+ $values = array();
+
+ foreach ($this->fields_to_duplicate as $field) {
+ $values[$field] = $task[$field];
+ }
+
+ return $values;
+ }
+
+ /**
+ * Create the new task and duplicate subtasks
+ *
+ * @access private
+ * @param integer $task_id Task id
+ * @param array $values Form values
+ * @return boolean|integer
+ */
+ private function save($task_id, array $values)
+ {
+ $new_task_id = $this->taskCreation->create($values);
+
+ if ($new_task_id) {
+ $this->subtask->duplicate($task_id, $new_task_id);
+ }
+
+ return $new_task_id;
+ }
+}