Merge branch 'devops24'

This commit is contained in:
liyuchun
2022-03-22 08:28:32 +08:00
50 changed files with 339 additions and 184 deletions
+2
View File
@@ -54,3 +54,5 @@ INSERT INTO `zt_config` (`vision`,`owner`, `module`, `section`, `key`, `value`)
INSERT INTO `zt_config` (`vision`,`owner`, `module`, `section`, `key`, `value`) VALUES ('lite','system', 'project', '', 'defaultCurrency', 'CNY');
ALTER TABLE `zt_apistruct` CHANGE `desc` `desc` text COLLATE 'utf8_general_ci' NOT NULL DEFAULT '' AFTER `type`;
ALTER TABLE `zt_mr` ADD `squash` ENUM('0','1') NOT NULL DEFAULT '0' AFTER `removeSourceBranch`;
+1
View File
@@ -875,6 +875,7 @@ CREATE TABLE IF NOT EXISTS `zt_mr` (
`compileID` mediumint(8) unsigned NOT NULL,
`compileStatus` char(30) NOT NULL,
`removeSourceBranch` enum('0','1') NOT NULL DEFAULT '0',
`squash` enum('0','1') NOT NULL DEFAULT '0',
`synced` enum('0','1') COLLATE 'utf8_general_ci' NOT NULL DEFAULT '1',
`syncError` varchar(255) NOT NULL,
`hasNoConflict` enum('0','1') COLLATE 'utf8_general_ci' NOT NULL DEFAULT '0',
+1 -1
View File
@@ -157,7 +157,7 @@ class baseValidater
*/
public static function checkMobile($var)
{
return preg_match("/^1[3-5,7,8]{1}[0-9]{9}$/", $var) ? true : false;
return preg_match("/^1[3-9]{1}[0-9]{9}$/", $var) ? true : false;
}
/**
+1
View File
@@ -41,6 +41,7 @@ $config->action->objectNameFields['kanbanregion'] = 'name';
$config->action->objectNameFields['kanban'] = 'name';
$config->action->objectNameFields['kanbancard'] = 'name';
$config->action->objectNameFields['sonarqube'] = 'name';
$config->action->objectNameFields['gitlab'] = 'name';
$config->action->commonImgSize = 870;
+5 -2
View File
@@ -117,8 +117,8 @@ $lang->action->objectTypes['entry'] = 'Entry';
$lang->action->objectTypes['webhook'] = 'Webhook';
$lang->action->objectTypes['team'] = 'Team';
$lang->action->objectTypes['whitelist'] = 'Whitelist';
$lang->action->objectTypes['pipeline'] = 'GitLab';
$lang->action->objectTypes['gitlab'] = 'GitLab';
$lang->action->objectTypes['pipeline'] = 'GitLab Server';
$lang->action->objectTypes['gitlab'] = 'GitLab Server';
$lang->action->objectTypes['jenkins'] = 'Jenkins';
$lang->action->objectTypes['mr'] = 'Merge Request';
$lang->action->objectTypes['gitlabproject'] = 'GitLab Project';
@@ -344,6 +344,8 @@ $lang->action->label->importedrelease = 'imported';
$lang->action->label->importedexecution = 'imported';
$lang->action->label->importedbuild = 'imported';
$lang->action->label->fromsonarqube = 'created a bug from SonarQube Issue named:';
$lang->action->label->bind = 'bound';
$lang->action->label->unbind = 'unbound';
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass;
@@ -642,6 +644,7 @@ $lang->action->label->kanbancolumn = 'Kanban Column|execution|kanban|execution=%
$lang->action->label->kanbanlane = 'Kanban Lane|execution|kanban|execution=%s&type=all';
$lang->action->label->kanbancard = 'Kanban Card|kanban|view|kanbanID=%s';
$lang->action->label->mr = 'Merge Request|mr|view|id=%s';
$lang->action->label->gitlab = 'GitLab Server|gitlab|view|id=%s';
/* Object type. */
$lang->action->search = new stdclass();
+5 -2
View File
@@ -117,8 +117,8 @@ $lang->action->objectTypes['entry'] = '应用';
$lang->action->objectTypes['webhook'] = 'Webhook';
$lang->action->objectTypes['team'] = '团队';
$lang->action->objectTypes['whitelist'] = '白名单';
$lang->action->objectTypes['pipeline'] = 'GitLab';
$lang->action->objectTypes['gitlab'] = 'GitLab';
$lang->action->objectTypes['pipeline'] = 'GitLab服务器';
$lang->action->objectTypes['gitlab'] = 'GitLab服务器';
$lang->action->objectTypes['jenkins'] = 'Jenkins';
$lang->action->objectTypes['mr'] = '合并请求';
$lang->action->objectTypes['gitlabproject'] = 'GitLab项目';
@@ -344,6 +344,8 @@ $lang->action->label->importedrelease = '导入了';
$lang->action->label->importedexecution = '导入了';
$lang->action->label->importedbuild = '导入了';
$lang->action->label->fromsonarqube = '由SonarQube问题创建';
$lang->action->label->bind = '绑定了';
$lang->action->label->unbind = '取消绑定了';
/* 动态信息按照对象分组 */
$lang->action->dynamicAction = new stdclass();
@@ -642,6 +644,7 @@ $lang->action->label->kanbancolumn = '看板列|execution|kanban|execution=%s';
$lang->action->label->kanbanlane = '看板泳道|execution|kanban|execution=%s&type=all';
$lang->action->label->kanbancard = '看板卡片|kanban|view|kanbanID=%s';
$lang->action->label->mr = '合并请求|mr|view|id=%s';
$lang->action->label->gitlab = 'GitLab服务器|gitlab|view|id=%s';
/* Object type. */
$lang->action->search = new stdclass();
+4 -1
View File
@@ -1098,7 +1098,7 @@ class actionModel extends model
if($actionType == 'svncommited' or $actionType == 'gitcommited') $action->actor = zget($commiters, $action->actor);
/* Get gitlab objectname. */
if(substr($objectType, 0,6) == 'gitlab') $action->objectName = $action->extra;
if(empty($action->objectName) and substr($objectType, 0, 6) == 'gitlab') $action->objectName = $action->extra;
/* Other actions, create a link. */
if(!$this->setObjectLink($action, $deptUsers))
@@ -1107,6 +1107,9 @@ class actionModel extends model
continue;
}
/* Set merge request link. */
if(empty($action->objectName) and $action->objectType == 'mr') $action->objectLink = '';
$action->major = (isset($this->config->action->majorList[$action->objectType]) && in_array($action->action, $this->config->action->majorList[$action->objectType])) ? 1 : 0;
}
return $actions;
+2 -1
View File
@@ -336,7 +336,8 @@ class backup extends control
if($statusFile)
{
$this->app->loadLang('extension');
$this->view->error = sprintf($this->lang->extension->noticeOkFile, str_replace(dirname($this->app->getBasePath()) . DS, '', $statusFile));
$statusFile = str_replace(dirname($this->app->getBasePath()) . DS, '', $statusFile);
$this->view->error = sprintf($this->lang->extension->noticeOkFile, $statusFile, $statusFile);
return print($this->display());
}
+2 -2
View File
@@ -612,9 +612,9 @@ class bug extends control
$this->view->productName = isset($this->products[$productID]) ? $this->products[$productID] : '';
$this->view->moduleOptionMenu = $moduleOptionMenu;
$this->view->stories = $stories;
$this->view->projects = $projects;
$this->view->projects = defined('TUTORIAL') ? $this->loadModel('tutorial')->getProject() : $projects;
$this->view->project = $project;
$this->view->executions = $executions;
$this->view->executions = defined('TUTORIAL') ? $this->loadModel('tutorial')->getExecutionPairs() : $executions;
$this->view->builds = $builds;
$this->view->moduleID = (int)$moduleID;
$this->view->projectID = $projectID;
+81 -81
View File
@@ -15,14 +15,14 @@ class convertModel extends model
{
/**
* Connect to db.
*
*
* @access public
* @return void
*/
public function connectDB($dbName = '')
{
$dsn = "mysql:host={$this->config->db->host}; port={$this->config->db->port};dbname={$dbName}";
try
try
{
$dbh = new PDO($dsn, $this->config->db->user, $this->config->db->password);
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
@@ -36,10 +36,10 @@ class convertModel extends model
return $exception->getMessage();
}
}
/**
* Check database exits or not.
*
*
* @access public
* @return bool
*/
@@ -51,7 +51,7 @@ class convertModel extends model
/**
* Check table exits or not.
*
*
* @param string $table
* @access public
* @return bool
@@ -79,7 +79,7 @@ class convertModel extends model
/**
* Save the max id of every table. Thus when we convert again, when can delete id larger then the saved max id.
*
*
* @access public
* @return void
*/
@@ -112,8 +112,8 @@ class convertModel extends model
/**
* Get jira data from db.
*
* @param string $module
*
* @param string $module
* @param int $lastID
* @param int $limit
* @access public
@@ -185,10 +185,10 @@ class convertModel extends model
/**
* Get jira data from file.
*
* @param sting $module
* @param int $lastID
* @param int $limit
*
* @param sting $module
* @param int $lastID
* @param int $limit
* @access public
* @return void
*/
@@ -203,7 +203,7 @@ class convertModel extends model
$xmlContent = file_get_contents($filePath);
$xmlContent = preg_replace ('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $xmlContent);
$parsedXML = simplexml_load_string($xmlContent, SimpleXMLElement::class, LIBXML_NOCDATA);
$parsedXML = simplexml_load_string($xmlContent, 'SimpleXMLElement', LIBXML_NOCDATA);
$dataList = array();
$parsedXML = $this->object2Array($parsedXML);
@@ -234,7 +234,7 @@ class convertModel extends model
}
}
if($limit)
if($limit)
{
$dataList = array_slice($dataList, $lastID, $limit, true);
if(empty($dataList)) return array();
@@ -297,7 +297,7 @@ class convertModel extends model
{
$issueLink = new stdclass();
$issueLink->LINKTYPE = $data['linktype'];
$issueLink->SOURCE = $data['source'];
$issueLink->SOURCE = $data['source'];
$issueLink->DESTINATION = $data['destination'];
$dataList[$key] = $issueLink;
@@ -332,7 +332,7 @@ class convertModel extends model
/**
* Get version group from jira file.
*
*
* @access public
* @return void
*/
@@ -340,7 +340,7 @@ class convertModel extends model
{
$xmlContent = file_get_contents($this->app->getTmpRoot() . 'jirafile/nodeassociation.xml');
$xmlContent = preg_replace ('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $xmlContent);
$parsedXML = simplexml_load_string($xmlContent, SimpleXMLElement::class, LIBXML_NOCDATA);
$parsedXML = simplexml_load_string($xmlContent, 'SimpleXMLElement', LIBXML_NOCDATA);
$dataList = array();
$parsedXML = $this->object2Array($parsedXML);
@@ -364,8 +364,8 @@ class convertModel extends model
/**
* Convert object to array.
*
* @param object $parsedXML
*
* @param object $parsedXML
* @access public
* @return void
*/
@@ -386,9 +386,9 @@ class convertModel extends model
/**
* Import jira from db.
*
* @param string $type
* @param int $lastID
*
* @param string $type
* @param int $lastID
* @access public
* @return void
*/
@@ -435,9 +435,9 @@ class convertModel extends model
/**
* Import jira from file.
*
* @param string $type
* @param int $lastID
*
* @param string $type
* @param int $lastID
* @param bool $createTable
* @access public
* @return void
@@ -484,8 +484,8 @@ class convertModel extends model
/**
* Import jira user.
*
* @param object $dataList
*
* @param object $dataList
* @param string $method
* @access public
* @return void
@@ -512,7 +512,7 @@ class convertModel extends model
$this->dao->dbh($this->dbh)->replace(TABLE_USER)->data($user, 'group')->exec();
if(!dao::isError())
{
{
$data = new stdclass();
$data->account = $user->account;
$data->group = $user->group;
@@ -524,8 +524,8 @@ class convertModel extends model
/**
* Import jira project.
*
* @param object $dataList
*
* @param object $dataList
* @param string $method
* @access public
* @return void
@@ -654,16 +654,16 @@ class convertModel extends model
$this->dao->dbh($this->dbh)->replace(TABLE_PROJECTPRODUCT)->set('project')->eq($projectID)->set('product')->eq($productID)->exec();
$this->dao->dbh($this->dbh)->replace(TABLE_PROJECTPRODUCT)->set('project')->eq($executionID)->set('product')->eq($productID)->exec();
$projectRelation['AType'] = 'jproject';
$projectRelation['BType'] = 'zproject';
$projectRelation['AID'] = $id;
$projectRelation['BID'] = $projectID;
$projectRelation['AType'] = 'jproject';
$projectRelation['BType'] = 'zproject';
$projectRelation['AID'] = $id;
$projectRelation['BID'] = $projectID;
$this->dao->dbh($this->dbh)->insert(JIRA_TMPRELATION)->data($projectRelation)->exec();
$executionRelation['AType'] = 'jproject';
$executionRelation['BType'] = 'zexecution';
$executionRelation['AID'] = $id;
$executionRelation['BID'] = $executionID;
$executionRelation['AType'] = 'jproject';
$executionRelation['BType'] = 'zexecution';
$executionRelation['AID'] = $id;
$executionRelation['BID'] = $executionID;
$this->dao->dbh($this->dbh)->insert(JIRA_TMPRELATION)->data($executionRelation)->exec();
$keyRelation['AType'] = 'joldkey';
@@ -677,8 +677,8 @@ class convertModel extends model
/**
* Import jira issue.
*
* @param object $dataList
*
* @param object $dataList
* @param string $method
* @access public
* @return void
@@ -728,7 +728,7 @@ class convertModel extends model
$issueType = isset($issueTypeList[$data->issuetype]) ? $issueTypeList[$data->issuetype] : 'task';
$issueID = $data->ID;
$issueProject = $data->PROJECT;
if(!isset($projectRelation[$issueProject])) continue;
$projectID = $projectRelation[$issueProject];
@@ -854,7 +854,7 @@ class convertModel extends model
$bug->pri = $data->PRIORITY;
$bug->status = $this->convertStatus('bug', $data->issuestatus);
$bug->steps = $data->DESCRIPTION;
$bug->openedBy = $this->getJiraAccount($data->CREATOR, $method);
$bug->openedBy = $this->getJiraAccount($data->CREATOR, $method);
$bug->openedDate = substr($data->CREATED, 0, 19);
$bug->openedBuild = 'trunk';
$bug->assignedTo = $this->getJiraAccount($data->ASSIGNEE, $method);
@@ -905,8 +905,8 @@ class convertModel extends model
/**
* Import jira build.
*
* @param object $dataList
*
* @param object $dataList
* @param string $method
* @access public
* @return void
@@ -995,8 +995,8 @@ class convertModel extends model
/**
* Import jira issue link.
*
* @param object $dataList
*
* @param object $dataList
* @param string $method
* @access public
* @return void
@@ -1043,7 +1043,7 @@ class convertModel extends model
if(!isset($issueStories[$source])) continue;
$parentID = $issueStories[$source];
$this->dao->dbh($this->dbh)->update(TABLE_STORY)->set('parent')->eq('-1')->where('id')->eq($parentID)->exec();
foreach($dest as $childID)
foreach($dest as $childID)
{
if(!isset($issueStories[$childID])) continue;
$this->dao->dbh($this->dbh)->update(TABLE_STORY)->set('parent')->eq($parentID)->where('id')->eq($issueStories[$childID])->exec();
@@ -1055,7 +1055,7 @@ class convertModel extends model
if(!isset($issueTasks[$source])) continue;
$parentID = $issueTasks[$source];
$this->dao->dbh($this->dbh)->update(TABLE_TASK)->set('parent')->eq('-1')->where('id')->eq($parentID)->exec();
foreach($dest as $childID)
foreach($dest as $childID)
{
if(!isset($issueTasks[$childID])) continue;
$this->dao->dbh($this->dbh)->update(TABLE_TASK)->set('parent')->eq($parentID)->where('id')->eq($issueTasks[$childID])->exec();
@@ -1071,12 +1071,12 @@ class convertModel extends model
if(!isset($relation[$objectType][$source]) or !isset($relation[$objectType][$dest])) continue;
if($objectType == 'story')
if($objectType == 'story')
{
if(empty($issueStories[$dest]) or empty($issueStories[$source])) continue;
$this->dao->dbh($this->dbh)->update(TABLE_STORY)->set('duplicateStory')->eq($$issueStories[$dest])->where('id')->eq($issueStories[$source])->exec();
}
elseif($objectType == 'bug')
elseif($objectType == 'bug')
{
if(empty($issueBugs[$dest]) or empty($issueBugs[$source])) continue;
$this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('duplicateBug')->eq($issueBugs[$dest])->where('id')->eq($issueBugs[$source])->exec();
@@ -1090,15 +1090,15 @@ class convertModel extends model
$sourceObjectType = $issueObjectType[$source];
$destObjectType = $issueObjectType[$dest];
if($sourceObjectType == 'task' and $destObjectType == 'story')
if($sourceObjectType == 'task' and $destObjectType == 'story')
{
$this->dao->dbh($this->dbh)->update(TABLE_TASK)->set('story')->eq($issueStories[$dest])->where('id')->eq($issueTasks[$source])->exec();
}
elseif($sourceObjectType == 'story' and $destObjectType == 'task')
elseif($sourceObjectType == 'story' and $destObjectType == 'task')
{
$this->dao->dbh($this->dbh)->update(TABLE_TASK)->set('story')->eq($issueStories[$source])->where('id')->eq($issueTasks[$dest])->exec();
}
elseif($sourceObjectType == 'story' and $destObjectType == 'bug')
elseif($sourceObjectType == 'story' and $destObjectType == 'bug')
{
$this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('story')->eq($issueStories[$source])->set('storyVersion')->eq(1)->where('id')->eq($issueBugs[$dest])->exec();
}
@@ -1106,7 +1106,7 @@ class convertModel extends model
{
$this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('story')->eq($issueStories[$dest])->set('storyVersion')->eq(1)->where('id')->eq($issueBugs[$source])->exec();
}
elseif($sourceObjectType == 'story' and $destObjectType == 'story')
elseif($sourceObjectType == 'story' and $destObjectType == 'story')
{
$this->dao->dbh($this->dbh)->update(TABLE_STORY)->set("linkStories=concat(linkStories, ',{$issueStories[$dest]}')")->where('id')->eq($issueStories[$source])->exec();
}
@@ -1119,8 +1119,8 @@ class convertModel extends model
/**
* Import jira action.
*
* @param object $dataList
*
* @param object $dataList
* @param string $method
* @access public
* @return void
@@ -1186,8 +1186,8 @@ class convertModel extends model
/**
* Import jira file.
*
* @param object $dataList
*
* @param object $dataList
* @param string $method
* @access public
* @return void
@@ -1256,9 +1256,9 @@ class convertModel extends model
/**
* Convert jira status.
*
* @param string $objectType
* @param string $jiraStatus
*
* @param string $objectType
* @param string $jiraStatus
* @access public
* @return void
*/
@@ -1279,8 +1279,8 @@ class convertModel extends model
/**
* Convert stage.
*
* @param string $jiraStatus
*
* @param string $jiraStatus
* @access public
* @return void
*/
@@ -1299,8 +1299,8 @@ class convertModel extends model
/**
* Get jira account.
*
* @param string $userKey
*
* @param string $userKey
* @param string $method
* @access public
* @return void
@@ -1311,7 +1311,7 @@ class convertModel extends model
if($method == 'db')
{
return $this->dao->dbh($this->sourceDBH)->select('lower_user_name')->from(JIRA_USER)->where('user_key')->eq($userKey)->fetch('lower_user_name');
return $this->dao->dbh($this->sourceDBH)->select('lower_user_name')->from(JIRA_USER)->where('user_key')->eq($userKey)->fetch('lower_user_name');
}
else
{
@@ -1322,7 +1322,7 @@ class convertModel extends model
/**
* Get jira app user pairs.
*
*
* @access public
* @return void
*/
@@ -1330,7 +1330,7 @@ class convertModel extends model
{
$xmlContent = file_get_contents($this->app->getTmpRoot() . 'jirafile/applicationuser.xml');
$xmlContent = preg_replace ('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $xmlContent);
$parsedXML = simplexml_load_string($xmlContent, SimpleXMLElement::class, LIBXML_NOCDATA);
$parsedXML = simplexml_load_string($xmlContent, 'SimpleXMLElement', LIBXML_NOCDATA);
$pairs = array();
$parsedXML = $this->object2Array($parsedXML);
@@ -1360,7 +1360,7 @@ class convertModel extends model
/**
* Split jira file.
*
*
* @access public
* @return void
*/
@@ -1389,11 +1389,11 @@ class convertModel extends model
{
$end = $footerList[$object];
while(true)
{
{
$followItemStr = fgets($handle);
$itemStr .= $followItemStr;
if(strpos($itemStr, $end) !== false) break;
}
}
}
$object = str_replace('<', '', $object);
@@ -1417,7 +1417,7 @@ class convertModel extends model
/**
* Create tmp table for import jira.
*
*
* @access public
* @return void
*/
@@ -1436,17 +1436,17 @@ CREATE TABLE `jiratmprelation`(
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
EOT;
try
{
try
{
$this->dbh->exec($sql);
}
}
catch(Exception $e){}
}
/**
* After exec.
*
* @param string $method
*
* @param string $method
* @access public
* @return void
*/
@@ -1456,8 +1456,8 @@ EOT;
$minDate = date('Y-m-d', time() - 30 * 24 * 3600);
$executionProject = $this->dao->dbh($this->dbh)->select('id,project')->from(TABLE_PROJECT)->where('type')->eq('sprint')->andWhere('project')->ne(0)->fetchPairs();
$minOpenedDatePairs = $this->dao->dbh($this->dbh)->select('execution,min(openedDate) as minOpenedDate')->from(TABLE_TASK)->where('execution')->in(array_keys($executionProject))->fetchPairs('execution', 'minOpenedDate');
foreach($executionProject as $executionID => $projectID)
foreach($executionProject as $executionID => $projectID)
{
$minOpenedDate = isset($minOpenedDatePairs[$executionID]) ? $minOpenedDatePairs[$executionID] : $minDate;
$minOpenedDate = substr($minOpenedDate, 0, 11);
@@ -1466,13 +1466,13 @@ EOT;
}
if($method == 'file') $this->deleteJiraFile();
$this->dbh->exec("DROP TABLE" . JIRA_TMPRELATION);
}
/**
* Delete jira backip file.
*
*
* @access public
* @return void
*/
+2 -2
View File
@@ -2786,7 +2786,7 @@ class execution extends control
$this->loadModel('branch');
foreach($products as $product)
{
$productModules = $this->tree->getOptionMenu($product->id, 'story', 0, array_keys($branches[$product->id]));
$productModules = $this->tree->getOptionMenu($product->id, 'story', 0, defined('TUTORIAL') ? array(0 => 0) : array_keys($branches[$product->id]));
foreach($productModules as $branch => $branchModules)
{
foreach($branchModules as $moduleID => $moduleName) $modules[$moduleID] = ((count($products) >= 2 and $moduleID != 0) ? $product->name : '') . $moduleName;
@@ -2825,7 +2825,7 @@ class execution extends control
{
$storyModule = $this->tree->getModulesName($story->module);
$productName = count($products) > 1 ? $products[$story->product]->name : '';
$modules[$story->module] = $productName . $storyModule[$story->module];
$modules[$story->module] = $productName . zget($storyModule, $story->module, '');
}
}
+4 -3
View File
@@ -29,7 +29,8 @@ class extension extends control
$this->view->title = $this->lang->extension->browse;
$this->view->position[] = $this->lang->extension->browse;
$this->view->error = sprintf($this->lang->extension->noticeOkFile, str_replace('\\', '/', $statusFile));
$statusFile = str_replace('\\', '/', $statusFile);
$this->view->error = sprintf($this->lang->extension->noticeOkFile, $statusFile, $statusFile);
$this->display('extension', 'safe');
helper::end();
}
@@ -148,7 +149,7 @@ class extension extends control
$statusFile = $this->loadModel('common')->checkSafeFile();
if($statusFile)
{
$this->view->error = sprintf($this->lang->extension->noticeOkFile, $statusFile);
$this->view->error = sprintf($this->lang->extension->noticeOkFile, $statusFile, $statusFile);
return $this->display();
}
/* Get the package file name. */
@@ -421,7 +422,7 @@ class extension extends control
$statusFile = $this->loadModel('common')->checkSafeFile();
if($statusFile)
{
$this->view->error = sprintf($this->lang->extension->noticeOkFile, $statusFile);
$this->view->error = sprintf($this->lang->extension->noticeOkFile, $statusFile, $statusFile);
return $this->display();
}
+3 -2
View File
@@ -92,13 +92,14 @@ $lang->extension->viewInstalled = 'Installed Extensions';
$lang->extension->viewAvailable = 'Available Extensions';
$lang->extension->viewDeactivated = 'Deactivated Extensions';
$lang->extension->backDBFile = 'This extension data has been backed up to %s!';
$lang->extension->noticeOkFile = '<h5>For security reasons, your Admin account has to be confirmed.</h5>
$lang->extension->noticeOkFile = "<h5>For security reasons, your Admin account has to be confirmed.</h5>
<h5>Plese login your ZenTao server and create %s.</h5>
<p>Execute command: echo '' > %s</p>
<p>Note</p>
<ol>
<li>The file you will create is empty.</li>
<li>If such file exists, delete it first, and then create one.</li>
</ol>';
</ol>";
$lang->extension->upgradeExt = 'Upgrade';
$lang->extension->installExt = 'Install';
+3 -2
View File
@@ -92,13 +92,14 @@ $lang->extension->viewInstalled = '查看已安装插件';
$lang->extension->viewAvailable = '查看可安装插件';
$lang->extension->viewDeactivated = '查看已禁用插件';
$lang->extension->backDBFile = '插件相关数据已经备份到 %s 文件中!';
$lang->extension->noticeOkFile = '<h5>为了安全起见,系统需要确认您的管理员身份</h5>
$lang->extension->noticeOkFile = "<h5>为了安全起见,系统需要确认您的管理员身份</h5>
<h5>请登录禅道所在的服务器,创建%s文件。</h5>
<p>可以执行命令:echo '' > %s</p>
<p>注意:</p>
<ol>
<li>文件内容为空。</li>
<li>如果之前文件存在,删除之后重新创建。</li>
</ol>';
</ol>";
$lang->extension->upgradeExt = '升级';
$lang->extension->installExt = '安装';
+2 -1
View File
@@ -452,7 +452,8 @@ class extensionModel extends model
}
else
{
if(!@mkdir($path, 0755, true))
$parentDir = mb_substr($path, 0, strripos($path, '/'));
if(!is_writable($parentDir) or !@mkdir($path, 0777, true))
{
$return->errors .= sprintf($this->lang->extension->errorTargetPathNotExists, $path) . '<br />';
$return->mkdirCommands .= "mkdir -p $path<br />";
+9 -1
View File
@@ -128,6 +128,14 @@ class gitModel extends model
$branches = $this->repo->getBranches($repo);
$commits = $repo->commits;
$gitlabAccountPairs = array();
if($repo->SCM == 'Gitlab')
{
$gitlabUserList = $this->loadModel('gitlab')->apiGetUsers($repo->gitlab);
$acountIDPairs = $this->gitlab->getUserIdAccountPairs($repo->gitlab);
foreach($gitlabUserList as $gitlabUser) $gitlabAccountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, $gitlabUser->realname);
}
/* Update code commit history. */
foreach($branches as $branch)
{
@@ -166,7 +174,7 @@ class gitModel extends model
' task:' . join(' ', $objects['tasks']) .
' bug:' . join(',', $objects['bugs']));
$this->repo->saveAction2PMS($objects, $log, $this->repoRoot, $repo->encoding, 'git');
$this->repo->saveAction2PMS($objects, $log, $this->repoRoot, $repo->encoding, 'git', $gitlabAccountPairs);
}
else
{
+25 -18
View File
@@ -149,9 +149,12 @@ class gitlab extends control
$user = $this->gitlab->apiGetCurrentUser($gitlab->url, $gitlab->token);
if(!isset($user->is_admin) or !$user->is_admin) return print(js::alert($this->lang->gitlab->tokenLimit) . js::locate($this->createLink('gitlab', 'edit', array('gitlabID' => $gitlabID))));
$zentaoUsers = $this->dao->select('account,email,realname')->from(TABLE_USER)->fetchAll('account');
if($_POST)
{
$users = $this->post->zentaoUsers;
$gitlabNames = $this->post->gitlabUserNames;
$accountList = array();
$repeatUsers = array();
foreach($users as $openID => $user)
@@ -167,29 +170,33 @@ class gitlab extends control
$user->providerID = $gitlabID;
$user->providerType = 'gitlab';
/* Delete binded users and save new relationship. */
$this->dao->delete()->from(TABLE_OAUTH)->where('providerType')->eq($user->providerType)->andWhere('providerID')->eq($user->providerID)->exec();
$oldUsers = $this->dao->select('*')->from(TABLE_OAUTH)->where('providerType')->eq($user->providerType)->andWhere('providerID')->eq($user->providerID)->fetchAll('openID');
foreach($users as $openID => $account)
{
if(!$account) continue;
$user->account = $account;
$user->openID = $openID;
$existAccount = isset($oldUsers[$openID]) ? $oldUsers[$openID] : '';
$this->dao->delete()
->from(TABLE_OAUTH)
->where('openID')->eq($user->openID)
->andWhere('providerType')->eq($user->providerType)
->andWhere('providerID')->eq($user->providerID)
->andWhere('account')->eq($user->account)
->exec();
$this->dao->insert(TABLE_OAUTH)->data($user)->exec();
if($existAccount and $existAccount->account != $account)
{
$this->dao->delete()
->from(TABLE_OAUTH)
->where('openID')->eq($openID)
->andWhere('providerType')->eq($user->providerType)
->andWhere('providerID')->eq($user->providerID)
->exec();
$this->loadModel('action')->create('gitlabuser', $openID, 'unbind', '', sprintf($this->lang->gitlab->bindDynamic, $gitlabNames[$openID], $zentaoUsers[$existAccount->account]->realname));
}
if(!$existAccount or $existAccount->account != $account)
{
if(!$account) continue;
$user->account = $account;
$user->openID = $openID;
$this->dao->insert(TABLE_OAUTH)->data($user)->exec();
$this->loadModel('action')->create('gitlabuser', $openID, 'bind', '', sprintf($this->lang->gitlab->bindDynamic, $gitlabNames[$openID], $zentaoUsers[$account]->realname));
}
}
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->server->http_referer));
}
$zentaoUsers = $this->dao->select('account,email,realname')->from(TABLE_USER)->fetchAll('account');
$this->view->title = $this->lang->gitlab->bindUser;
$this->view->userPairs = $userPairs;
$this->view->gitlabUsers = $this->gitlab->apiGetUsers($gitlabID);
@@ -227,8 +234,8 @@ class gitlab extends control
$this->loadModel('action');
$this->gitlab->delete(TABLE_PIPELINE, $id);
$actionID = $this->dao->lastInsertID();
$gitLab = $this->gitlab->getByID($id);
$actionID = $this->action->create('gitlab', $id, 'deleted');
$changes = common::createChanges($oldGitLab, $gitLab);
$this->action->logHistory($actionID, $changes);
echo js::reload('parent');
@@ -252,7 +259,7 @@ class gitlab extends control
$user = $this->gitlab->apiGetCurrentUser($gitlab->url, $gitlab->token, true);
if(!is_object($user)) return $this->send(array('result' => 'fail', 'message' => array('url' => array(sprintf($this->lang->gitlab->hostError, $this->config->gitlab->minCompatibleVersion)))));
if(!isset($user->is_admin) or !$user->is_admin) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->gitlab->tokenError))));
if(isset($user->error)) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->gitlab->tokenError))));
/* Verify version compatibility. */
$result = $this->gitlab->getVersion($gitlab->url, $gitlab->token);
+1
View File
@@ -18,6 +18,7 @@ $lang->gitlab->bindingStatus = 'Binding Status';
$lang->gitlab->notBind = 'Not bind';
$lang->gitlab->binded = 'Binded';
$lang->gitlab->bindedError = 'The bound user has been deleted or modified. Please bind again.';
$lang->gitlab->bindDynamic = '%s and Zentao user %s';
$lang->gitlab->serverFail = 'Connect to GitLab server failed, please check the GitLab server.';
$lang->gitlab->lastUpdate = 'Last Update';
$lang->gitlab->confirmAddWebhook = 'Are you sure about creating Webhook?';
+1
View File
@@ -18,6 +18,7 @@ $lang->gitlab->bindingStatus = '绑定状态';
$lang->gitlab->notBind = '未绑定';
$lang->gitlab->binded = '已绑定';
$lang->gitlab->bindedError = '绑定的用户已删除或者已修改,请重新绑定';
$lang->gitlab->bindDynamic = '%s与禅道用户%s';
$lang->gitlab->serverFail = '连接GitLab服务器异常,请检查GitLab服务器。';
$lang->gitlab->lastUpdate = '最后更新';
$lang->gitlab->confirmAddWebhook = '您确定创建Webhook吗?';
+2
View File
@@ -28,6 +28,7 @@
<tbody>
<?php foreach($gitlabUsers as $gitlabUser):?>
<?php if(isset($gitlabUser->zentaoAccount)) continue;?>
<?php echo html::hidden("gitlabUserNames[$gitlabUser->id]", $gitlabUser->realname);?>
<tr>
<td class='w-60px'><?php echo html::image($gitlabUser->avatar, "height=40");?></td>
<td class='text-left'>
@@ -42,6 +43,7 @@
<?php endforeach;?>
<?php foreach($gitlabUsers as $gitlabUser):?>
<?php if(!isset($gitlabUser->zentaoAccount)) continue;?>
<?php echo html::hidden("gitlabUserNames[$gitlabUser->id]", $gitlabUser->realname);?>
<tr>
<td class='w-60px'><?php echo html::image($gitlabUser->avatar, "height=40");?></td>
<td>
+7 -1
View File
@@ -42,7 +42,13 @@
<?php foreach ($gitlabList as $id => $gitlab): ?>
<tr class='text' title='<?php if(!$gitlab->isAdminToken) echo $lang->gitlab->tokenLimit;?>'>
<td class='text-center'><?php echo $id;?></td>
<td class='text-c-name' title='<?php echo $gitlab->name;?>'><a class="iframe" href="<?php echo $this->createLink('gitlab', 'view', "id=$id", '', true); ?>"><?php echo $gitlab->name;?></a></td>
<td class='text-c-name' title='<?php echo $gitlab->name;?>'>
<?php if(common::hasPriv('gitlab', 'view')):?>
<a class="iframe" href="<?php echo $this->createLink('gitlab', 'view', "id=$id", '', true); ?>"><?php echo $gitlab->name;?></a>
<?php else:?>
<?php echo $gitlab->name;?>
<?php endif;?>
</td>
<td class='text' title='<?php echo $gitlab->url;?>'><?php echo html::a($gitlab->url, $gitlab->url, '_target');?></td>
<td class='c-actions text-left'>
<?php
+1 -1
View File
@@ -26,7 +26,7 @@
<div class="cell">
<div class="detail">
<div class="detail-title"><?php echo $lang->gitlab->url;?></div>
<div class="detail-content article-content"><?php echo $gitlab->url;?></div>
<div class="detail-content article-content"><?php echo html::a($gitlab->url, $gitlab->url, '_target');?></div>
</div>
</div>
<div class='cell action-cell'><?php include '../../common/view/action.html.php';?></div>
+3
View File
@@ -0,0 +1,3 @@
<?php
$config->install = new stdclass();
$config->install->step5RequiredFields = 'company,account,password';
+4 -1
View File
@@ -157,7 +157,10 @@ $lang->install->getPriv = 'Set Admin';
$lang->install->company = 'Company Name';
$lang->install->account = 'Admin Account';
$lang->install->password = 'Admin Password';
$lang->install->errorEmptyPassword = 'Password should not be blank.';
$lang->install->errorEmpty['company'] = "{$lang->install->company} should not be blank.";
$lang->install->errorEmpty['account'] = "{$lang->install->account} should not be blank.";
$lang->install->errorEmpty['password'] = "{$lang->install->password} should not be blank.";
$lang->install->processList['11'] = 'Project management';
$lang->install->processList['12'] = 'Project planning';
+4 -1
View File
@@ -157,7 +157,10 @@ $lang->install->getPriv = '设置帐号';
$lang->install->company = '公司名称';
$lang->install->account = '管理员帐号';
$lang->install->password = '管理员密码';
$lang->install->errorEmptyPassword = '密码不能为空';
$lang->install->errorEmpty['company'] = "{$lang->install->company}不能为空";
$lang->install->errorEmpty['account'] = "{$lang->install->account}不能为空";
$lang->install->errorEmpty['password'] = "{$lang->install->password}不能为空";
$lang->install->processList['11'] = '立项管理';
$lang->install->processList['12'] = '项目规划';
+11 -3
View File
@@ -502,13 +502,21 @@ class installModel extends model
*/
public function grantPriv()
{
if($this->post->password == '') return print(js::error($this->lang->install->errorEmptyPassword));
$requiredFields = explode(',', $this->config->install->step5RequiredFields);
foreach($requiredFields as $field)
{
if(empty($this->post->{$field}))
{
dao::$errors[] = $this->lang->install->errorEmpty[$field];
return false;
}
}
/* Insert a company. */
$company = new stdclass();
$company->name = $this->post->company;
$company->admins = ",{$this->post->account},";
$this->dao->insert(TABLE_COMPANY)->data($company)->autoCheck()->batchCheck('name', 'notempty')->exec();
$this->dao->insert(TABLE_COMPANY)->data($company)->autoCheck()->exec();
if(!dao::isError())
{
/* Set admin. */
@@ -518,7 +526,7 @@ class installModel extends model
$admin->password = md5($this->post->password);
$admin->gender = 'f';
$admin->visions = 'rnd,lite';
$this->dao->replace(TABLE_USER)->data($admin)->check('account', 'notempty')->exec();
$this->dao->replace(TABLE_USER)->data($admin)->exec();
}
}
+1
View File
@@ -65,6 +65,7 @@ class mr extends control
$this->view->objectID = $objectID;
$this->view->orderBy = $orderBy;
$this->view->openIDList = $openIDList;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->display();
}
+1
View File
@@ -60,6 +60,7 @@ $lang->mr->approvalResultList['reject'] = 'Reject';
$lang->mr->needApproved = 'This MR should be approved before merge';
$lang->mr->needCI = 'Merge only after passing CI';
$lang->mr->removeSourceBranch = 'Delete source branch after merge';
$lang->mr->squash = 'Squash commits';
$lang->mr->repeatedOperation = 'Do not repeat operations';
+1
View File
@@ -60,6 +60,7 @@ $lang->mr->approvalResultList['reject'] = '拒绝';
$lang->mr->needApproved = '需要通过评审才能合并';
$lang->mr->needCI = '需要通过构建才能合并';
$lang->mr->removeSourceBranch = '合并后删除源分支';
$lang->mr->squash = '合并提交';
$lang->mr->repeatedOperation = '请勿重复操作';
+15 -5
View File
@@ -162,6 +162,7 @@ class mrModel extends model
->setDefault('repoID', 0)
->setDefault('removeSourceBranch','0')
->setDefault('needCI', 0)
->setDefault('squash', 0)
->add('createdBy', $this->app->user->account)
->add('createdDate', helper::now())
->get();
@@ -184,7 +185,6 @@ class mrModel extends model
$this->dao->insert(TABLE_MR)->data($MR, $this->config->mr->create->skippedFields)
->batchCheck($this->config->mr->create->requiredFields, 'notempty')
->checkIF($MR->needCI, 'jobID', 'notempty')
->autoCheck()
->exec();
if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError());
@@ -198,6 +198,7 @@ class mrModel extends model
$MRObject->title = $MR->title;
$MRObject->description = $MR->description;
$MRObject->remove_source_branch = $MR->removeSourceBranch == '1' ? true : false;
$MRObject->squash = $MR->squash == '1' ? 1 : 0;
if($MR->assignee)
{
$gitlabAssignee = $this->gitlab->getUserIDByZentaoAccount($this->post->gitlabID, $MR->assignee);
@@ -341,6 +342,7 @@ class mrModel extends model
->setDefault('repoID', 0)
->setDefault('removeSourceBranch','0')
->setDefault('needCI', 0)
->setDefault('squash', 0)
->setDefault('editedBy', $this->app->user->account)
->setDefault('editedDate', helper::now())
->setIF($this->post->needCI == 0, 'jobID', 0)
@@ -369,6 +371,7 @@ class mrModel extends model
$newMR->description = $MR->description;
$newMR->target_branch = $MR->targetBranch;
$newMR->remove_source_branch = $MR->removeSourceBranch == '1' ? true : false;
$newMR->squash = $MR->squash == '1' ? 1 : 0;
if($MR->assignee)
{
$gitlabAssignee = $this->gitlab->getUserIDByZentaoAccount($oldMR->gitlabID, $MR->assignee);
@@ -555,6 +558,9 @@ class mrModel extends model
->fetch();
if(empty($todoDesc))
{
$acountPairs = $this->gitlab->getUserIdRealnamePairs($gitlabID);
$author = isset($acountPairs[$rawTodo->author->id]) ? $acountPairs[$rawTodo->author->id] : $rawTodo->author->name;
$todo = new stdClass;
$todo->account = $this->app->user->account;
$todo->assignedTo = $account;
@@ -567,7 +573,7 @@ class mrModel extends model
$todo->idvalue = $rawTodo->id;
$todo->pri = 3;
$todo->name = $this->lang->mr->common . ": " . $rawTodo->target->title;
$todo->desc = $rawTodo->target->assignee->name . '&nbsp;' . $this->lang->mr->at . '&nbsp;' . '<a href="' . $this->gitlab->apiGetSingleProject($gitlabID, $projectID)->web_url . '" target="_blank">' . $rawTodo->project->path .'</a>' . '&nbsp;' . $this->lang->mr->todomessage . '<a href="' . $rawTodo->target->web_url . '" target="_blank">' . '&nbsp;' . $this->lang->mr->common .'</a>' . '。';
$todo->desc = $author . '&nbsp;' . $this->lang->mr->at . '&nbsp;' . '<a href="' . $this->gitlab->apiGetSingleProject($gitlabID, $projectID)->web_url . '" target="_blank">' . $rawTodo->project->path .'</a>' . '&nbsp;' . $this->lang->mr->todomessage . '<a href="' . $rawTodo->target->web_url . '" target="_blank">' . '&nbsp;' . $this->lang->mr->common .'</a>' . '。';
$todo->status = 'wait';
$todo->finishedBy = '';
@@ -747,9 +753,13 @@ class mrModel extends model
*/
public function apiAcceptMR($gitlabID, $projectID, $MRID, $sudo = "")
{
$url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID/merge");
if($sudo != "") return json_decode(commonModel::http($url, $data = null, $options = array(CURLOPT_CUSTOMREQUEST => 'PUT'), $headers = array("sudo: {$sudo}")));
return json_decode(commonModel::http($url, $data = null, $options = array(CURLOPT_CUSTOMREQUEST => 'PUT')));
$apiRoot = $this->gitlab->getApiRoot($gitlabID);
$approveUrl = sprintf($apiRoot, "/projects/$projectID/merge_requests/$MRID/approved");
commonModel::http($approveUrl, null, array(CURLOPT_CUSTOMREQUEST => 'POST'));
$url = sprintf($apiRoot, "/projects/$projectID/merge_requests/$MRID/merge");
if($sudo != "") return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT'), $headers = array("sudo: {$sudo}")));
return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT')));
}
/**
+2
View File
@@ -59,6 +59,7 @@
<th class='w-200px text-left'><?php common::printOrderLink('targetBranch', $orderBy, $vars, $lang->mr->targetBranch);?></th>
<th class='w-120px text-left'><?php common::printOrderLink('mergeStatus', $orderBy, $vars, $lang->mr->mergeStatus);?></th>
<th class='w-120px text-left'><?php common::printOrderLink('approvalStatus', $orderBy, $vars, $lang->mr->approvalStatus);?></th>
<th class='w-120px text-left'><?php common::printOrderLink('createdBy', $orderBy, $vars, $lang->mr->author);?></th>
<th class='w-120px c-actions-3'><?php echo $lang->actions;?></th>
</tr>
</thead>
@@ -82,6 +83,7 @@
<?php else:?>
<td><?php echo empty($MR->approvalStatus) ? $lang->mr->approvalStatusList['notReviewed'] : $lang->mr->approvalStatusList[$MR->approvalStatus];?></td>
<?php endif;?>
<td class='text' title='<?php echo zget($users, $MR->createdBy);?>'><?php echo zget($users, $MR->createdBy);?></td>
<td class='c-actions'>
<?php
$canDelete = ($app->user->admin or (isset($projects[$MR->gitlabID][$MR->sourceProject]->owner->id) and $projects[$MR->gitlabID][$MR->sourceProject]->owner->id == $openIDList[$MR->gitlabID])) ? '' : 'disabled';
+9
View File
@@ -76,6 +76,15 @@
<th><?php echo $lang->job->common;?></th>
<td colspan='1' class='required'><?php echo html::select('jobID', array(''), '', "class='form-control chosen'");?></td>
</tr>
<tr>
<th><?php echo $lang->mr->squash;?></th>
<td colspan='1'>
<div class="checkbox-primary">
<input type="checkbox" name="squash" value="1" id="squash">
<label for="squash"></label>
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->mr->assignee;?></th>
<td><?php echo html::select('assignee', $users, '', "class='form-control chosen'");?></td>
+17
View File
@@ -50,10 +50,17 @@
<th style="white-space: nowrap;"><?php echo $lang->mr->targetProject;?></th>
<td>
<div class='input-group'>
<?php if($MR->status == 'merged' or $MR->status == 'closed'):?>
<span class='fix-border text-left'>
<?php echo $this->loadModel('gitlab')->apiGetSingleProject($MR->gitlabID, $MR->targetProject)->name_with_namespace;?>:
<?php echo $MR->targetBranch;?>
</span>
<?php else:?>
<span class='input-group-addon fix-border'>
<?php echo $this->loadModel('gitlab')->apiGetSingleProject($MR->gitlabID, $MR->targetProject)->name_with_namespace;?>
</span>
<?php echo html::select('targetBranch', $targetBranchList, $MR->targetBranch, "class='form-control chosen'");?>
<?php endif;?>
</div>
</td>
</tr>
@@ -93,6 +100,16 @@
<th><?php echo $lang->job->common;?></th>
<td colspan='1' class='required'><?php echo html::select('jobID', $jobList, $MR->jobID, "class='form-control chosen'");?></td>
</tr>
<tr>
<th><?php echo $lang->mr->squash;?></th>
<td colspan='1'>
<div class="checkbox-primary">
<?php $checked = $MR->squash == '1' ? 'checked' : '' ?>
<input type="checkbox" <?php echo $checked;?> name="squash" value="1" id="squash">
<label for="squash"></label>
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->mr->assignee;?></th>
<td><?php echo html::select('assignee', $users, $assignee, "class='form-control chosen'");?></td>
+1 -1
View File
@@ -106,7 +106,7 @@ js::set('revision', '');
<td>
<div class='input-group'>
<?php echo $productSelect?>
<?php if($branches) echo html::select('branch', $branches, '', "class='form-control' style='width:95px'");?>
<?php if($branches) echo html::select('branch', $branches, '', "class='form-control' style='width:95px' onchange='loadBranch(this)'");?>
</div>
</td>
<th><?php echo $lang->repo->module?></th>
+20 -13
View File
@@ -141,11 +141,15 @@ class repo extends control
$this->app->loadLang('action');
$products = $this->loadModel('product')->getProductPairsByProject($objectID);
$productID = count($products) > 0 ? key($products) : '';
$this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->create;
$this->view->position[] = $this->lang->repo->create;
$this->view->groups = $this->loadModel('group')->getPairs();
$this->view->users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted');
$this->view->products = $this->loadModel('product')->getProductPairsByProject($objectID);
$this->view->products = $products;
$this->view->productID = $productID;
$this->view->gitlabHosts = $this->loadModel('gitlab')->getPairs();
$this->display();
@@ -297,7 +301,6 @@ class repo extends control
$this->app->loadClass('pager', $static = true);
$pager = new pager(0, 8, 1);
$commiters = $this->loadModel('user')->getCommiters();
$logType = 'file';
$revisions = $this->repo->getCommits($repo, '/' . $entry, 'HEAD', $logType, $pager);
@@ -306,7 +309,6 @@ class repo extends control
{
if($revision == 'HEAD' and $i == 0) $revision = $log->revision;
if($revision == $log->revision) $revisionName = strpos($repo->SCM, 'Git') !== false ? $this->repo->getGitRevisionName($log->revision, $log->commit) : $log->revision;
$log->committer = zget($commiters, $log->committer, $log->committer);
$i++;
}
if(!isset($revisionName))
@@ -473,11 +475,6 @@ class repo extends control
/* Synchronous commit only in root path. */
if(strpos($repo->SCM, 'Git') !== false and empty($path) and $infos and empty($revisions)) $this->locate($this->repo->createLink('showSyncCommit', "repoID=$repoID&objectID=$objectID&branch=" . base64_encode($this->cookie->repoBranch)));
/* Set committers. */
$commiters = $this->loadModel('user')->getCommiters();
foreach($infos as $info) $info->committer = zget($commiters, $info->account, $info->account);
foreach($revisions as $log) $log->committer = zget($commiters, $log->committer, $log->committer);
$this->view->title = $this->lang->repo->common;
$this->view->repo = $repo;
$this->view->repos = $this->repos;
@@ -535,9 +532,7 @@ class repo extends control
$this->scm->setEngine($repo);
$info = $this->scm->info($entry, $revision);
$logs = $this->repo->getCommits($repo, $entry, $revision, $type, $pager);
$commiters = $this->loadModel('user')->getCommiters();
foreach($logs as $log) $log->committer = zget($commiters, $log->committer, $log->committer);
$logs = $this->repo->getCommits($repo, $entry, $revision, $type, $pager);
$this->view->repo = $repo;
$this->view->title = $this->lang->repo->common;
@@ -1080,9 +1075,7 @@ class repo extends control
$repo = $this->repo->getRepoByID($repoID);
$path = $this->repo->decodePath($path);
$commiters = $this->loadModel('user')->getCommiters();
$revisions = $this->repo->getCommits($repo, $path, 'HEAD', $type, $pager);
foreach($revisions as $revision) $revision->committer = zget($commiters, $revision->committer, $revision->committer);
$this->view->repo = $this->repo->getRepoByID($repoID);
$this->view->revisions = $revisions;
@@ -1262,4 +1255,18 @@ class repo extends control
{
return $this->send(array('status' => 'success', 'rules' => $this->config->repo->rules));
}
/**
* Ajax get executions.
*
* @param int $productID
* @param int $branch
* @access public
* @return void
*/
public function ajaxGetExecutions($productID, $branch = 0)
{
$executions = $this->repo->getExecutionPairs($productID, $branch);
echo html::select('execution', array('' => '') + $executions, '', 'class="form-control chosen"');
}
}
+1
View File
@@ -11,6 +11,7 @@ h3 {font-size: 16px;}
.mini-icon {display: inline-block; height: 16px; width: 16px; background-color: transparent; background-position: 0 0; background-repeat: no-repeat; vertical-align: text-bottom;}
.action {float: left;}
.input-group select#encrypt {border-left: 0px;}
.input-group #encrypt_chosen {width: 40% !important;}
.arrange {float: right;}
.versions {position: relative;}
#diffRepo {position: absolute; left: 20px; z-index: 1000;}
+45 -15
View File
@@ -206,6 +206,8 @@ class repoModel extends model
->setIf($this->post->SCM == 'Gitlab', 'client', $this->post->gitlabHost)
->setIf($this->post->SCM == 'Gitlab', 'extra', $this->post->gitlabProject)
->setIf($this->post->SCM == 'Gitlab', 'prefix', '')
->setIf($this->post->SCM == 'Git', 'account', '')
->setIf($this->post->SCM == 'Git', 'password', '')
->skipSpecial('path,client,account,password')
->setDefault('product', '')
->join('product', ',')
@@ -219,8 +221,9 @@ class repoModel extends model
{
$scm = $this->app->loadClass('scm');
$scm->setEngine($data);
$info = $scm->info('');
$data->prefix = empty($info->root) ? '' : trim(str_ireplace($info->root, '', str_replace('\\', '/', $data->path)), '/');
$info = $scm->info('');
$infoRoot = urldecode($info->root);
$data->prefix = empty($infoRoot) ? '' : trim(str_ireplace($infoRoot, '', str_replace('\\', '/', $data->path)), '/');
if($data->prefix) $data->prefix = '/' . $data->prefix;
}
@@ -280,8 +283,9 @@ class repoModel extends model
{
$scm = $this->app->loadClass('scm');
$scm->setEngine($data);
$info = $scm->info('');
$data->prefix = empty($info->root) ? '' : trim(str_ireplace($info->root, '', str_replace('\\', '/', $data->path)), '/');
$info = $scm->info('');
$infoRoot = urldecode($info->root);
$data->prefix = empty($infoRoot) ? '' : trim(str_ireplace($infoRoot, '', str_replace('\\', '/', $data->path)), '/');
if($data->prefix) $data->prefix = '/' . $data->prefix;
}
elseif($data->SCM != $repo->SCM and $data->SCM == 'Git')
@@ -1246,7 +1250,7 @@ class repoModel extends model
dao::$errors['client'] = $this->lang->repo->error->clientVersion;
return false;
}
if(preg_match('/[^\:\/\\A-Za-z0-9_\-\'\"\.]/', $path))
if(preg_match('/[^\:\/A-Za-z0-9_\-\'\"\.]/', $path))
{
dao::$errors['encoding'] = $this->lang->repo->error->encoding . "<br />" . nl2br($message);
return false;
@@ -1370,7 +1374,7 @@ class repoModel extends model
{
$tasks[$id] = $id;
$actions['task'][$id]['start']['consumed'] = $matches[11][$i];
$actions['task'][$id]['start']['left'] = $matches[16][$i];
$actions['task'][$id]['start']['left'] = $matches[17][$i];
}
}
}
@@ -1385,7 +1389,7 @@ class repoModel extends model
{
$tasks[$id] = $id;
$actions['task'][$id]['effort']['consumed'] = $matches[11][$i];
$actions['task'][$id]['effort']['left'] = $matches[16][$i];
$actions['task'][$id]['effort']['left'] = $matches[17][$i];
}
}
}
@@ -1506,8 +1510,8 @@ class repoModel extends model
$storyReg = "(($storyModule) *(({$idMarks})[0-9]+(({$idSplits})[0-9]+)*))";
$taskReg = "(($taskModule) *(({$idMarks})[0-9]+(({$idSplits})[0-9]+)*))";
$bugReg = "(($bugModule) *(({$idMarks})[0-9]+(({$idSplits})[0-9]+)*))";
$costReg = "($costs) *(($costMarks)([0-9]+)($costUnit))";
$leftReg = "($lefts) *(($leftMarks)([0-9]+)($leftUnit))";
$costReg = "($costs) *(($costMarks)([0-9]+(\.?[0-9]+)?)($costUnit))";
$leftReg = "($lefts) *(($leftMarks)([0-9]+(\.?[0-9]+)?)($leftUnit))";
$startTaskReg = "({$startAction}) *{$taskReg}.*$costReg.*$leftReg";
$effortTaskReg = "({$effortAction}) *{$taskReg}.*$costReg.*$leftReg";
@@ -1533,11 +1537,21 @@ class repoModel extends model
* @param array $objects
* @param object $log
* @param string $repoRoot
* @param string $encodings
* @param string $scm
* @param array $gitlabAccountPairs
* @access public
* @return void
*/
public function saveAction2PMS($objects, $log, $repoRoot = '', $encodings = 'utf-8', $scm = 'svn')
public function saveAction2PMS($objects, $log, $repoRoot = '', $encodings = 'utf-8', $scm = 'svn', $gitlabAccountPairs = array())
{
if(empty($gitlabAccountPairs))
{
$commiters = $this->loadModel('user')->getCommiters('account');
$log->author = zget($commiters, $log->author);
}
$log->author = isset($gitlabAccountPairs[$log->author]) ? $gitlabAccountPairs[$log->author] : $log->author;
if(isset($this->app->user))
{
$account = $this->app->user->account;
@@ -1545,11 +1559,11 @@ class repoModel extends model
}
$action = new stdclass();
$action->actor = $log->author;
$action->date = $log->date;
$action->actor = $log->author;
$action->date = $log->date;
$action->extra = $scm == 'svn' ? $log->revision : substr($log->revision, 0, 10);
$action->comment = htmlSpecialString($this->iconvComment($log->msg, $encodings));
$action->extra = $scm == 'svn' ? $log->revision : substr($log->revision, 0, 10);
$comment = htmlSpecialString($this->iconvComment($log->msg, $encodings));
$this->loadModel('action');
$actions = $objects['actions'];
@@ -1566,7 +1580,7 @@ class repoModel extends model
$action->objectID = $taskID;
$action->product = $productsAndExecutions[$taskID]['product'];
$action->execution = $productsAndExecutions[$taskID]['execution'];
$action->comment = $this->lang->repo->revisionA . ': #' . $action->extra . "<br />" . $action->comment;
$action->comment = $this->lang->repo->revisionA . ': #' . $action->extra . "<br />" . $comment;
foreach($taskActions as $taskAction => $params)
{
$_POST = array();
@@ -1961,4 +1975,20 @@ class repoModel extends model
$this->fixCommit($repoID);
}
/**
* Get execution pairs.
*
* @param int $product
* @param int $branch
* @access public
* @return array
*/
public function getExecutionPairs($product, $branch = 0)
{
$pairs = array();
$executions = $this->loadModel('execution')->getList(0, 'all', 'undone', 0, $product, $branch);
foreach($executions as $execution) $pairs[$execution->id] = $execution->name;
return $pairs;
}
}
+1 -1
View File
@@ -91,7 +91,7 @@
</td>
<td align='center'><?php echo $repo->SCM == 'Subversion' ? $info->revision : substr($info->revision, 0, 10);?></td>
<td><?php echo substr($info->date, 0, 10)?></td>
<td><?php echo $info->committer?></td>
<td><?php echo $info->account?></td>
<?php $comment = htmlSpecialString($info->comment, ENT_QUOTES);?>
<td class='comment' title='<?php echo $comment?>'><?php echo $comment?></td>
</tr>
+4 -5
View File
@@ -25,16 +25,16 @@
<table class='table table-form'>
<tr>
<th><?php echo $lang->repo->product; ?></th>
<td class='required'><?php echo html::select('product[]', $products, '', "class='form-control chosen' multiple"); ?></td>
<td class='required'><?php echo html::select('product[]', $products, $productID, "class='form-control chosen' multiple"); ?></td>
</tr>
<tr>
<th class='thWidth'><?php echo $lang->repo->type; ?></th>
<td style="width:550px"><?php echo html::select('SCM', $lang->repo->scmList, 'Gitlab', "onchange='scmChanged(this.value)' class='form-control'"); ?></td>
<td style="width:550px"><?php echo html::select('SCM', $lang->repo->scmList, 'Gitlab', "onchange='scmChanged(this.value)' class='form-control chosen'"); ?></td>
<td class="tips-git"><?php echo $lang->repo->syncTips; ?></td>
</tr>
<tr class='gitlab hide'>
<th><?php echo $lang->repo->gitlabHost;?></th>
<td class='required'><?php echo html::select('gitlabHost', $gitlabHosts, '', "class='form-control' placeholder='{$lang->repo->placeholder->gitlabHost}'");?>
<td class='required'><?php echo html::select('gitlabHost', $gitlabHosts, '', "class='form-control chosen' placeholder='{$lang->repo->placeholder->gitlabHost}'");?>
</tr>
<tr class='gitlab hide'>
<th><?php echo $lang->repo->gitlabProject;?></th>
@@ -75,8 +75,7 @@
<td>
<div class='input-group'>
<?php echo html::password('password', '', "class='form-control'");?>
<span class='input-group-addon fix-border fix-padding'></span>
<?php echo html::select('encrypt', $lang->repo->encryptList, 'base64', "class='form-control'");?>
<?php echo html::select('encrypt', $lang->repo->encryptList, 'base64', "class='form-control chosen'");?>
</div>
</td>
</tr>
+3 -4
View File
@@ -33,12 +33,12 @@
</tr>
<tr>
<th class='thWidth'><?php echo $lang->repo->type; ?></th>
<td style="width:550px"><?php echo html::select('SCM', $lang->repo->scmList, $repo->SCM, "onchange='scmChanged(this.value)' class='form-control'"); ?></td>
<td style="width:550px"><?php echo html::select('SCM', $lang->repo->scmList, $repo->SCM, "onchange='scmChanged(this.value)' class='form-control chosen'"); ?></td>
<td><span class="tips-git"><?php echo $lang->repo->syncTips; ?></span></td>
</tr>
<tr class='gitlab hide'>
<th><?php echo $lang->repo->gitlabHost;?></th>
<td class='required'><?php echo html::select('gitlabHost', $gitlabHosts, isset($repo->gitlab) ? $repo->gitlab : '', "class='form-control' placeholder='{$lang->repo->placeholder->gitlabHost}'");?>
<td class='required'><?php echo html::select('gitlabHost', $gitlabHosts, isset($repo->gitlab) ? $repo->gitlab : '', "class='form-control chosen' placeholder='{$lang->repo->placeholder->gitlabHost}'");?>
</tr>
<tr class='gitlab hide'>
<th><?php echo $lang->repo->gitlabProject;?></th>
@@ -79,8 +79,7 @@
<td>
<div class='input-group'>
<?php echo html::password('password', $repo->password, "class='form-control'");?>
<span class='input-group-addon fix-border fix-padding'></span>
<?php echo html::select('encrypt', $lang->repo->encryptList, $repo->encrypt, "class='form-control'");?>
<?php echo html::select('encrypt', $lang->repo->encryptList, $repo->encrypt, "class='form-control chosen'");?>
</div>
</td>
<td></td>
+4 -4
View File
@@ -36,19 +36,19 @@
<td class='text-center'><?php echo $repo->id; ?></td>
<td class='text'><?php echo zget($lang->repo->scmList, $repo->SCM); ?></td>
<td class='text' title='<?php echo $repo->name; ?>'><?php echo html::a($this->createLink('repo', 'browse', "repoID={$repo->id}&branchID=&objectID=$objectID"), $repo->name);?></td>
<td class='text'>
<?php
$productList = explode(',', str_replace(' ', '', $repo->product));
$productNames = '';
$productList = explode(',', str_replace(' ', '', $repo->product));
if(isset($productList) and $productList[0])
{
foreach($productList as $productID)
{
if(!isset($products[$productID])) continue;
echo ' ' . html::a($this->createLink('product', 'browse', "productID=$productID"), zget($products, $productID, $productID));
$productNames .= ' ' . zget($products, $productID, $productID);
}
}
?>
</td>
<td class='text' title='<?php echo $productNames;?>'><?php echo $productNames;?></td>
<td class='text' title='<?php echo $repo->path; ?>'><?php echo $repo->path; ?></td>
<td class='text-left c-actions'>
<?php
+9 -1
View File
@@ -124,7 +124,15 @@ class treeModel extends model
public function getOptionMenu($rootID, $type = 'story', $startModule = 0, $branch = 0)
{
if(empty($branch)) $branch = 0;
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getModulePairs();
if(defined('TUTORIAL'))
{
$modulePairs = $this->loadModel('tutorial')->getModulePairs();
if(!is_array($branch)) return $modulePairs;
$modules = array();
foreach($branch as $b) $modules[$b] = $modulePairs;
return $modules;
}
/* If type of $branch is array, get modules of these branches. */
if(gettype($branch) == 'array')
+3
View File
@@ -275,8 +275,11 @@ class tutorialModel extends model
$execution->name = 'Test execution';
$execution->code = 'test';
$execution->lifetime = '';
$execution->attribute = '';
$execution->begin = date('Y-m-d', strtotime('-7 days'));
$execution->end = date('Y-m-d', strtotime('+7 days'));
$execution->realBegan = '';
$execution->realEnd = '';
$execution->days = 10;
$execution->status = 'wait';
$execution->pri = '1';
+2
View File
@@ -69,3 +69,5 @@
.card.ad > .card-reveal > .card-heading {padding: 12px 10px 10px 15px;}
.card.ad > .card-reveal {color: #333;}
.card.ad > .card-reveal li {line-height: 1.5; font-size: 12px;}
.result-box {height: 400px; position: fixed; left: 50%; top: 50%; margin-left: -400px; margin-top: -200px;}
+2 -1
View File
@@ -87,7 +87,8 @@ $lang->upgrade->mergeProgramDesc = <<<EOD
<h4>2. Independent {$lang->projectCommon}</h4>
<p>Choose several {$lang->projectCommon}s and migrate them to one Program, or migrate them separately.</p>
<h4>4. Link {$lang->projectCommon}s of several {$lang->productCommon}s</h4>
<p>You can set {$lang->projectCommon}s as one new project.</p>
<p>After selecting a historical {$lang->projectCommon} as a project upgrade, the user can select the program to which this project belongs or create a new program.</p>
<p>After selecting a historical {$lang->projectCommon} as the iterative upgrade, the user can select the project and program to which the execution belongs or create a new project and program.</p>
EOD;
$lang->upgrade->to15Mode['classic'] = 'Keep the classic mode';
+2 -1
View File
@@ -87,7 +87,8 @@ $lang->upgrade->mergeProgramDesc = <<<EOD
<h4>情况三:独立的{$lang->projectCommon}</h4>
<p>可以选择若干个{$lang->projectCommon}迁移到一个项目集中,也可以独立迁移。</p>
<h4>情况四:关联多个{$lang->productCommon}的{$lang->projectCommon}</h4>
<p>可以选择这些{$lang->projectCommon}归属于某个新项目下。</p>
<p>选择历史{$lang->projectCommon}作为项目升级后,用户可以选择这个项目所属的项目集或新建项目集。</p>
<p>选择历史{$lang->projectCommon}作为迭代升级后,用户可以选择这个执行所属的项目集、项目或新建项目集、项目。</p>
EOD;
$lang->upgrade->to15Mode['classic'] = '经典管理模式';
+1 -1
View File
@@ -11,7 +11,7 @@
?>
<?php include '../../common/view/header.lite.html.php';?>
<div class='container'>
<div class='modal-dialog'>
<div class='modal-dialog result-box'>
<div class='modal-header'>
<strong><?php echo $lang->upgrade->result;?></strong>
</div>
+3 -2
View File
@@ -158,10 +158,11 @@ class userModel extends model
/**
* Get commiters from the user table.
*
* @param string $field
* @access public
* @return array
*/
public function getCommiters()
public function getCommiters($field = 'realname')
{
$rawCommiters = $this->dao->select('commiter, account, realname')->from(TABLE_USER)->where('commiter')->ne('')->fetchAll();
if(!$rawCommiters) return array();
@@ -172,7 +173,7 @@ class userModel extends model
$userCommiters = explode(',', $commiter->commiter);
foreach($userCommiters as $userCommiter)
{
$commiters[$userCommiter] = $commiter->realname ? $commiter->realname : $commiter->account;
$commiters[$userCommiter] = $commiter->$field ? $commiter->$field : $commiter->account;
}
}
@@ -8,8 +8,9 @@ class myClient extends client
if($statusFile)
{
$this->app->loadLang('extension');
$this->view->error = sprintf($this->lang->extension->noticeOkFile, str_replace('\\', '/', $statusFile));
die($this->display('client', 'safe'));
$statusFile = str_replace('\\', '/', $statusFile);
$this->view->error = sprintf($this->lang->extension->noticeOkFile, $statusFile, $statusFile);
return print($this->display('client', 'safe'));
}
if($_POST) $_POST['desc'] = mb_substr($this->post->desc, 0, 100);
@@ -8,8 +8,9 @@ class myClient extends client
if($statusFile)
{
$this->app->loadLang('extension');
$this->view->error = sprintf($this->lang->extension->noticeOkFile, str_replace('\\', '/', $statusFile));
die($this->display('client', 'safe'));
$statusFile = str_replace('\\', '/', $statusFile);
$this->view->error = sprintf($this->lang->extension->noticeOkFile, $statusFile, $statusFile);
return print($this->display('client', 'safe'));
}
if($_POST) $_POST['desc'] = mb_substr($this->post->desc, 0, 100);