protected function _getByTypeID($type, $id) { $crit = $this->getCriteria(); $crit->addWhere(self::SCOPE, framework\Context::getScope()->getID()); $crit->addWhere($type == 'step' ? self::FROM_STEP_ID : self::TRANSITION_ID, $id); $crit->addJoin(WorkflowTransitions::getTable(), WorkflowTransitions::ID, self::TRANSITION_ID); $return_array = array(); if ($res = $this->doSelect($crit, false)) { while ($row = $res->getNextRow()) { if ($type == 'step') { $return_array[$row->get(self::TRANSITION_ID)] = new \thebuggenie\core\entities\WorkflowTransition($row->get(self::TRANSITION_ID)); } else { $return_array[$row->get(self::FROM_STEP_ID)] = new \thebuggenie\core\entities\WorkflowStep($row->get(self::FROM_STEP_ID)); } } } return $return_array; }
/** * The project board whiteboard page * * @Route(url="/boards/:board_id/whiteboard/issues/*") * @CsrfProtected * * @param framework\Request $request */ public function runWhiteboardIssues(framework\Request $request) { $this->forward403unless($this->_checkProjectPageAccess('project_planning')); $this->board = entities\tables\AgileBoards::getTable()->selectById($request['board_id']); $this->forward403unless($this->board instanceof entities\AgileBoard); try { if ($request->isPost()) { $issue = \thebuggenie\core\entities\tables\Issues::getTable()->selectById((int) $request['issue_id']); $column = entities\BoardColumn::getB2DBTable()->selectById((int) $request['column_id']); $milestone = \thebuggenie\core\entities\Milestone::getB2DBTable()->selectById((int) $request['milestone_id']); $swimlane = null; if ($request['swimlane_identifier']) { foreach ($column->getBoard()->getMilestoneSwimlanes($milestone) as $swimlane) { if ($swimlane->getIdentifier() == $request['swimlane_identifier']) { break; } } } if ($request->hasParameter('transition_id')) { $transitions = array(\thebuggenie\core\entities\tables\WorkflowTransitions::getTable()->selectById((int) $request['transition_id'])); if ($transitions[0]->hasTemplate()) { return $this->renderJSON(array('component' => $this->getComponentHTML('main/issue_workflow_transition', compact('issue')), 'transition_id' => $transitions[0]->getID())); } if (!$transitions[0]->transitionIssueToOutgoingStepWithoutRequest($issue)) { $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('error' => framework\Context::getI18n()->__('There was an error trying to move this issue to the next step in the workflow'), 'message' => preg_replace('/\\s+/', ' ', $this->getComponentHTML('main/issue_transition_error')))); } } else { list($status_ids, $transitions, $rule_status_valid) = $issue->getAvailableWorkflowStatusIDsAndTransitions(); $available_statuses = array_intersect($status_ids, $column->getStatusIds()); if ($rule_status_valid && count($available_statuses) == 1 && count($transitions[reset($available_statuses)]) == 1 && $transitions[reset($available_statuses)][0]->hasTemplate()) { return $this->renderJSON(array('component' => $this->getComponentHTML('main/issue_workflow_transition', compact('issue')), 'transition_id' => $transitions[reset($available_statuses)][0]->getID())); } if (empty($available_statuses)) { $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('error' => $this->getI18n()->__('There are no valid transitions to any states in this column'))); } if (count($available_statuses) > 1 || count($available_statuses) == 1 && count($transitions[reset($available_statuses)]) > 1) { return $this->renderJSON(array('component' => $this->getComponentHTML('agile/whiteboardtransitionselector', array('issue' => $issue, 'transitions' => $transitions, 'statuses' => $available_statuses, 'new_column' => $column, 'board' => $column->getBoard(), 'swimlane_identifier' => $request['swimlane_identifier'])))); } if (!$transitions[reset($available_statuses)][0]->transitionIssueToOutgoingStepWithoutRequest($issue)) { $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('error' => framework\Context::getI18n()->__('There was an error trying to move this issue to the next step in the workflow'), 'message' => preg_replace('/\\s+/', ' ', $this->getComponentHTML('main/issue_transition_error')))); } } return $this->renderJSON(array('transition' => 'ok', 'issue' => $this->getComponentHTML('agile/whiteboardissue', array('issue' => $issue, 'column' => $column, 'swimlane' => $swimlane)))); } else { $milestone = \thebuggenie\core\entities\tables\Milestones::getTable()->selectById((int) $request['milestone_id']); return $this->renderJSON(array('component' => $this->getComponentHTML('agile/whiteboardcontent', array('board' => $this->board, 'milestone' => $milestone)), 'swimlanes' => $this->board->usesSwimlanes() ? 1 : 0)); } } catch (\Exception $e) { $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('error' => $e->getMessage())); } }
public function runConfigureWorkflowTransition(framework\Request $request) { $this->workflow = null; $this->transition = null; try { $this->workflow = tables\Workflows::getTable()->selectById((int) $request['workflow_id']); if ($request->hasParameter('transition_id')) { $mode = $request['mode']; $this->transition = tables\WorkflowTransitions::getTable()->selectById((int) $request['transition_id']); if ($request->isPost()) { if ($mode == 'edit') { if (!$this->transition->isInitialTransition()) { $this->transition->setName($request['transition_name']); $this->transition->setDescription($request['transition_description']); if ($request['template']) { $this->transition->setTemplate($request['template']); } else { $this->transition->setTemplate(null); } } try { $step = tables\WorkflowSteps::getTable()->selectById((int) $request['outgoing_step_id']); $this->transition->setOutgoingStep($step); } catch (\Exception $e) { } $this->transition->save(); $transition = $this->transition; $redirect_transition = true; } elseif ($mode == 'delete') { $this->transition->deleteTransition($request['direction'], $request['step_id']); $this->forward(framework\Context::getRouting()->generate('configure_workflow_step', array('workflow_id' => $this->workflow->getID(), 'step_id' => $request['step_id']))); } elseif ($mode == 'delete_action') { $this->action = tables\WorkflowTransitionActions::getTable()->selectById((int) $request['action_id']); $this->action->delete(); return $this->renderJSON(array('message' => $this->getI18n()->__('The action has been deleted'))); } elseif ($mode == 'new_action') { $action = new entities\WorkflowTransitionAction(); $action->setActionType($request['action_type']); $action->setTransition($this->transition); $action->setWorkflow($this->workflow); $action->setTargetValue(''); $action->save(); return $this->renderJSON(array('content' => $this->getComponentHTML('configuration/workflowtransitionaction', array('action' => $action)))); } elseif ($mode == 'update_action') { $this->action = tables\WorkflowTransitionActions::getTable()->selectById((int) $request['action_id']); $this->action->setTargetValue($request['target_value']); $this->action->save(); $text = $request['target_value']; switch ($this->action->getActionType()) { case entities\WorkflowTransitionAction::ACTION_ASSIGN_ISSUE: if ($this->action->hasTargetValue()) { $target_details = explode('_', $this->action->getTargetValue()); $text = $target_details[0] == 'user' ? entities\User::getB2DBTable()->selectById((int) $target_details[1])->getNameWithUsername() : entities\Team::getB2DBTable()->selectById((int) $target_details[1])->getName(); } else { $text = $this->getI18n()->__('User specified during transition'); } break; case entities\WorkflowTransitionAction::ACTION_SET_RESOLUTION: $text = $this->action->getTargetValue() ? tables\ListTypes::getTable()->selectById((int) $this->action->getTargetValue())->getName() : $this->getI18n()->__('Resolution specified by user'); break; case entities\WorkflowTransitionAction::ACTION_SET_REPRODUCABILITY: $text = $this->action->getTargetValue() ? tables\ListTypes::getTable()->selectById((int) $this->action->getTargetValue())->getName() : $this->getI18n()->__('Reproducability specified by user'); break; case entities\WorkflowTransitionAction::ACTION_SET_STATUS: $target = $this->action->getTargetValue() ? tables\ListTypes::getTable()->selectById((int) $this->action->getTargetValue()) : null; $text = $this->action->getTargetValue() ? '<span class="status_badge" style="background-color: ' . $target->getColor() . '; color: ' . $target->getTextColor() . ';">' . $target->getName() . '</span>' : $this->getI18n()->__('Status provided by user'); break; case entities\WorkflowTransitionAction::ACTION_SET_PRIORITY: $text = $this->action->getTargetValue() ? tables\ListTypes::getTable()->selectById((int) $this->action->getTargetValue())->getName() : $this->getI18n()->__('Priority specified by user'); break; case entities\WorkflowTransitionAction::ACTION_SET_MILESTONE: $target = $this->action->getTargetValue() ? \thebuggenie\core\entities\tables\ListTypes::getTable()->selectById((int) $this->action->getTargetValue()) : null; $text = $this->action->getTargetValue() ? $target->getProject()->getName() . ' - ' . $target->getName() : $this->getI18n()->__('Milestone specified by user'); break; case entities\WorkflowTransitionAction::CUSTOMFIELD_SET_PREFIX . $this->action->getCustomActionType(): switch (\thebuggenie\core\entities\CustomDatatype::getByKey($this->action->getCustomActionType())->getType()) { case \thebuggenie\core\entities\CustomDatatype::INPUT_TEXTAREA_MAIN: case \thebuggenie\core\entities\CustomDatatype::INPUT_TEXTAREA_SMALL: break; case \thebuggenie\core\entities\CustomDatatype::DATE_PICKER: return $this->renderJSON(array('content' => date('Y-m-d', (int) $text))); break; case \thebuggenie\core\entities\CustomDatatype::USER_CHOICE: return $this->renderJSON(array('content' => $this->getComponentHTML('main/userdropdown', array('user' => $text)))); break; case \thebuggenie\core\entities\CustomDatatype::TEAM_CHOICE: return $this->renderJSON(array('content' => $this->getComponentHTML('main/teamdropdown', array('team' => $text)))); break; case \thebuggenie\core\entities\CustomDatatype::CLIENT_CHOICE: if (is_numeric($this->action->getTargetValue())) { $text = $this->action->getTargetValue() ? \thebuggenie\core\entities\tables\Clients::getTable()->selectById((int) $this->action->getTargetValue())->getName() : $this->getI18n()->__('Value provided by user'); } break; case \thebuggenie\core\entities\CustomDatatype::RELEASES_CHOICE: if (is_numeric($this->action->getTargetValue())) { $target = $this->action->getTargetValue() ? \thebuggenie\core\entities\tables\Builds::getTable()->selectById((int) $this->action->getTargetValue()) : null; $text = $this->action->getTargetValue() ? $target->getProject()->getName() . ' - ' . $target->getName() : $this->getI18n()->__('Value provided by user'); } break; case \thebuggenie\core\entities\CustomDatatype::COMPONENTS_CHOICE: if (is_numeric($this->action->getTargetValue())) { $target = $this->action->getTargetValue() ? \thebuggenie\core\entities\tables\Components::getTable()->selectById((int) $this->action->getTargetValue()) : null; $text = $this->action->getTargetValue() ? $target->getProject()->getName() . ' - ' . $target->getName() : $this->getI18n()->__('Value provided by user'); } break; case \thebuggenie\core\entities\CustomDatatype::EDITIONS_CHOICE: if (is_numeric($this->action->getTargetValue())) { $target = $this->action->getTargetValue() ? \thebuggenie\core\entities\tables\Editions::getTable()->selectById((int) $this->action->getTargetValue()) : null; $text = $this->action->getTargetValue() ? $target->getProject()->getName() . ' - ' . $target->getName() : $this->getI18n()->__('Value provided by user'); } break; case \thebuggenie\core\entities\CustomDatatype::MILESTONE_CHOICE: if (is_numeric($this->action->getTargetValue())) { $target = $this->action->getTargetValue() ? \thebuggenie\core\entities\tables\Milestones::getTable()->selectById((int) $this->action->getTargetValue()) : null; $text = $this->action->getTargetValue() ? $target->getProject()->getName() . ' - ' . $target->getName() : $this->getI18n()->__('Value provided by user'); } break; case \thebuggenie\core\entities\CustomDatatype::STATUS_CHOICE: if (is_numeric($this->action->getTargetValue())) { $target = $this->action->getTargetValue() ? tables\ListTypes::getTable()->selectById((int) $this->action->getTargetValue()) : null; $text = $this->action->getTargetValue() ? '<span class="status_badge" style="background-color: ' . $target->getColor() . '; color: ' . $target->getTextColor() . ';">' . $target->getName() . '</span>' : $this->getI18n()->__('Value provided by user'); } break; case \thebuggenie\core\entities\CustomDatatype::DROPDOWN_CHOICE_TEXT: default: if (is_numeric($this->action->getTargetValue())) { $text = $this->action->getTargetValue() ? tables\CustomFieldOptions::getTable()->selectById((int) $this->action->getTargetValue())->getName() : $this->getI18n()->__('Value provided by user'); } break; } break; } return $this->renderJSON(array('content' => $text)); } elseif ($mode == 'delete_validation_rule') { $this->rule = tables\WorkflowTransitionValidationRules::getTable()->selectById((int) $request['rule_id']); $this->rule->delete(); return $this->renderJSON(array('message' => $this->getI18n()->__('The validation rule has been deleted'))); } elseif ($mode == 'new_validation_rule') { if (!in_array($request['postorpre'], array('post', 'pre'))) { throw new \InvalidArgumentException($this->getI18n()->__('Invalid transition definition')); } $rule = new entities\WorkflowTransitionValidationRule(); if ($request['postorpre'] == 'post') { $exists = (bool) $this->transition->hasPostValidationRule($request['rule']); if (!$exists) { $rule->setPost(); } } elseif ($request['postorpre'] == 'pre') { $exists = (bool) $this->transition->hasPreValidationRule($request['rule']); if (!$exists) { $rule->setPre(); } } if ($exists) { $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('message' => $this->getI18n()->__('This validation rule already exist'))); } $rule->setRule($request['rule']); $rule->setRuleValue(''); $rule->setTransition($this->transition); $rule->setWorkflow($this->workflow); $rule->save(); return $this->renderJSON(array('content' => $this->getComponentHTML('configuration/workflowtransitionvalidationrule', array('rule' => $rule)))); } elseif ($mode == 'update_validation_rule') { $rule = tables\WorkflowTransitionValidationRules::getTable()->selectById((int) $request['rule_id']); $text = null; if ($rule->isCustom()) { switch ($rule->getCustomType()) { case entities\CustomDatatype::RADIO_CHOICE: case entities\CustomDatatype::DROPDOWN_CHOICE_TEXT: case entities\CustomDatatype::TEAM_CHOICE: case entities\CustomDatatype::STATUS_CHOICE: case entities\CustomDatatype::MILESTONE_CHOICE: case entities\CustomDatatype::CLIENT_CHOICE: case entities\CustomDatatype::COMPONENTS_CHOICE: case entities\CustomDatatype::EDITIONS_CHOICE: case entities\CustomDatatype::RELEASES_CHOICE: $rule->setRuleValue(join(',', $request['rule_value'] ?: array())); $text = $rule->getRuleValue() ? $rule->getRuleValueAsJoinedString() : $this->getI18n()->__('Any valid value'); break; } } else { switch ($rule->getRule()) { case entities\WorkflowTransitionValidationRule::RULE_MAX_ASSIGNED_ISSUES: $rule->setRuleValue($request['rule_value']); $text = $rule->getRuleValue() ? $rule->getRuleValue() : $this->getI18n()->__('Unlimited'); break; case entities\WorkflowTransitionValidationRule::RULE_PRIORITY_VALID: case entities\WorkflowTransitionValidationRule::RULE_REPRODUCABILITY_VALID: case entities\WorkflowTransitionValidationRule::RULE_RESOLUTION_VALID: case entities\WorkflowTransitionValidationRule::RULE_STATUS_VALID: case entities\WorkflowTransitionValidationRule::RULE_TEAM_MEMBERSHIP_VALID: case entities\WorkflowTransitionValidationRule::RULE_ISSUE_IN_MILESTONE_VALID: $rule->setRuleValue(join(',', $request['rule_value'] ?: array())); $text = $rule->getRuleValue() ? $rule->getRuleValueAsJoinedString() : $this->getI18n()->__('Any valid value'); break; } } $rule->save(); $this->rule = $rule; return $this->renderJSON(array('content' => $text)); } } } elseif ($request->isPost() && $request->hasParameter('step_id')) { $step = tables\WorkflowSteps::getTable()->selectById((int) $request['step_id']); if ($request['add_transition_type'] == 'existing' && $request->hasParameter('existing_transition_id')) { $transition = tables\WorkflowTransitions::getTable()->selectById((int) $request['existing_transition_id']); $redirect_transition = false; } else { if ($request['transition_name'] && $request['outgoing_step_id'] && $request->hasParameter('template')) { if (($outgoing_step = tables\WorkflowSteps::getTable()->selectById((int) $request['outgoing_step_id'])) && $step instanceof entities\WorkflowStep) { if (!$request['template'] || array_key_exists($request['template'], entities\WorkflowTransition::getTemplates())) { $transition = new entities\WorkflowTransition(); $transition->setWorkflow($this->workflow); $transition->setName($request['transition_name']); $transition->setDescription($request['transition_description']); $transition->setOutgoingStep($outgoing_step); $transition->setTemplate($request['template']); $transition->save(); $step->addOutgoingTransition($transition); $redirect_transition = true; } else { throw new \InvalidArgumentException($this->getI18n()->__('Please select a valid template')); } } else { throw new \InvalidArgumentException($this->getI18n()->__('Please select a valid outgoing step')); } } else { throw new \InvalidArgumentException($this->getI18n()->__('Please fill in all required fields')); } } $step->addOutgoingTransition($transition); } else { throw new \InvalidArgumentException('Invalid action'); } } catch (\InvalidArgumentException $e) { $this->error = $e->getMessage(); } catch (\Exception $e) { $this->error = $this->getI18n()->__('This workflow / transition does not exist'); } if (isset($redirect_transition) && $redirect_transition) { $this->forward(framework\Context::getRouting()->generate('configure_workflow_transition', array('workflow_id' => $this->workflow->getID(), 'transition_id' => $transition->getID()))); } elseif (isset($redirect_transition)) { $this->forward(framework\Context::getRouting()->generate('configure_workflow_steps', array('workflow_id' => $this->workflow->getID()))); } }
public function getNumberOfIncomingTransitions() { if ($this->_num_incoming_transitions === null && $this->_incoming_transitions !== null) { $this->_num_incoming_transitions = count($this->_incoming_transitions); } elseif ($this->_num_incoming_transitions === null) { $this->_num_incoming_transitions = tables\WorkflowTransitions::getTable()->countByStepID($this->getID()); } return $this->_num_incoming_transitions; }
public function copy($new_name) { $new_workflow = new \thebuggenie\core\entities\Workflow(); $new_workflow->setName($new_name); $new_workflow->save(); $step_mapper = array(); $transition_mapper = array(); foreach ($this->getSteps() as $key => $step) { $this->_steps[$key] = $step->copy($new_workflow); $step_mapper[$key] = $this->_steps[$key]->getID(); } foreach ($this->getTransitions() as $key => $transition) { $old_id = $transition->getID(); $this->_transitions[$key] = $transition->copy($new_workflow); $transition_mapper[$old_id] = $this->_transitions[$key]->getID(); } tables\WorkflowStepTransitions::getTable()->copyByWorkflowIDs($this->getID(), $new_workflow->getID()); tables\WorkflowStepTransitions::getTable()->reMapStepIDsByWorkflowID($new_workflow->getID(), $step_mapper); tables\WorkflowTransitions::getTable()->reMapByWorkflowID($new_workflow->getID(), $step_mapper); tables\WorkflowStepTransitions::getTable()->reMapTransitionIDsByWorkflowID($new_workflow->getID(), $transition_mapper); $new_initial_transition = $this->getInitialTransition()->copy($new_workflow); $new_initial_transition->setOutgoingStepID($step_mapper[$this->getInitialTransition()->getOutgoingStep()->getID()]); $new_initial_transition->save(); $new_workflow->setInitialTransition($new_initial_transition); $new_workflow->save(); return $new_workflow; }
/** * The project board whiteboard page * * @Route(url="/boards/:board_id/whiteboard/issues/*") * @CsrfProtected * * @param framework\Request $request */ public function runWhiteboardIssues(framework\Request $request) { $this->forward403unless($this->_checkProjectPageAccess('agile_board')); $this->board = entities\tables\AgileBoards::getTable()->selectById($request['board_id']); $this->forward403unless($this->board instanceof entities\AgileBoard); try { if ($request->isPost()) { $issue = \thebuggenie\core\entities\tables\Issues::getTable()->selectById((int) $request['issue_id']); $column = entities\BoardColumn::getB2DBTable()->selectById((int) $request['column_id']); $milestone = \thebuggenie\core\entities\Milestone::getB2DBTable()->selectById((int) $request['milestone_id']); $swimlane = null; if ($request['swimlane_identifier']) { foreach ($column->getBoard()->getMilestoneSwimlanes($milestone) as $swimlane) { if ($swimlane->getIdentifier() == $request['swimlane_identifier']) { break; } } } if ($request->hasParameter('transition_id')) { $transitions = array(\thebuggenie\core\entities\tables\WorkflowTransitions::getTable()->selectById((int) $request['transition_id'])); } else { list($status_ids, $transitions) = $issue->getAvailableWorkflowStatusIDsAndTransitions(); $available_statuses = array_intersect($status_ids, $column->getStatusIds()); if (empty($available_statuses)) { $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('error' => $this->getI18n()->__('There are no valid transitions to any states in this column'))); } if (count($available_statuses) > 1) { return $this->renderJSON(array('component' => $this->getComponentHTML('agile/whiteboardtransitionselector', array('issue' => $issue, 'transitions' => $transitions, 'statuses' => $available_statuses, 'new_column' => $column, 'board' => $column->getBoard(), 'swimlane_identifier' => $request['swimlane_identifier'])))); } } current($transitions)->transitionIssueToOutgoingStepWithoutRequest($issue); return $this->renderJSON(array('transition' => 'ok', 'issue' => $this->getComponentHTML('agile/whiteboardissue', array('issue' => $issue, 'column' => $column, 'swimlane' => $swimlane)))); } else { $milestone = \thebuggenie\core\entities\tables\Milestones::getTable()->selectById((int) $request['milestone_id']); return $this->renderJSON(array('component' => $this->getComponentHTML('agile/whiteboardcontent', array('board' => $this->board, 'milestone' => $milestone)))); } } catch (\Exception $e) { $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('error' => $e->getMessage())); } }