Exemplo n.º 1
0
 public function processIncomingEmailCommand($content, Issue $issue)
 {
     if (!$issue->isWorkflowTransitionsAvailable()) {
         return false;
     }
     $lines = preg_split("/(\r?\n)/", $content);
     $first_line = array_shift($lines);
     $commands = explode(" ", trim($first_line));
     $command = array_shift($commands);
     foreach ($issue->getAvailableWorkflowTransitions() as $transition) {
         if (strpos(str_replace(array(' ', '/'), array('', ''), mb_strtolower($transition->getName())), str_replace(array(' ', '/'), array('', ''), mb_strtolower($command))) !== false) {
             foreach ($commands as $single_command) {
                 if (mb_strpos($single_command, '=')) {
                     list($key, $val) = explode('=', $single_command);
                     switch ($key) {
                         case 'resolution':
                             if (($resolution = Resolution::getByKeyish($val)) instanceof Resolution) {
                                 framework\Context::getRequest()->setParameter('resolution_id', $resolution->getID());
                             }
                             break;
                         case 'status':
                             if (($status = Status::getByKeyish($val)) instanceof Status) {
                                 framework\Context::getRequest()->setParameter('status_id', $status->getID());
                             }
                             break;
                     }
                 }
             }
             framework\Context::getRequest()->setParameter('comment_body', join("\n", $lines));
             return $transition->transitionIssueToOutgoingStepWithoutRequest($issue);
         }
     }
 }
