Merge branch '15.0.beta3' of https://gitlab.zcorp.cc/easycorp/zentaopms into 15.0.beta3

This commit is contained in:
hufangzhou
2021-04-28 11:00:32 +08:00
15 changed files with 436 additions and 43 deletions
+9 -2
View File
@@ -501,7 +501,8 @@ class gitlab
if($version)
{
$lastCommit = $this->getSingleCommit($version);
if(empty($lastCommit)) return array();
if(!isset($lastCommit->committed_date)) return array('commits' => array(), 'files' => array());
$params['until'] = $lastCommit->committed_date;
}
@@ -644,7 +645,13 @@ class gitlab
$api = ltrim($api, '/');
$api = $this->root . $api . '?' . http_build_query($params);
$response = file_get_contents($api);
$response = commonModel::http($api);
if(!empty(commonModel::$requestErrors))
{
commonModel::$requestErrors = array();
return array();
}
return json_decode($response);
}
+1 -1
View File
@@ -401,7 +401,7 @@ class bug extends control
else
{
setcookie('bugModule', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
$location = $this->createLink('bug', 'browse', "productID={$this->post->product}&branch=$branch&browseType=unclosed&param=0&orderBy=id_desc");
$location = $this->createLink('bug', 'browse', "productID={$this->post->product}&branch=$branch&browseType=byModule&param={$this->post->module}&orderBy=id_desc");
}
if($this->app->getViewType() == 'xhtml') $location = $this->createLink('bug', 'view', "bugID=$bugID");
$response['locate'] = $location;
+2 -1
View File
@@ -209,7 +209,8 @@ function loadProductModules(productID)
{
branch = $('#branch').val();
if(typeof(branch) == 'undefined') branch = 0;
link = createLink('tree', 'ajaxGetOptionMenu', 'productID=' + productID + '&viewtype=bug&branch=' + branch + '&rootModuleID=0&returnType=html&fieldID=&needManage=true');
if(typeof(moduleID) == 'undefined') moduleID = 0;
link = createLink('tree', 'ajaxGetOptionMenu', 'productID=' + productID + '&viewtype=bug&branch=' + branch + '&rootModuleID=0&returnType=html&fieldID=&needManage=true&extra=&currentModuleID=' + moduleID);
$('#moduleIdBox').load(link, function()
{
$(this).find('select').chosen()
+1
View File
@@ -25,6 +25,7 @@ js::set('stepsNotEmpty', $lang->bug->stepsNotEmpty);
js::set('isStepsTemplate', $isStepsTemplate);
js::set('oldProjectID', $projectID);
js::set('blockID', $blockID);
js::set('moduleID', $moduleID);
?>
<div id="mainContent" class="main-content fade">
<div class="center-block">
+1
View File
@@ -54,3 +54,4 @@ $lang->cron->notice->mon = '取值范围:1-12';
$lang->cron->notice->dow = '取值范围:0-6';
$lang->cron->notice->help = '注:如果服务器重启,或者发现计划任务没有正常工作,那么计划任务已经停止工作。需要手动点击【重启】按钮,或者一分钟后刷新页面,来开启计划任务。如果任务列表中第一条记录的最后执行时间改变,说明任务开启成功。';
$lang->cron->notice->errorRule = '"%s" 填写的不是合法的值';
$lang->cron->notice->errorType = '不能创建操作系统命令类型的计划任务';
+38 -26
View File
@@ -13,8 +13,8 @@ class cronModel extends model
{
/**
* Get by Id.
*
* @param int $cronID
*
* @param int $cronID
* @access public
* @return object
*/
@@ -25,8 +25,8 @@ class cronModel extends model
/**
* Get crons.
*
* @param string $params
*
* @param string $params
* @access public
* @return array
*/
@@ -40,8 +40,8 @@ class cronModel extends model
/**
* Parse crons.
*
* @param array $crons
*
* @param array $crons
* @access public
* @return array
*/
@@ -64,12 +64,12 @@ class cronModel extends model
$parsedCron['cron'] = CronExpression::factory($parsedCron['schema']);
$parsedCron['time'] = $parsedCron['cron']->getNextRunDate();
$parsedCrons[$cron->id] = $parsedCron;
}
catch(InvalidArgumentException $e)
}
catch(InvalidArgumentException $e)
{
$this->dao->update(TABLE_CRON)->set('status')->eq('stop')->where('id')->eq($cron->id)->exec();
continue;
}
}
}
}
$this->dao->update(TABLE_CRON)->set('lastTime')->eq(date(DT_DATETIME1))->where('lastTime')->eq('0000-00-00 00:00:00')->andWhere('status')->ne('stop')->exec();
@@ -78,10 +78,10 @@ class cronModel extends model
/**
* Change cron status.
*
* @param int $cronID
* @param string $status
* @param bool $changeTime
*
* @param int $cronID
* @param string $status
* @param bool $changeTime
* @access public
* @return bool
*/
@@ -96,8 +96,8 @@ class cronModel extends model
/**
* Log cron.
*
* @param string $log
*
* @param string $log
* @access public
* @return void
*/
@@ -115,7 +115,7 @@ class cronModel extends model
/**
* Get last execed time.
*
*
* @access public
* @return string
*/
@@ -127,7 +127,7 @@ class cronModel extends model
/**
* Runable cron.
*
*
* @access public
* @return bool
*/
@@ -145,7 +145,7 @@ class cronModel extends model
/**
* Check change cron.
*
*
* @access public
* @return bool
*/
@@ -156,8 +156,8 @@ class cronModel extends model
}
/**
* Create cron.
*
* Create cron.
*
* @access public
* @return int
*/
@@ -169,6 +169,12 @@ class cronModel extends model
->skipSpecial('m,h,dom,mon,dow,command')
->get();
if(!$this->config->features->cronSystemCall and $cron->type == 'system')
{
dao::$errors[] = $this->lang->cron->notice->errorType;
return false;
}
$result = $this->checkRule($cron);
if(!empty($result))
{
@@ -182,9 +188,9 @@ class cronModel extends model
}
/**
* Update cron.
*
* @param int $cronID
* Update cron.
*
* @param int $cronID
* @access public
* @return bool
*/
@@ -195,6 +201,12 @@ class cronModel extends model
->skipSpecial('m,h,dom,mon,dow,command')
->get();
if(!$this->config->features->cronSystemCall and $cron->type == 'system')
{
dao::$errors[] = $this->lang->cron->notice->errorType;
return false;
}
$result = $this->checkRule($cron);
if(!empty($result))
{
@@ -208,8 +220,8 @@ class cronModel extends model
/**
* Check cron rule.
*
* @param object $cron
*
* @param object $cron
* @access public
* @return string
*/
@@ -256,7 +268,7 @@ class cronModel extends model
/**
* Get current cron status.
*
*
* @access public
* @return int
*/
-1
View File
@@ -72,7 +72,6 @@ class executionModel extends model
if($execution->type == 'stage')
{
global $lang;
$this->loadModel('execution');
$this->app->loadLang('project');
$lang->executionCommon = $lang->project->stage;
include $this->app->getModulePath('execution') . 'lang/' . $this->app->getClientLang() . '.php';
+1 -1
View File
@@ -867,7 +867,7 @@ class repo extends control
set_time_limit(0);
$repo = $this->repo->getRepoByID($repoID);
if(empty($repo)) die();
//if($repo->synced) die('finish');
if($repo->synced) die('finish');
$this->commonAction($repoID);
$this->scm->setEngine($repo);
+5 -2
View File
@@ -281,15 +281,18 @@ class repoModel extends model
$repo = $this->getRepoByID($id);
$data = fixer::input('post')
->setIf($this->post->SCM == 'Gitlab', 'password', $this->post->gitlabToken)
->setIf($this->post->SCM == 'Gitlab', 'client', $this->post->gitlabHost)
->setIf($this->post->SCM == 'Gitlab', 'extra', $this->post->gitlabProject)
->setDefault('client', 'svn')
->setDefault('prefix', $repo->prefix)
->setDefault('product', '')
->setIF($this->post->path != $repo->path, 'synced', 0)
->skipSpecial('path,client,account,password')
->join('product', ',')
->get();
if($this->post->SCM == 'Gitlab') $data->path = sprintf($this->config->repo->gitlab->apiPath, $data->gitlabHost, $this->post->gitlabProject);
if($data->path != $repo->path) $data->synced = 0;
$data->acl = empty($data->acl) ? '' : json_encode($data->acl);
@@ -313,7 +316,7 @@ class repoModel extends model
$this->dao->update(TABLE_REPO)->data($data, $skip = 'gitlabHost,gitlabToken,gitlabProject')
->batchCheck($this->config->repo->edit->requiredFields, 'notempty')
->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty')
->checkIF($data->SCM == 'GitLab', 'gitlabProject', 'notempty')
->checkIF($data->SCM == 'GitLab', 'extra', 'notempty')
->autoCheck()
->where('id')->eq($id)->exec();
+4
View File
@@ -16,3 +16,7 @@ html[lang="en"] .main-header > .input-group {width: 250px;}
#formSettingBtn {position: absolute; top: 14px; right: 20px; z-index: 1000;}
#formSettingBtn .dropdown {margin-right: 0px;}
#formSettingBtn #formSetting {padding: 10px 12px;}
#formSettingBtn .checkboxes {padding: 10px 3px;}
#formSettingBtn .checkbox-primary {width: 50%; float: left; margin: 3px 0;}
#formSetting .btn {margin-right: 8px;}
+4 -2
View File
@@ -419,10 +419,12 @@ class tree extends control
* @param string $returnType
* @param string $fieldID
* @param bool $needManage
* @param string $extra
* @param int $currentModuleID
* @access public
* @return string the html select string.
*/
public function ajaxGetOptionMenu($rootID, $viewType = 'story', $branch = 0, $rootModuleID = 0, $returnType = 'html', $fieldID = '', $needManage = false, $extra = '')
public function ajaxGetOptionMenu($rootID, $viewType = 'story', $branch = 0, $rootModuleID = 0, $returnType = 'html', $fieldID = '', $needManage = false, $extra = '', $currentModuleID = 0)
{
if($viewType == 'task')
{
@@ -448,7 +450,7 @@ class tree extends control
$changeFunc = '';
if($viewType == 'task' or $viewType == 'bug' or $viewType == 'case') $changeFunc = "onchange='loadModuleRelated()'";
$field = $fieldID ? "modules[$fieldID]" : 'module';
$output = html::select("$field", $optionMenu, '', "class='form-control' $changeFunc");
$output = html::select("$field", $optionMenu, $currentModuleID, "class='form-control' $changeFunc");
if(count($optionMenu) == 1 and $needManage)
{
$output .= "<span class='input-group-addon'>";
+1 -1
View File
@@ -191,7 +191,7 @@ class userModel extends model
/**
* Get user info by ID.
*
* @param int $userID
* @param mix $userID
* @access public
* @return object|bool
*/
+82 -6
View File
@@ -1,6 +1,6 @@
<?php
/**
* 本文件创建一个 app 示例,并且通过执行 $app->loadCommon() 方法创建名为 tester 的commonModel对象。
* 本文件创建一个 app 实例,并且通过执行 $app->loadCommon() 方法创建名为 tester 的commonModel对象。
* This file build a app instance and provide a instance of commonModel named as tester by $app->loadCommon().
*
* All request of entries should be routed by this router.
@@ -13,13 +13,89 @@
* @link http://www.zentao.net
*/
/* Set the error reporting. */
error_reporting(0);
error_reporting(E_ALL & E_STRICT);
$frameworkRoot = dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'framework' . DIRECTORY_SEPARATOR;
/* Load the framework. */
include '../framework/router.class.php';
include '../framework/control.class.php';
include '../framework/model.class.php';
include '../framework/helper.class.php';
include $frameworkRoot . 'router.class.php';
include $frameworkRoot . 'control.class.php';
include $frameworkRoot . 'model.class.php';
include $frameworkRoot . 'helper.class.php';
$app = router::createApp('pms', dirname(dirname(__FILE__)), 'router');
$tester = $app->loadCommon();
$config->zendataRoot = dirname(__FILE__) . DS . 'zendata';
$config->zdPath = "/usr/local/zd/zd";
/**
* Save variable to $_result.
*
* @param mix $result
* @access public
* @return bool true
*/
function run($result)
{
global $_result;
$_result = $result;
return true;
}
/**
* Print expect data.
*
* @param int $key
* @param string $delimiter
* @access public
* @return void
*/
function expect($key, $delimiter = ',')
{
global $_result;
echo ">> ";
$result = "";
if(!is_array($_result) and !is_object($_result))
{
$result = (string) $_result;
}
else
{
$keyList = explode(',', $key);
$dimension = 1;
foreach($_result as $value)
{
if(is_array($value) or is_object($value)) $dimension = 2;
}
if($dimension == 1) $_result = array($_result);
foreach($_result as $object)
{
foreach($keyList as $key) $result .= zget($object, $key, '') . $delimiter;
}
$result = trim($result, $delimiter);
}
echo $result . "\n";
echo "\n";
}
/**
* Import data create by zendata to one table.
*
* @param string $table
* @param string $yaml
* @param int $count
* @access public
* @return void
*/
function zdImport($table, $yaml, $count = 10)
{
chdir(dirname(__FILE__));
global $app, $config;
$dns = "mysql://{$config->db->user}:{$config->db->password}@{$config->db->host}:{$config->db->port}/{$config->db->name}#utf8";
$table = trim($table, '`');
$commad = "$config->zdPath -c $yaml -t $table -T -dns $dns --clear -n $count";
system($commad);
}
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/init.php';
/**
[case]
title=测试 userModel::getById();
cid=1
pid=1
[group]
1. 使用ID获取一个存在的用户 >> `\d,\w+`
2. 使用account获取一个存在的用户 >> `\d`
3. 使用account获取一个存在的用户 >> ``
[esac]
*/
$user = $tester->loadModel('user');
$app->dbh->query("truncate zt_user");
zdImport(TABLE_USER, "zendata/user.yaml", 10);
$randUser = $tester->dao->select('*,rand() as rand')->from(TABLE_USER)->orderBy('rand')->fetch();
if(!$randUser) exit("Prepair data error.");
unset($randUser->rand);
/* Step 1.*/
run($user->getByID($randUser->id, 'id')) and expect('id,account');
/* Step 2.*/
run($user->getByID($randUser->account, 'account')) and expect('id');
/* Step 3.*/
run($user->getByID(null, 'id')) and expect('id');
+256
View File
@@ -0,0 +1,256 @@
title: table zt_user
desc: "用户信息"
author: automated export
version: "1.0"
fields:
- field: id
note: "ID"
range: 1-10000
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: dept
note: "所属部门"
range: 1-10000
prefix: ""
postfix: "\t"
format: ""
- field: account
note: "用户名"
from: name.enaccount.v1.yaml
use: common_underline
postfix: "\t" # 后缀,特殊字符加引号,否则无法解析。
format: ""
- field: password
note: "密码"
range: 123456
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: role
note: "职位"
range: qa,dev,pm,po,td,pd,qd,top,market,service,operation,support,others
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: realname
note: "真实姓名"
from: name.cnreal.v1.yaml
use: three
format: ""
- field: nickname
note: "昵称"
from: name.enaccount.v1.yaml
use: common
postfix: "\t"
loop: 0
- field: commiter
note: "源代码帐号"
from: name.enaccount.v1.yaml
use: common
postfix: "@zentao.net"
loop: 0
format: ""
- field: avatar
note: ""
range: 0
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: birthday
note: "生日"
from: time.date.v1.yaml
use: date
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: gender
note: "性别"
range: f,m
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: email
note: "邮箱"
range: 1-10000
prefix: "这里是邮箱"
postfix: "\t"
loop: 0
format: ""
- field: skype
note: "Skype"
range: Skype
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: qq
note: "QQ"
range: QQ
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: mobile
note: "手机"
range: mobile
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: phone
note: "电话"
range: phone
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: weixin
note: "微信"
range: weixin
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: dingding
note: "钉钉"
range: dingding
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: slack
note: "Slack"
range: slack
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: whatsapp
note: "WhatsApp"
range: whatsApp
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: address
note: "通讯地址"
range: 1-10000
prefix: "这是通讯地址"
postfix: "\t"
loop: 0
format: ""
- field: zipcode
note: "邮编"
range: 1-10000
prefix: "这是邮编"
postfix: "\t"
loop: 0
format: ""
- field: join
note: "入职日期"
from: time.date.v1.yaml
use: date
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: visits
note: "访问次数"
range: 0-10000:R
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: ip
note: "最后IP"
from: ip.v1.yaml
use: ipA,ipB
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: last
note: "最后登录"
range: 1-10000
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: fails
note: "失败次数"
range: 1-10000
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: locked
note: "锁定时间"
from: time.date.v1.yaml
use: date
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: feedback
note: "反馈[非研发]"
range: 0
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: ranzhi
note: "ZDOO账号"
range: 0
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: ldap
note: ""
range: 0
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: score
note: "积分"
range: 1-10000:R
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: scoreLevel
note: "积分等级"
range: 0
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: deleted
note: "是否删除"
range: 0
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: clientStatus
note: "连接状态"
range: offline
prefix: ""
postfix: "\t"
loop: 0
format: ""
- field: clientLang
note: "连接语言"
range: en
prefix: ""
postfix: "\t"
loop: 0
format: ""