| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000 |
- <?php
- /**
- * The control file of mr module of ZenTaoPMS.
- *
- * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
- * @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
- * @author Yanyi Cao <caoyanyi@easycorp.ltd>
- * @package mr
- * @link https://www.zentao.net
- * @property mrModel $mr
- * @property mrZen $mrZen
- */
- class mr extends control
- {
- /**
- * The gitlab constructor.
- * @param string $moduleName
- * @param string $methodName
- */
- public function __construct($moduleName = '', $methodName = '')
- {
- parent::__construct($moduleName, $methodName);
- /* This is essential when changing tab(menu) from gitlab to repo. */
- /* Optional: common::setMenuVars('devops', $this->session->repoID); */
- if($this->app->getMethodName() != 'browse')
- {
- $this->loadModel('ci')->setMenu();
- $this->view->objectID = 0;
- if(in_array($this->app->tab, array('execution', 'project'))) $this->view->objectID = $this->session->{$this->app->tab};
- if($this->app->tab == 'execution')
- {
- $this->view->executionID = $this->session->execution;
- $this->loadModel('execution')->setMenu((int)$this->session->execution);
- }
- if($this->app->tab == 'project')
- {
- $this->view->projectID = $this->session->project;
- $this->loadModel('project')->setMenu((int)$this->session->project);
- }
- /* Unlock session for wait to get data of repo. */
- if(!in_array(strtolower($this->app->methodName), array('linkbug', 'linkstory', 'linktask'))) session_write_close();
- }
- }
- /**
- * 获取合并请求列表.
- * Browse mr.
- *
- * @param int $repoID
- * @param string $mode
- * @param string $param
- * @param int $objectID
- * @param string $orderBy
- * @param int $recTotal
- * @param int $recPerPage
- * @param int $pageID
- * @access public
- * @return void
- */
- public function browse($repoID = 0, $mode = 'status', $param = 'opened', $objectID = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
- {
- if($this->app->tab == 'execution')
- {
- $this->session->set('execution', $objectID);
- $execution = $this->loadModel('execution')->getByID($objectID);
- if($execution && $execution->type === 'kanban') return $this->locate($this->createLink('execution', 'kanban', "executionID=$objectID"));
- $features = $this->execution->getExecutionFeatures($execution);
- if(!$features['devops']) return $this->locate($this->createLink('execution', 'task', "objectID=$objectID"));
- $this->loadModel('execution')->setMenu($objectID);
- }
- elseif($this->app->tab == 'project')
- {
- $this->session->set('project', $objectID);
- $this->loadModel('project')->setMenu($objectID);
- }
- if(in_array($this->app->tab, array('execution', 'project')) && $objectID) return print($this->fetch('mr', 'browseByExecution', "repoID={$repoID}&mode={$mode}¶m={$param}&objectID={$objectID}&orderBy={$orderBy}&recTotal={$recTotal}&recPerPage={$recPerPage}&pageID={$pageID}"));
- session_write_close();
- $repoList = $this->loadModel('repo')->getListBySCM(implode(',', $this->config->repo->gitServiceTypeList));
- if(empty($repoList)) $this->locate($this->repo->createLink('create'));
- if(!$repoID) $repoID = key($repoList);
- $repoID = $this->repo->saveState($repoID, $objectID);
- if(!isset($repoList[$repoID])) return $this->locate($this->createLink('repo', 'browse', "repoID=$repoID&objectID=$objectID"));
- $repo = $repoList[$repoID];
- $this->loadModel('ci')->setMenu($repo->id);
- if($param == 'assignee' || $param == 'creator')
- {
- $mode = $param;
- $param = $this->app->user->account;
- }
- $this->app->loadClass('pager', true);
- $pager = new pager($recTotal, $recPerPage, $pageID);
- $filterProjects = empty($repo->serviceProject) ? array() : array($repo->serviceHost => $repo->serviceProject);
- $MRList = $this->mr->getList($mode, $param, $orderBy, $filterProjects, $repoID, 0, $pager);
- $projects = $this->mrZen->getAllProjects($repo);
- $this->view->title = $this->lang->mr->common . $this->lang->hyphen . $this->lang->mr->browse;
- $this->view->MRList = $MRList;
- $this->view->projects = $projects;
- $this->view->pager = $pager;
- $this->view->mode = $mode;
- $this->view->param = $param;
- $this->view->objectID = $objectID;
- $this->view->repo = $repo;
- $this->view->orderBy = $orderBy;
- $this->view->openIDList = $this->app->user->admin ? array() : $this->loadModel('pipeline')->getProviderPairsByAccount($repo->SCM);
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->display();
- }
- /**
- * 获取执行下合并请求列表.
- * Browse mr for execution.
- *
- * @param int $repoID
- * @param string $mode
- * @param string $param
- * @param int $projectID
- * @param string $orderBy
- * @param int $recTotal
- * @param int $recPerPage
- * @param int $pageID
- * @access public
- * @return void
- */
- public function browseByExecution($repoID = 0, $mode = 'status', $param = 'opened', $projectID = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
- {
- if($param == 'assignee' || $param == 'creator')
- {
- $mode = $param;
- $param = $this->app->user->account;
- }
- $this->app->loadClass('pager', true);
- $pager = new pager($recTotal, $recPerPage, $pageID);
- $MRList = $this->mr->getList($mode, $param, $orderBy, array(), $repoID, $projectID, $pager);
- $repoList = $this->loadModel('repo')->getList($projectID);
- $repoPairs = array();
- foreach($repoList as $repo)
- {
- if(!in_array($repo->SCM, $this->config->repo->gitServiceTypeList)) continue;
- $repoPairs[$repo->id] = $repo->name;
- if($repoID && $repoID != $repo->id) continue;
- }
- $openIDList = array();
- if(!$this->app->user->admin)
- {
- $this->loadModel('pipeline');
- foreach(array('gitlab', 'gitea', 'gogs') as $service) $openIDList += $this->pipeline->getProviderPairsByAccount($service);
- }
- $objectName = $this->app->tab == 'project' ? 'projectID' : 'executionID';
- $this->view->{$objectName} = $projectID;
- $this->view->title = $this->lang->mr->common . $this->lang->hyphen . $this->lang->mr->browse;
- $this->view->MRList = $MRList;
- $this->view->pager = $pager;
- $this->view->mode = $mode;
- $this->view->repoID = $repoID;
- $this->view->param = $param;
- $this->view->objectID = $projectID;
- $this->view->repoList = $repoList;
- $this->view->repoPairs = $repoPairs;
- $this->view->orderBy = $orderBy;
- $this->view->openIDList = $openIDList;
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->display();
- }
- /**
- * 创建合并请求.
- * Create MR function.
- *
- * @param int $repoID
- * @param int $objectID
- * @access public
- * @return void
- */
- public function create($repoID = 0, $objectID = 0)
- {
- if($_POST)
- {
- $MR = form::data($this->config->mr->form->create)
- ->setIF($this->post->needCI == 0, 'jobID', 0)
- ->add('createdBy', $this->app->user->account)
- ->skipSpecial('title,description')
- ->get();
- $result = $this->mr->create($MR);
- return $this->send($result);
- }
- $repoID = $this->loadModel('repo')->saveState($repoID);
- $repo = $this->repo->getByID($repoID);
- if(!in_array($repo->SCM, $this->config->repo->gitServiceTypeList))
- {
- $repoList = $this->repo->getListBySCM(implode(',', $this->config->repo->gitServiceTypeList));
- $repoID = key($repoList);
- $repoID = $this->loadModel('repo')->saveState($repoID);
- $repo = $repoList[$repoID];
- }
- if(in_array($repo->SCM, $this->config->repo->notSyncSCM)) $repo->serviceProject = (int)$repo->serviceProject;
- $project = $this->loadModel(strtolower($repo->SCM))->apiGetSingleProject($repo->gitService, $repo->serviceProject, false);
- $jobPairs = array();
- $jobs = $this->loadModel('job')->getListByRepoID($repoID);
- foreach($jobs as $job) $jobPairs[$job->id] = "[{$job->id}]{$job->name}";
- $repoPairs = array();
- if(in_array($this->app->tab, array('execution', 'project')) && $objectID)
- {
- $repoList = $this->loadModel('repo')->getList($objectID);
- foreach($repoList as $repoInfo)
- {
- if(in_array($repoInfo->SCM, $this->config->repo->gitServiceTypeList)) $repoPairs[$repoInfo->id] = $repoInfo->name;
- }
- }
- $this->view->title = $this->lang->mr->create;
- $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed');
- $this->view->repo = $repo;
- $this->view->repoPairs = $repoPairs;
- $this->view->project = $project;
- $this->view->executionID = $objectID;
- $this->view->objectID = $objectID;
- $this->view->jobPairs = $jobPairs;
- $this->display();
- }
- /**
- * 编辑合并请求。
- * Edit MR function.
- *
- * @param int $MRID
- * @access public
- * @return void
- */
- public function edit($MRID)
- {
- if($_POST)
- {
- $MR = form::data($this->config->mr->form->edit)
- ->setIF($this->post->needCI == 0, 'jobID', 0)
- ->add('editedBy', $this->app->user->account)
- ->skipSpecial('title,description')
- ->get();
- $result = $this->mr->update($MRID, $MR);
- return $this->send($result);
- }
- $MR = $this->mr->fetchByID($MRID);
- if(isset($MR->hostID)) $rawMR = $this->mr->apiGetSingleMR($MR->repoID, $MR->mriid);
- $this->view->title = $this->lang->mr->edit;
- $this->view->MR = $MR;
- $this->view->rawMR = isset($rawMR) ? $rawMR : false;
- if(!isset($rawMR->id) || empty($rawMR)) return $this->display();
- /* Fetch user list both in Zentao and current GitLab project. */
- $host = $this->loadModel('pipeline')->getByID($MR->hostID);
- $this->view->host = $host;
- $this->mrZen->assignEditData($MR, $host->type);
- }
- /**
- * 删除合并请求。
- * Delete a MR.
- *
- * @param int $MRID
- * @access public
- * @return void
- */
- public function delete($MRID)
- {
- $mr = $this->mr->fetchByID($MRID);
- $this->mr->deleteByID($MRID);
- if(dao::isError()) return $this->sendError(dao::getError());
- return $this->sendSuccess(array('load' => $this->createLink($this->app->rawModule, 'browse', "repoID={$mr->repoID}")));
- }
- /**
- * 合并请求详情。
- * View a MR.
- *
- * @param int $MRID
- * @access public
- * @return void
- */
- public function view($MRID)
- {
- $oldMR = $this->mr->fetchByID($MRID);
- if(!$oldMR) return $this->locate($this->createLink($this->app->rawModule, 'browse'));
- if(isset($oldMR->hostID)) $rawMR = $this->mr->apiGetSingleMR($oldMR->repoID, $oldMR->mriid);
- if($oldMR->synced && (!isset($rawMR->id) || empty($rawMR))) $this->sendError($this->lang->mr->apiError->emptyResponse, true);
- /* Sync MR from GitLab to ZenTaoPMS. */
- $MR = $this->mr->apiSyncMR($oldMR);
- $host = $this->loadModel('pipeline')->getByID($MR->hostID);
- if(in_array($host->type, $this->config->pipeline->formatTypeService))
- {
- $MR->sourceProject = (int)$MR->sourceProject;
- $MR->targetProject = (int)$MR->targetProject;
- }
- $sourceProject = $this->loadModel($host->type)->apiGetSingleProject($MR->hostID, $MR->sourceProject, false);
- $compile = $this->loadModel('compile')->getByID($MR->compileID);
- $this->view->title = $this->lang->mr->view;
- $this->view->MR = $MR;
- $this->view->rawMR = isset($rawMR) ? $rawMR : false;
- $this->view->repo = $this->loadModel('repo')->getByID($MR->repoID);
- $this->view->reviewer = $this->loadModel('user')->getById($MR->assignee);
- $this->view->actions = $this->loadModel('action')->getList($this->app->rawModule, $MRID);
- $this->view->compile = $compile;
- $this->view->hasNewCommit = $compile ? $this->mrZen->checkNewCommit($host->type, $MR->hostID, (string)$MR->targetProject, $MR->mriid, $compile->createdDate) : false;
- $this->view->sourceProject = $sourceProject;
- $this->view->targetProject = $this->{$host->type}->apiGetSingleProject($MR->hostID, $MR->targetProject, false);
- $this->view->sourceBranch = $this->mrZen->getBranchUrl($host, $MR->sourceProject, $MR->sourceBranch);
- $this->view->targetBranch = $this->mrZen->getBranchUrl($host, $MR->targetProject, $MR->targetBranch);
- $this->display();
- }
- /**
- * 定时任务,从GitLab API同步合并请求状态到禅道数据库,默认5分钟执行一次。
- * Crontab sync MR from GitLab API to Zentao database, default time 5 minutes to execute once.
- *
- * @access public
- * @return void
- */
- public function syncMR()
- {
- $MRList = $this->mr->getList();
- $this->mr->batchSyncMR($MRList);
- if(dao::isError())
- {
- echo json_encode(dao::getError());
- return true;
- }
- echo 'success';
- }
- /**
- * 通过合并请求。
- * Accept a MR.
- *
- * @param int $MRID
- * @access public
- * @return void
- */
- public function accept($MRID)
- {
- $MR = $this->mr->fetchByID($MRID);
- /* Judge that if this MR can be accepted. */
- if(isset($MR->needCI) and $MR->needCI == '1')
- {
- $compileStatus = empty($MR->compileID) ? 'fail' : $this->loadModel('compile')->getByID($MR->compileID)->status;
- if(isset($compileStatus) and $compileStatus != 'success')
- {
- return $this->sendError($this->lang->mr->needCI);
- }
- }
- if(isset($MR->needApproved) and $MR->needApproved == '1')
- {
- if($MR->approvalStatus != 'approved')
- {
- return $this->sendError($this->lang->mr->needApproved);
- }
- }
- if(isset($MR->hostID)) $rawMR = $this->mr->apiAcceptMR($MR);
- if(isset($rawMR->state) and $rawMR->state == 'merged')
- {
- $this->mr->logMergedAction($MR);
- return $this->sendSuccess(array('message' => $this->lang->mr->mergeSuccess, 'load' => true));
- }
- /* The type of variable `$rawMR->message` is string. This is different with apiCreateMR. */
- if(isset($rawMR->message))
- {
- $errorMessage = $this->mr->convertApiError($rawMR->message);
- return $this->sendError(sprintf($this->lang->mr->apiError->sudo, $errorMessage));
- }
- return $this->sendError($this->lang->mr->mergeFailed);
- }
- /**
- * 获取合并请求的对比信息。
- * View diff between MR source and target branches.
- *
- * @param int $MRID
- * @access public
- * @return void
- * @param string $encoding
- */
- public function diff($MRID, $encoding = '')
- {
- $encoding = empty($encoding) ? 'utf-8' : $encoding;
- $encoding = strtolower(str_replace('_', '-', $encoding)); /* Revert $config->requestFix in $encoding. */
- $MR = $this->mr->fetchByID($MRID);
- $this->view->title = $this->lang->mr->viewDiff;
- $this->view->MR = $MR;
- $this->view->compile = $this->loadModel('compile')->getById($MR->compileID);
- if($MR->synced)
- {
- $rawMR = $this->mr->apiGetSingleMR($MR->repoID, $MR->mriid);
- $this->view->rawMR = $rawMR;
- if(!isset($rawMR->id) || empty($rawMR)) return $this->display();
- }
- $diffs = $this->mr->getDiffs($MR, $encoding);
- $arrange = $this->cookie->arrange ? $this->cookie->arrange : 'inline';
- if($this->server->request_method == 'POST')
- {
- if($this->post->arrange)
- {
- $arrange = $this->post->arrange;
- helper::setcookie('arrange', $arrange);
- }
- if($this->post->encoding) $encoding = $this->post->encoding;
- }
- $this->view->repo = $this->loadModel('repo')->getByID($MR->repoID);
- $this->view->diffs = $arrange == 'appose' ? $this->repo->getApposeDiff($diffs) : $diffs;
- $this->view->encoding = $encoding;
- $this->view->oldRevision = $MR->targetBranch;
- $this->view->newRevision = $MR->sourceBranch;
- $this->display();
- }
- /**
- * 审核合并请求。
- * Approval for this MR.
- *
- * @param int $MRID
- * @param string $action
- * @return void
- */
- public function approval($MRID, $action = 'approve')
- {
- $MR = $this->mr->fetchByID($MRID);
- if($_POST)
- {
- $comment = $this->post->comment;
- $result = $this->mr->approve($MR, $action, $comment);
- return $this->send($result);
- }
- $showCompileResult = false;
- if(!empty($MR->compileStatus))
- {
- $showCompileResult = true;
- $this->view->compileUrl = $this->createLink('job', 'view', "jobID={$MR->jobID}&compileID={$MR->compileID}");
- }
- $this->view->MR = $MR;
- $this->view->action = $action;
- $this->view->actions = $this->loadModel('action')->getList($this->app->rawModule, $MRID);
- $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed');
- $this->view->showCompileResult = $showCompileResult;
- $this->display();
- }
- /**
- * 关闭合并请求。
- * Close this MR.
- *
- * @param int $MRID
- * @access public
- * @return void
- */
- public function close($MRID)
- {
- $MR = $this->mr->fetchByID($MRID);
- $result = $this->mr->close($MR);
- return $this->send($result);
- }
- /**
- * 重新打开合并请求。
- * Reopen this MR.
- *
- * @param int $MRID
- * @access public
- * @return void
- */
- public function reopen($MRID)
- {
- $MR = $this->mr->fetchByID($MRID);
- return $this->send($this->mr->reopen($MR));
- }
- /**
- * 获取合并请求的关联信息。
- * link MR list.
- *
- * @param int $MRID
- * @param string $type
- * @param string $orderBy
- * @param string $param
- * @param int $recPerPage
- * @param int $pageID
- * @return void
- */
- public function link($MRID, $type = 'story', $orderBy = 'id_desc', $param = '', $recPerPage = 20, $pageID = 1)
- {
- $MR = $this->mr->fetchByID($MRID);
- $product = $this->mr->getMRProduct($MR);
- /* Load pager. */
- $this->app->loadClass('pager', true);
- $storyPager = new pager(0, $recPerPage, $type == 'story' ? $pageID : 1);
- $bugPager = new pager(0, $recPerPage, $type == 'bug' ? $pageID : 1);
- $taskPager = new pager(0, $recPerPage, $type == 'task' ? $pageID : 1);
- $productID = $product ? $product->id : 0;
- $stories = $this->mr->getLinkList($MRID, 'story', $type == 'story' ? $orderBy : '', $storyPager);
- $bugs = $this->mr->getLinkList($MRID, 'bug', $type == 'bug' ? $orderBy : '', $bugPager);
- $tasks = $this->mr->getLinkList($MRID, 'task', $type == 'task' ? $orderBy : '', $taskPager);
- $builds = $this->loadModel('build')->getBuildPairs($productID);
- $this->view->title = $this->lang->mr->common . $this->lang->hyphen . $this->lang->mr->link;
- $this->view->MR = $MR;
- $this->view->repoID = $MR->repoID;
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->view->stories = $stories;
- $this->view->bugs = $bugs;
- $this->view->tasks = $tasks;
- $this->view->product = $product;
- $this->view->storyPager = $storyPager;
- $this->view->bugPager = $bugPager;
- $this->view->taskPager = $taskPager;
- $this->view->type = $type;
- $this->view->builds = $builds;
- $this->view->orderBy = $orderBy;
- $this->view->param = $param;
- $this->display();
- }
- /**
- * 获取合并请求可关联的需求列表。
- * Link story to mr.
- *
- * @param int $MRID
- * @param int $repoID
- * @param string $browseType
- * @param int $param
- * @param string $orderBy
- * @param int $recTotal
- * @param int $recPerPage
- * @param int $pageID
- * @access public
- * @return void
- */
- public function linkStory($MRID, $repoID = 0, $browseType = '', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 10, $pageID = 1)
- {
- if(!empty($_POST['stories']))
- {
- $this->mr->link($MRID, 'story', $this->post->stories);
- if(dao::isError()) return $this->sendError(dao::getError());
- $link = $this->createLink($this->app->rawModule,'link', "MRID=$MRID&type=story&orderBy=$orderBy");
- return $this->sendSuccess(array('load' => $link, 'closeModal' => true));
- }
- $this->loadModel('story');
- /* Load pager. */
- $this->app->loadClass('pager', true);
- $pager = new pager($recTotal, $recPerPage, $pageID);
- /* Build search form. */
- $queryID = ($browseType == 'bySearch') ? (int) $param : 0;
- $this->mrZen->buildLinkStorySearchForm($MRID, $repoID, $orderBy, $queryID);
- $repo = $this->loadModel('repo')->fetchByID($repoID);
- $productID = $repo ? $repo->product : 0;
- $linkedStories = $this->mr->getLinkList($MRID, 'story');
- if($browseType == 'bySearch')
- {
- $this->session->set('repoID', $repoID);
- $allStories = $this->story->getBySearch('all', 0, $queryID, $orderBy, 0, 'story', array_keys($linkedStories), '', $pager);
- }
- else
- {
- $allStories = $this->story->getProductStories($productID, 'all', '0', 'draft,reviewing,active,changing', 'story', $orderBy, true, array_keys($linkedStories), $pager);
- }
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->view->allStories = $allStories;
- $this->view->MRID = $MRID;
- $this->view->browseType = $browseType;
- $this->view->param = $param;
- $this->view->orderBy = $orderBy;
- $this->view->repoID = $repoID;
- $this->view->pager = $pager;
- $this->display();
- }
- /**
- * 获取合并请求可关联的Bug列表。
- * Link bug to mr.
- *
- * @param int $MRID
- * @param int $repoID
- * @param string $browseType
- * @param int $param
- * @param string $orderBy
- * @param int $recTotal
- * @param int $recPerPage
- * @param int $pageID
- * @access public
- * @return void
- */
- public function linkBug($MRID, $repoID = 0, $browseType = '', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 10, $pageID = 1)
- {
- if(!empty($_POST['bugs']))
- {
- $this->mr->link($MRID, 'bug', $this->post->bugs);
- if(dao::isError()) return $this->sendError(dao::getError());
- $link = $this->createLink($this->app->rawModule,'link', "MRID=$MRID&type=bug&orderBy=$orderBy");
- return $this->sendSuccess(array('load' => $link, 'closeModal' => true));
- }
- $this->loadModel('bug');
- $queryID = ($browseType == 'bysearch') ? (int)$param : 0;
- $this->mrZen->buildLinkBugSearchForm($MRID, $repoID, $orderBy, $queryID);
- /* Load pager. */
- $this->app->loadClass('pager', true);
- $pager = new pager($recTotal, $recPerPage, $pageID);
- /* Build search form. */
- $repo = $this->loadModel('repo')->fetchByID($repoID);
- $productIdList = $repo ? explode(',', trim($repo->product, ',')) : 0;
- $linkedBugs = $this->mr->getLinkList($MRID, 'bug');
- if($browseType == 'bySearch')
- {
- $allBugs = $this->bug->getBySearch('bug', $productIdList, 0, 0, 0, $queryID, implode(',', array_keys($linkedBugs)), $orderBy, $pager);
- }
- else
- {
- $allBugs = $this->bug->getActiveBugs($productIdList, 0, '0', array_keys($linkedBugs), $pager, $orderBy);
- }
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->view->allBugs = $allBugs;
- $this->view->MRID = $MRID;
- $this->view->browseType = $browseType;
- $this->view->param = $param;
- $this->view->orderBy = $orderBy;
- $this->view->pager = $pager;
- $this->view->repoID = $repoID;
- $this->display();
- }
- /**
- * 获取合并请求可关联的任务列表。
- * Link task to mr.
- *
- * @param int $MRID
- * @param int $repoID
- * @param string $browseType
- * @param int $param
- * @param string $orderBy
- * @param int $recTotal
- * @param int $recPerPage
- * @param int $pageID
- * @access public
- * @return void
- */
- public function linkTask($MRID, $repoID = 0, $browseType = 'unclosed', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 10, $pageID = 1)
- {
- if(!empty($_POST['tasks']))
- {
- $this->mr->link($MRID, 'task', $this->post->tasks);
- if(dao::isError()) return $this->sendError(dao::getError());
- $link = $this->createLink($this->app->rawModule,'link', "MRID=$MRID&type=task&orderBy=$orderBy");
- return $this->sendSuccess(array('load' => $link, 'closeModal' => true));
- }
- /* Set browse type. */
- $browseType = strtolower($browseType);
- $queryID = ($browseType == 'bysearch') ? (int)$param : 0;
- /* Get executions by product. */
- $this->loadModel('product');
- $executions = array();
- $repo = $this->loadModel('repo')->fetchByID($repoID);
- $productIdList = $repo ? explode(',', trim($repo->product, ',')) : array();
- foreach($productIdList as $productID)
- {
- if(empty($productID)) continue;
- $executions = $executions + $this->product->getExecutionPairsByProduct((int)$productID);
- }
- $this->loadModel('execution');
- $this->mrZen->buildLinkTaskSearchForm($MRID, $repoID, $orderBy, $queryID, $executions);
- $linkedTasks = $this->mr->getLinkList($MRID, 'task');
- /* Get tasks by executions. */
- $allTasks = array();
- if($browseType == 'bysearch')
- {
- $allTasks = $this->execution->getTasks(0, 0, $executions, $browseType, $queryID, 0, $orderBy, null);
- }
- else
- {
- $this->loadModel('task');
- $queryStatus = $this->lang->task->statusList;
- unset($queryStatus['closed']);
- $condition = new stdclass();
- $condition->statusList = array_keys($queryStatus);
- $condition->executionList = array_keys($executions);
- $allTasks = $this->loadModel('task')->getListByCondition($condition);
- }
- /* Filter linked tasks. */
- $linkedTaskIDs = array_keys($linkedTasks);
- foreach($allTasks as $key => $task)
- {
- if(in_array($task->id, $linkedTaskIDs)) unset($allTasks[$key]);
- }
- $this->mrZen->processLinkTaskPager($recTotal, $recPerPage, $pageID, $allTasks);
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->view->MRID = $MRID;
- $this->view->browseType = $browseType;
- $this->view->param = $param;
- $this->view->orderBy = $orderBy;
- $this->view->repoID = $repoID;
- $this->display();
- }
- /**
- * 解除合并请求关联的对象。
- * UnLink an mr link.
- *
- * @param int $MRID
- * @param string $type
- * @param int $linkID
- * @access public
- * @return void
- */
- public function unlink($MRID, $type, $linkID)
- {
- $this->mr->unlink($MRID, $type, $linkID);
- if(dao::isError()) return $this->sendError(dao::getError());
- return $this->sendSuccess(array('message' => '', 'load' => $this->createLink($this->app->rawModule, 'link', "MRID=$MRID&type=$type")));
- }
- /**
- * 查看合并请求的提交记录。
- * Show the commit logs for this Merge Request.
- *
- * @param int $MRID
- * @return void
- */
- public function commitLogs($MRID)
- {
- $MR = $this->mr->fetchByID($MRID);
- $compile = $this->loadModel('compile')->getById($MR->compileID);
- $this->view->title = $this->lang->mr->commitLogs;
- $this->view->MR = $MR;
- $this->view->compile = $compile;
- if($MR->synced)
- {
- $rawMR = $this->mr->apiGetSingleMR($MR->repoID, $MR->mriid);
- $this->view->rawMR = $rawMR;
- if(!isset($rawMR->id) || empty($rawMR)) return $this->display();
- }
- $repo = $this->loadModel('repo')->getByID($MR->repoID);
- $commitLogs = $this->mr->apiGetMRCommits($MR->hostID, $MR->targetProject, $MR->mriid);
- foreach($commitLogs as $commitLog)
- {
- $commitLog->repoID = $MR->repoID;
- if(in_array(strtolower($repo->SCM), array('gitea', 'gogs')))
- {
- $commitLog->id = $commitLog->sha;
- $commitLog->committed_date = $commitLog->author->committer->date;
- $commitLog->committer_name = $commitLog->author->committer->name;
- $commitLog->committer_email = $commitLog->author->committer->email;
- $commitLog->title = $commitLog->commit->message;
- }
- $commitLog->id = substr($commitLog->id, 0, 10);
- }
- $this->view->commitLogs = $commitLogs;
- $this->view->repo = $repo;
- $this->display();
- }
- /**
- * 获取构建列表。
- * AJAX: Get job list.
- *
- * @param int $repoID
- * @return void
- */
- public function ajaxGetJobList($repoID)
- {
- $jobList = $this->loadModel('job')->getListByRepoID($repoID);
- if(!$jobList) return $this->send(array('message' => array()));
- $options = "<option value=''></option>";
- foreach($jobList as $job) $options .= "<option value='{$job->id}' data-name='{$job->name}'>[{$job->id}] {$job->name}</option>";
- $this->send($options);
- }
- /**
- * 检查是否有相同的合并请求。
- * Ajax check same opened mr for source branch.
- *
- * @param int $hostID
- * @access public
- * @return void
- */
- public function ajaxCheckSameOpened($hostID)
- {
- $sourceProject = $this->post->sourceProject;
- $sourceBranch = $this->post->sourceBranch;
- $targetProject = $this->post->targetProject;
- $targetBranch = $this->post->targetBranch;
- $result = $this->mr->checkSameOpened($hostID, (string)$sourceProject, $sourceBranch, (string)$targetProject, $targetBranch);
- echo json_encode($result);
- }
- /**
- * 获取分支权限。
- * Ajax get branch privileges.
- *
- * @param int $hostID
- * @param string $project
- * @access public
- * @return void
- */
- public function ajaxGetBranchPrivs($hostID, $project)
- {
- $host = $this->loadModel('pipeline')->getByID($hostID);
- if(in_array($host->type, array('gitea', 'gogs')))
- {
- $project = urldecode(base64_decode($project));
- }
- else
- {
- $project = (int)$project;
- }
- $branchPrivs = array();
- $branches = $this->loadModel($host->type)->apiGetBranchPrivs($hostID, $project);
- foreach($branches as $branch) $branchPrivs[$branch->name] = $branch->name;
- echo json_encode($branchPrivs);
- }
- /**
- * 从代码托管服务器同步合并请求到禅道。
- * AJAX: sync Merge Requests from API server.
- *
- * @param int $repoID
- * @return void
- */
- public function ajaxSyncMRs($repoID)
- {
- if(!$repoID) $this->sendSuccess();
- $repo = $this->loadModel('repo')->getByID($repoID);
- if($repo && in_array($repo->SCM, $this->config->repo->notSyncSCM)) $repo->serviceProject = (int)$repo->serviceProject;
- $rawMRs = $this->loadModel(strtolower($repo->SCM))->apiGetMergeRequests($repo->gitService, $repo->serviceProject);
- if(empty($rawMRs)) $this->sendSuccess();
- $MRs = $this->dao->select('`id`,`sourceProject`,`sourceBranch`,`targetProject`,`targetBranch`,`mriid`')->from(TABLE_MR)->where('repoID')->eq($repoID)->fetchAll();
- $existedMRs = array();
- $needSyncMRs = $rawMRs;
- foreach($rawMRs as $index => $rawMR)
- {
- if($rawMR->state == 'merged' || $rawMR->source_project_id != $rawMR->target_project_id)
- {
- unset($needSyncMRs[$index]);
- continue;
- }
- foreach($MRs as $MR)
- {
- if($MR->mriid == $rawMR->iid
- && $MR->sourceProject == $rawMR->source_project_id && $MR->sourceBranch == $rawMR->source_branch
- && $MR->targetProject == $rawMR->target_project_id && $MR->targetBranch == $rawMR->target_branch)
- {
- $existedMRs[$MR->id] = $needSyncMRs[$index];
- unset($needSyncMRs[$index]);
- }
- }
- }
- $this->mrZen->saveMrData($repo, $needSyncMRs);
- foreach($existedMRs as $mrID => $existedMR)
- {
- $MR = $this->mr->fetchByID($mrID);
- $status = $existedMR->state ?: '';
- $mergeStatus = $existedMR->merge_status ?: '';
- if($MR->title != $existedMR->title || $MR->status != $status || $MR->mergeStatus != $mergeStatus)
- {
- $newMR = new stdclass();
- $newMR->title = $existedMR->title;
- $newMR->status = $status;
- $newMR->isFlow = empty($existedMR->flow) ? 0 : 1;
- $newMR->mergeStatus = $mergeStatus;
- $this->dao->update(TABLE_MR)->data($newMR)->where('id')->eq($mrID)->exec();
- if(!dao::isError()) $this->loadModel('action')->create(empty($existedMR->flow) ? 'mr' : 'pullreq', $mrID, 'synced', '', '', 'system');
- }
- }
- $this->sendSuccess();
- }
- /**
- * 执行合并请求的构建。
- * AJAX exec MR job.
- *
- * @param int $MRID
- * @param int $jobID
- * @access public
- * @return void
- */
- public function ajaxExecJob($MRID, $jobID)
- {
- $this->mr->execJob($MRID, $jobID);
- return $this->sendSuccess(array('load' => true));
- }
- /**
- * 获取合并请求关联的对象。
- * AJAX get MR linked objects.
- *
- * @param int $MRID
- * @access public
- * @return void
- */
- public function ajaxLinkObjects($MRID)
- {
- $mr = $this->mr->fetchByID($MRID);
- if(!$mr) return false;
- return $this->mr->linkObjects($mr);
- }
- /**
- * 同步流水线的构建状态。
- * AJAX sync compile status.
- *
- * @param int $compileID
- * @access public
- * @return void
- */
- public function ajaxSyncCompile($compileID)
- {
- $this->loadModel('ci')->checkCompileStatus($compileID);
- return $this->sendSuccess(array('message' => $this->lang->mr->refreshSuccess, 'load' => true));
- }
- }
|