Exemplo n.º 2
0
 public static function loadFixtures(\thebuggenie\core\entities\Scope $scope, \thebuggenie\core\entities\Workflow $workflow, $steps)
 {
     $rejected_resolutions = array();
     $rejected_resolutions[] = Resolution::getByKeyish('notanissue')->getID();
     $rejected_resolutions[] = Resolution::getByKeyish('wontfix')->getID();
     $rejected_resolutions[] = Resolution::getByKeyish('cantfix')->getID();
     $rejected_resolutions[] = Resolution::getByKeyish('cantreproduce')->getID();
     $rejected_resolutions[] = Resolution::getByKeyish('duplicate')->getID();
     $resolved_resolutions = array();
     $resolved_resolutions[] = Resolution::getByKeyish('resolved')->getID();
     $resolved_resolutions[] = Resolution::getByKeyish('wontfix')->getID();
     $resolved_resolutions[] = Resolution::getByKeyish('postponed')->getID();
     $resolved_resolutions[] = Resolution::getByKeyish('duplicate')->getID();
     $closed_statuses = array();
     $closed_statuses[] = Status::getByKeyish('closed')->getID();
     $closed_statuses[] = Status::getByKeyish('postponed')->getID();
     $closed_statuses[] = Status::getByKeyish('done')->getID();
     $closed_statuses[] = Status::getByKeyish('fixed')->getID();
     $transitions = array();
     $transitions['investigateissue'] = array('name' => 'Investigate issue', 'description' => 'Assign the issue to yourself and start investigating it', 'outgoing_step' => 'investigating', 'template' => null, 'pre_validations' => array(WorkflowTransitionValidationRule::RULE_MAX_ASSIGNED_ISSUES => 5), 'actions' => array(WorkflowTransitionAction::ACTION_ASSIGN_ISSUE_SELF => 0));
     $transitions['requestmoreinformation'] = array('name' => 'Request more information', 'description' => 'Move issue back to new state for more details', 'outgoing_step' => 'new', 'template' => 'main/updateissueproperties', 'actions' => array(WorkflowTransitionAction::ACTION_CLEAR_ASSIGNEE => 0));
     $transitions['confirmissue'] = array('name' => 'Confirm issue', 'description' => 'Confirm that the issue is valid', 'outgoing_step' => 'confirmed', 'template' => null, 'actions' => array(WorkflowTransitionAction::ACTION_SET_PERCENT => 10));
     $transitions['rejectissue'] = array('name' => 'Reject issue', 'description' => 'Reject the issue as invalid', 'outgoing_step' => 'rejected', 'template' => 'main/updateissueproperties', 'post_validations' => array(WorkflowTransitionValidationRule::RULE_RESOLUTION_VALID => join(',', $rejected_resolutions)), 'actions' => array(WorkflowTransitionAction::ACTION_SET_RESOLUTION => 0, WorkflowTransitionAction::ACTION_SET_DUPLICATE => 0, WorkflowTransitionAction::ACTION_SET_PERCENT => 100, WorkflowTransitionAction::ACTION_USER_STOP_WORKING => 0));
     $transitions['acceptissue'] = array('name' => 'Accept issue', 'description' => 'Accept the issue and assign it to yourself', 'outgoing_step' => 'inprogress', 'template' => null, 'pre_validations' => array(WorkflowTransitionValidationRule::RULE_MAX_ASSIGNED_ISSUES => 5), 'actions' => array(WorkflowTransitionAction::ACTION_ASSIGN_ISSUE_SELF => 0, WorkflowTransitionAction::ACTION_USER_START_WORKING => 0));
     $transitions['reopenissue'] = array('name' => 'Reopen issue', 'description' => 'Reopen the issue', 'outgoing_step' => 'new', 'template' => null, 'actions' => array(WorkflowTransitionAction::ACTION_CLEAR_RESOLUTION => 0, WorkflowTransitionAction::ACTION_CLEAR_DUPLICATE => 0, WorkflowTransitionAction::ACTION_CLEAR_PERCENT => 0));
     $transitions['assignissue'] = array('name' => 'Assign issue', 'description' => 'Accept the issue and assign it to someone', 'outgoing_step' => 'inprogress', 'template' => 'main/updateissueproperties', 'actions' => array(WorkflowTransitionAction::ACTION_ASSIGN_ISSUE => 0, WorkflowTransitionAction::ACTION_USER_START_WORKING => 0));
     $transitions['markreadyfortesting'] = array('name' => 'Mark ready for testing', 'description' => 'Mark the issue as ready to be tested', 'outgoing_step' => 'readyfortesting', 'template' => null, 'actions' => array(WorkflowTransitionAction::ACTION_CLEAR_ASSIGNEE => 0, WorkflowTransitionAction::ACTION_USER_STOP_WORKING => 0));
     $transitions['resolveissue'] = array('name' => 'Resolve issue', 'description' => 'Resolve the issue', 'outgoing_step' => 'closed', 'template' => 'main/updateissueproperties', 'post_validations' => array(WorkflowTransitionValidationRule::RULE_STATUS_VALID => join(',', $closed_statuses), WorkflowTransitionValidationRule::RULE_RESOLUTION_VALID => join(',', $resolved_resolutions)), 'actions' => array(WorkflowTransitionAction::ACTION_SET_STATUS => 0, WorkflowTransitionAction::ACTION_SET_PERCENT => 100, WorkflowTransitionAction::ACTION_SET_RESOLUTION => 0, WorkflowTransitionAction::ACTION_USER_STOP_WORKING => 0));
     $transitions['testissuesolution'] = array('name' => 'Test issue solution', 'description' => 'Check whether the solution is valid', 'outgoing_step' => 'testing', 'template' => null, 'actions' => array(WorkflowTransitionAction::ACTION_ASSIGN_ISSUE_SELF => 0, WorkflowTransitionAction::ACTION_USER_START_WORKING => 0));
     $transitions['acceptissuesolution'] = array('name' => 'Accept issue solution', 'description' => 'Mark the issue as resolved', 'outgoing_step' => 'closed', 'template' => 'main/updateissueproperties', 'actions' => array(WorkflowTransitionAction::ACTION_SET_RESOLUTION => 0, WorkflowTransitionAction::ACTION_CLEAR_ASSIGNEE => 0, WorkflowTransitionAction::ACTION_USER_STOP_WORKING => 0));
     $transitions['rejectissuesolution'] = array('name' => 'Reject issue solution', 'description' => 'Reject the proposed solution and mark the issue as in progress', 'outgoing_step' => 'inprogress', 'template' => null, 'actions' => array(WorkflowTransitionAction::ACTION_SET_RESOLUTION => 0, WorkflowTransitionAction::ACTION_CLEAR_ASSIGNEE => 0, WorkflowTransitionAction::ACTION_USER_STOP_WORKING => 0));
     foreach ($transitions as $key => $transition) {
         $transition_object = new \thebuggenie\core\entities\WorkflowTransition();
         $transition_object->setName($transition['name']);
         $transition_object->setDescription($transition['description']);
         $transition_object->setOutgoingStep($steps[$transition['outgoing_step']]['step']);
         $transition_object->setTemplate($transition['template']);
         $transition_object->setWorkflow($workflow);
         $transition_object->save();
         $transitions[$key] = $transition_object;
         if (array_key_exists('pre_validations', $transition) && is_array($transition['pre_validations'])) {
             foreach ($transition['pre_validations'] as $type => $validation) {
                 $rule = new \thebuggenie\core\entities\WorkflowTransitionValidationRule();
                 $rule->setTransition($transition_object);
                 $rule->setPre();
                 $rule->setRule($type);
                 $rule->setRuleValue($validation);
                 $rule->setWorkflow($workflow);
                 $rule->save();
             }
         }
         if (array_key_exists('post_validations', $transition) && is_array($transition['post_validations'])) {
             foreach ($transition['post_validations'] as $type => $validation) {
                 $rule = new \thebuggenie\core\entities\WorkflowTransitionValidationRule();
                 $rule->setTransition($transition_object);
                 $rule->setPost();
                 $rule->setRule($type);
                 $rule->setRuleValue($validation);
                 $rule->setWorkflow($workflow);
                 $rule->save();
             }
         }
         if (array_key_exists('actions', $transition) && is_array($transition['actions'])) {
             foreach ($transition['actions'] as $type => $action) {
                 $action_object = new \thebuggenie\core\entities\WorkflowTransitionAction();
                 $action_object->setActionType($type);
                 $action_object->setTransition($transition_object);
                 $action_object->setWorkflow($workflow);
                 if (!is_null($action)) {
                     $action_object->setTargetValue($action);
                 }
                 $action_object->save();
             }
         }
     }
     return $transitions;
 }
