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;
 }
Example #2
0
 public function runConfigureRole(framework\Request $request)
 {
     try {
         $role = new entities\Role($request['role_id']);
     } catch (\Exception $e) {
         $this->getResponse()->setHttpStatus(400);
         return $this->renderJSON(array('error' => $this->getI18n()->__('This is not a valid role')));
     }
     if ($role->isSystemRole()) {
         $access_level = $this->getAccessLevel($request['section'], 'core');
     } else {
         $access_level = $this->getUser()->canManageProject($role->getProject()) ? framework\Settings::ACCESS_FULL : framework\Settings::ACCESS_READ;
     }
     switch ($request['mode']) {
         case 'list_permissions':
             return $this->renderComponent('configuration/rolepermissionslist', array('role' => $role));
             break;
         case 'edit':
             if (!$access_level == framework\Settings::ACCESS_FULL) {
                 $this->getResponse()->setHttpStatus(400);
                 return $this->renderJSON(array('error' => $this->getI18n()->__('You do not have access to edit these permissions')));
             }
             if ($request->isPost()) {
                 $role->setName($request['name']);
                 $role->save();
                 $new_permissions = array();
                 foreach ($request['permissions'] ?: array() as $new_permission) {
                     $permission_details = explode(',', $new_permission);
                     $new_permissions[$permission_details[2]] = array('module' => $permission_details[0], 'target_id' => $permission_details[1]);
                 }
                 $existing_permissions = array();
                 foreach ($role->getPermissions() as $existing_permission) {
                     if (!array_key_exists($existing_permission->getPermission(), $new_permissions)) {
                         $role->removePermission($existing_permission);
                     } else {
                         $existing_permissions[$existing_permission->getPermission()] = $new_permissions[$existing_permission->getPermission()];
                         unset($new_permissions[$existing_permission->getPermission()]);
                     }
                 }
                 foreach ($new_permissions as $permission_key => $details) {
                     $p = new entities\RolePermission();
                     $p->setModule($details['module']);
                     $p->setPermission($permission_key);
                     if ($details['target_id']) {
                         $p->setTargetID($details['target_id']);
                     }
                     $role->addPermission($p);
                 }
                 foreach ($existing_permissions as $permission_key => $details) {
                     $p = new entities\RolePermission();
                     $p->setModule($details['module']);
                     $p->setPermission($permission_key);
                     if ($details['target_id']) {
                         $p->setTargetID($details['target_id']);
                     }
                     tables\Permissions::getTable()->addRolePermission($role, $p);
                 }
                 framework\Context::clearPermissionsCache();
                 framework\Context::cacheAllPermissions();
                 return $this->renderJSON(array('message' => $this->getI18n()->__('Permissions updated'), 'permissions_count' => count($request['permissions']), 'role_name' => $role->getName()));
             }
             return $this->renderComponent('configuration/rolepermissionsedit', array('role' => $role));
         case 'delete':
             if (!$access_level == framework\Settings::ACCESS_FULL || !$request->isPost()) {
                 $this->getResponse()->setHttpStatus(400);
                 return $this->renderJSON(array('error' => $this->getI18n()->__('This role cannot be removed')));
             }
             $role->delete();
             return $this->renderJSON(array('message' => $this->getI18n()->__('Role deleted')));
     }
 }