Exemplo n.º 3
0
 public static function processCommit(\thebuggenie\core\entities\Project $project, $commit_msg, $old_rev, $new_rev, $date = null, $changed, $author, $branch = null, \Closure $callback = null)
 {
     $output = '';
     framework\Context::setCurrentProject($project);
     if ($project->isArchived()) {
         return;
     }
     if (Commits::getTable()->isProjectCommitProcessed($new_rev, $project->getID())) {
         return;
     }
     try {
         framework\Context::getI18n();
     } catch (\Exception $e) {
         framework\Context::reinitializeI18n(null);
     }
     // Is VCS Integration enabled?
     if (framework\Settings::get('vcs_mode_' . $project->getID(), 'vcs_integration') == self::MODE_DISABLED) {
         $output .= '[VCS ' . $project->getKey() . '] This project does not use VCS Integration' . "\n";
         return $output;
     }
     // Parse the commit message, and obtain the issues and transitions for issues.
     $parsed_commit = \thebuggenie\core\entities\Issue::getIssuesFromTextByRegex($commit_msg);
     $issues = $parsed_commit["issues"];
     $transitions = $parsed_commit["transitions"];
     // Build list of affected files
     $file_lines = preg_split('/[\\n\\r]+/', $changed);
     $files = array();
     foreach ($file_lines as $aline) {
         $action = mb_substr($aline, 0, 1);
         if ($action == "A" || $action == "U" || $action == "D" || $action == "M") {
             $theline = trim(mb_substr($aline, 1));
             $files[] = array($action, $theline);
         }
     }
     // Find author of commit, fallback is guest
     /*
      * Some VCSes use a different format of storing the committer's name. Systems like bzr, git and hg use the format
      * Joe Bloggs <*****@*****.**>, instead of a classic username. Therefore a user will be found via 4 queries:
      * a) First we extract the email if there is one, and find a user with that email
      * b) If one is not found - or if no email was specified, then instead test against the real name (using the name part if there was an email)
      * c) the username or full name is checked against the friendly name field
      * d) and if we still havent found one, then we check against the username
      * e) and if we STILL havent found one, we use the guest user
      */
     // a)
     $user = \thebuggenie\core\entities\tables\Users::getTable()->getByEmail($author);
     if (!$user instanceof \thebuggenie\core\entities\User && preg_match("/(?<=<)(.*)(?=>)/", $author, $matches)) {
         $email = $matches[0];
         // a2)
         $user = \thebuggenie\core\entities\tables\Users::getTable()->getByEmail($email);
         if (!$user instanceof \thebuggenie\core\entities\User) {
             // Not found by email
             preg_match("/(?<=^)(.*)(?= <)/", $author, $matches);
             $author = $matches[0];
         }
     }
     // b)
     if (!$user instanceof \thebuggenie\core\entities\User) {
         $user = \thebuggenie\core\entities\tables\Users::getTable()->getByRealname($author);
     }
     // c)
     if (!$user instanceof \thebuggenie\core\entities\User) {
         $user = \thebuggenie\core\entities\tables\Users::getTable()->getByBuddyname($author);
     }
     // d)
     if (!$user instanceof \thebuggenie\core\entities\User) {
         $user = \thebuggenie\core\entities\tables\Users::getTable()->getByUsername($author);
     }
     // e)
     if (!$user instanceof \thebuggenie\core\entities\User) {
         $user = framework\Settings::getDefaultUser();
     }
     framework\Context::setUser($user);
     framework\Settings::forceSettingsReload();
     framework\Context::cacheAllPermissions();
     $output .= '[VCS ' . $project->getKey() . '] Commit to be logged by user ' . $user->getName() . "\n";
     if ($date == null) {
         $date = NOW;
     }
     // Create the commit data
     $commit = new Commit();
     $commit->setAuthor($user);
     $commit->setDate($date);
     $commit->setLog($commit_msg);
     $commit->setPreviousRevision($old_rev);
     $commit->setRevision($new_rev);
     $commit->setProject($project);
     if ($branch !== null) {
         $data = 'branch:' . $branch;
         $commit->setMiscData($data);
     }
     if ($callback !== null) {
         $commit = $callback($commit);
     }
     $commit->save();
     $output .= '[VCS ' . $project->getKey() . '] Commit logged with revision ' . $commit->getRevision() . "\n";
     // Iterate over affected issues and update them.
     foreach ($issues as $issue) {
         $inst = new IssueLink();
         $inst->setIssue($issue);
         $inst->setCommit($commit);
         $inst->save();
         // Process all commit-message transitions for an issue.
         foreach ($transitions[$issue->getFormattedIssueNo()] as $transition) {
             if (framework\Settings::get('vcs_workflow_' . $project->getID(), 'vcs_integration') == self::WORKFLOW_ENABLED) {
                 framework\Context::setUser($user);
                 framework\Settings::forceSettingsReload();
                 framework\Context::cacheAllPermissions();
                 if ($issue->isWorkflowTransitionsAvailable()) {
                     // Go through the list of possible transitions for an issue. Only
                     // process transitions that are applicable to issue's workflow.
                     foreach ($issue->getAvailableWorkflowTransitions() as $possible_transition) {
                         if (mb_strtolower($possible_transition->getName()) == mb_strtolower($transition[0])) {
                             $output .= '[VCS ' . $project->getKey() . '] Running transition ' . $transition[0] . ' on issue ' . $issue->getFormattedIssueNo() . "\n";
                             // String representation of parameters. Used for log message.
                             $parameters_string = "";
                             // Iterate over the list of this transition's parameters, and
                             // set them.
                             foreach ($transition[1] as $parameter => $value) {
                                 $parameters_string .= "{$parameter}={$value} ";
                                 switch ($parameter) {
                                     case 'resolution':
                                         if (($resolution = \thebuggenie\core\entities\Resolution::getByKeyish($value)) instanceof \thebuggenie\core\entities\Resolution) {
                                             framework\Context::getRequest()->setParameter('resolution_id', $resolution->getID());
                                         }
                                         break;
                                     case 'status':
                                         if (($status = \thebuggenie\core\entities\Status::getByKeyish($value)) instanceof \thebuggenie\core\entities\Status) {
                                             framework\Context::getRequest()->setParameter('status_id', $status->getID());
                                         }
                                         break;
                                 }
                             }
                             // Run the transition.
                             $possible_transition->transitionIssueToOutgoingStepWithoutRequest($issue);
                             // Log an informative message about the transition.
                             $output .= '[VCS ' . $project->getKey() . '] Ran transition ' . $possible_transition->getName() . ' with parameters \'' . $parameters_string . '\' on issue ' . $issue->getFormattedIssueNo() . "\n";
                         }
                     }
                 }
             }
         }
         $issue->addSystemComment(framework\Context::getI18n()->__('This issue has been updated with the latest changes from the code repository.<source>%commit_msg</source>', array('%commit_msg' => $commit_msg)), $user->getID());
         $output .= '[VCS ' . $project->getKey() . '] Updated issue ' . $issue->getFormattedIssueNo() . "\n";
     }
     // Create file links
     foreach ($files as $afile) {
         // index 0 is action, index 1 is file
         $inst = new File();
         $inst->setAction($afile[0]);
         $inst->setFile($afile[1]);
         $inst->setCommit($commit);
         $inst->save();
         $output .= '[VCS ' . $project->getKey() . '] Added with action ' . $afile[0] . ' file ' . $afile[1] . "\n";
     }
     framework\Event::createNew('vcs_integration', 'new_commit')->trigger(array('commit' => $commit));
     return $output;
 }