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

This commit is contained in:
wangyidong
2021-04-28 09:19:10 +08:00
33 changed files with 474 additions and 91 deletions
+3 -2
View File
@@ -138,8 +138,9 @@ $config->features->checkClient = true;
/* 文件上传设置。 Upload settings. */
$config->file = new stdclass();
$config->file->dangers = 'php,php3,php4,phtml,php5,jsp,py,rb,asp,aspx,ashx,asa,cer,cdx,aspl,shtm,shtml,html,htm';
$config->file->allowed = 'txt,doc,docx,dot,wps,wri,pdf,ppt,pptx,xls,xlsx,ett,xlt,xlsm,csv,jpg,jpeg,png,psd,gif,ico,bmp,swf,avi,rmvb,rm,mp3,mp4,3gp,flv,mov,movie,rar,zip,bz,bz2,tar,gz,mpp,rp,pdm,vsdx,vsd,sql';
$config->file->dangers = 'php,php3,php4,phtml,php5,jsp,py,rb,asp,aspx,ashx,asa,cer,cdx,aspl,shtm,shtml,html,htm';
$config->file->allowed = 'txt,doc,docx,dot,wps,wri,pdf,ppt,pptx,xls,xlsx,ett,xlt,xlsm,csv,jpg,jpeg,png,psd,gif,ico,bmp,swf,avi,rmvb,rm,mp3,mp4,3gp,flv,mov,movie,rar,zip,bz,bz2,tar,gz,mpp,rp,pdm,vsdx,vsd,sql';
$config->file->storageType = 'fs'; // fs or s3
/* Upload settings. */
$config->allowedTags = '<p><span><h1><h2><h3><h4><h5><em><u><strong><br><ol><ul><li><img><a><b><font><hr><pre><div><table><td><th><tr><tbody><embed><style>';
-24
View File
@@ -228,30 +228,6 @@ class helper extends baseHelper
$version
);
}
/**
* Save file to storage: fs(www/data/upload) or s3(s3, oss, minio)
*
* @param string $tmpFile
* @param string $fileName
* @access public
* @return bool
*/
public static function saveFile($tmpFile, $filePath)
{
global $config;
if(!isset($config->storageType) or $config->storageType == 'fs')
{
return move_uploaded_file($tmpFile, $filePath);
}
else if(isset($config->storageType) and $config->storageType == 's3')
{
return move_uploaded_file($tmpFile, $filePath); // TODO
}
return false;
}
}
/**
+16 -6
View File
@@ -885,16 +885,18 @@ class baseJS
* 显示一个确认框,点击确定跳转到$okURL,点击取消跳转到$cancelURL。
* show a confirm box, press ok go to okURL, else go to cancleURL.
*
* @param string $message 显示的内容。 the text to be showed.
* @param string $okURL 点击确定后跳转的地址。 the url to go to when press 'ok'.
* @param string $cancleURL 点击取消后跳转的地址。 the url to go to when press 'cancle'.
* @param string $okTarget 点击确定后跳转的target。 the target to go to when press 'ok'.
* @param string $cancleTarget 点击取消后跳转的target。 the target to go to when press 'cancle'.
* @param string $message 显示的内容。 the text to be showed.
* @param string $okURL 点击确定后跳转的地址。 the url to go to when press 'ok'.
* @param string $cancleURL 点击取消后跳转的地址。 the url to go to when press 'cancle'.
* @param string $okTarget 点击确定后跳转的target。 the target to go to when press 'ok'.
* @param string $cancleTarget 点击取消后跳转的target。 the target to go to when press 'cancle'.
* @param string $okOpenApp 点击确定后跳转的应用。 the app to go to when press 'ok'.
* @param string $cancleOpenApp 点击取消后跳转的应用。 the app to go to when press 'cancle'.
* @static
* @access public
* @return string
*/
static public function confirm($message = '', $okURL = '', $cancleURL = '', $okTarget = "self", $cancleTarget = "self")
static public function confirm($message = '', $okURL = '', $cancleURL = '', $okTarget = "self", $cancleTarget = "self", $okOpenApp = '', $cancleOpenApp = '')
{
global $app;
if($app->viewType == 'json')
@@ -921,6 +923,10 @@ class baseJS
{
$confirmAction = "history.back(-1);";
}
elseif(strpos($okTarget, '$.apps.open') !== false)
{
$confirmAction = "$okTarget('$okURL', '$okOpenApp');";
}
elseif(!empty($okURL))
{
$confirmAction = "$okTarget.location = '$okURL';";
@@ -931,6 +937,10 @@ class baseJS
{
$cancleAction = "history.back(-1);";
}
elseif(strpos($cancleTarget, '$.apps.open') !== false)
{
$cancleAction = "$cancleTarget('$cancleURL', '$cancleOpenApp');";
}
elseif(!empty($cancleURL))
{
$cancleAction = "$cancleTarget.location = '$cancleURL';";
+1 -1
View File
@@ -63,7 +63,7 @@
<?php if($i == 0):?>
<td <?php if($rowspan > 1) echo "rowspan='$rowspan'"?>><?php echo date(DT_DATETIME1, $backupFile->time);?></td>
<?php endif;?>
<td class='text-left' style='padding-left:5px;'><?php echo $file;?></td>
<td title=<?php echo $file;?> class='text-left' style='padding-left:5px;'><?php echo $file;?></td>
<td><?php echo zget($summary, 'allCount', '');?></td>
<td><?php echo zget($summary, 'count', '');?></td>
<td>
+3 -3
View File
@@ -61,7 +61,7 @@ class bug extends control
}
else
{
$products = $this->product->getPairs();
$products = $this->product->getPairs('', 0, 'program_asc');
}
$this->view->products = $this->products = $products;
@@ -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;
@@ -514,7 +514,7 @@ class bug extends control
if(empty($moduleOptionMenu)) die(js::locate(helper::createLink('tree', 'browse', "productID=$productID&view=story")));
/* Get products and projects. */
$products = $this->config->CRProduct ? $this->products : $this->product->getPairs('noclosed');
$products = $this->config->CRProduct ? $this->products : $this->product->getPairs('noclosed', 0, 'program_asc');
$projects = array(0 => '');
if($projectID)
{
+1 -1
View File
@@ -240,7 +240,7 @@
<table class='table table-data'>
<tbody>
<tr>
<th class='w-60px'><?php echo $lang->bug->execution;?></th>
<th class='w-70px'><?php echo $lang->bug->execution;?></th>
<td><?php if($bug->execution) echo html::a($this->createLink('execution', 'browse', "executionid=$bug->execution"), $bug->executionName);?></td>
</tr>
<tr class='nofixed'>
+1 -1
View File
@@ -505,7 +505,7 @@ class caselib extends control
$file = $file[0];
$fileName = $this->file->savePath . $this->file->getSaveName($file['pathname']);
helper::saveFile($file['tmpname'], $fileName);
move_uploaded_file($file['tmpname'], $fileName);
$rows = $this->file->parseCSV($fileName);
$fields = $this->testcase->getImportFields($productID);
+1 -1
View File
@@ -43,7 +43,7 @@
</tr>
<tr>
<th><?php echo $lang->doclib->control;?></th>
<?php if($lib->type == 'product' or $lib->type == 'execution' or ($config->systemMode == 'classic' and $lib->type != 'custom')):?>
<?php if($lib->type == 'product' or $lib->type == 'execution'):?>
<td>
<?php echo html::radio('acl', $lang->doclib->aclListA, $lib->acl, "onchange='toggleAcl(this.value, \"lib\")'")?>
<span class='text-info' id='noticeAcl'><?php echo $lang->doc->noticeAcl['lib'][$lib->type][$lib->acl];?></span>
+1 -1
View File
@@ -2127,7 +2127,7 @@ class executionModel extends model
$this->loadModel('story')->setStage($storyID);
$this->unlinkCases($executionID, $storyID);
$objectType = $executionID == $this->session->project ? unlinkedfromproject : unlinkedfromexecution;
$objectType = $executionID == $this->session->project ? 'unlinkedfromproject' : 'unlinkedfromexecution';
$this->loadModel('action')->create('story', $storyID, $objectType, '', $executionID);
$tasks = $this->dao->select('id')->from(TABLE_TASK)->where('story')->eq($storyID)->andWhere('execution')->eq($executionID)->andWhere('status')->in('wait,doing')->fetchPairs('id');
+2 -1
View File
@@ -431,7 +431,7 @@ class extension extends control
$tmpName = $_FILES['file']['tmp_name'];
$fileName = $_FILES['file']['name'];
$dest = $this->app->getTmpRoot() . "/extension/$fileName";
helper::saveFile($tmpName, $dest);
move_uploaded_file($tmpName, $dest);
$extension = basename($fileName, '.zip');
$return = $this->extension->extractPackage($extension);
@@ -455,6 +455,7 @@ class extension extends control
$link = $type == 'install' ? inlink('install', "extension=$extension") : inlink('upgrade', "extension=$extension");
die(js::locate($link, 'parent'));
}
$this->display();
}
+2 -2
View File
@@ -97,7 +97,7 @@ class fileModel extends model
foreach($files as $id => $file)
{
if($file['size'] == 0) continue;
if(!helper::saveFile($file['tmpname'], $this->savePath . $this->getSaveName($file['pathname']))) return false;
if(!move_uploaded_file($file['tmpname'], $this->savePath . $this->getSaveName($file['pathname']))) return false;
$file = $this->compressImage($file);
@@ -470,7 +470,7 @@ class fileModel extends model
$filePath = $this->dao->select('pathname')->from(TABLE_FILE)->where('id')->eq($fileID)->fetch();
$pathName = $filePath->pathname;
$realPathName = $this->savePath . $this->getRealPathName($pathName);
if(!is_dir(dirname($realPathName)))mkdir(dirname($realPathName));
if(!is_dir(dirname($realPathName))) mkdir(dirname($realPathName));
helper::saveFile($file['tmpname'], $realPathName);
$file['pathname'] = $pathName;
+2 -1
View File
@@ -17,8 +17,9 @@ $sessionString .= session_name() . '=' . session_id();
function deleteFile(fileID)
{
if(!fileID) return;
hiddenwin.location.href =createLink('file', 'delete', 'fileID=' + fileID);
hiddenwin.location.href = createLink('file', 'delete', 'fileID=' + fileID);
}
/* Download a file, append the mouse to the link. Thus we call decide to open the file in browser no download it. */
function downloadFile(fileID, extension, imageWidth, fileTitle)
{
-1
View File
@@ -56,7 +56,6 @@ js::set('defaultOpen', $open);
<li id='menuToggleMenu'>
<a type='button' class='menu-toggle'>
<i class='icon icon-sm icon-menu-collapse'></i>
<i class='icon icon-sm icon-menu-unfold'></i>
</a>
</li>
</ul>
+2 -1
View File
@@ -40,7 +40,8 @@ $lang->product->plans = 'Plan';
$lang->product->releases = 'Release';
$lang->product->docs = 'Dok';
$lang->product->bugs = 'Verknüpfte Bugs';
$lang->product->projects = "Verknüpfte {$lang->executionCommon}";
$lang->product->projects = "Linked Project";
$lang->product->executions = "Verknüpfte {$lang->execution->common}";
$lang->product->cases = 'Fälle';
$lang->product->builds = 'Builds';
$lang->product->roadmap = 'Roadmap';
+2 -1
View File
@@ -44,7 +44,8 @@ $lang->product->plans = 'Plans';
$lang->product->releases = 'Releases';
$lang->product->docs = 'Doc';
$lang->product->bugs = 'Linked Bug';
$lang->product->projects = "Linked {$lang->executionCommon}";
$lang->product->projects = "Linked Project";
$lang->product->executions = "Linked {$lang->execution->common}";
$lang->product->cases = 'Case';
$lang->product->builds = 'Build';
$lang->product->roadmap = "{$lang->productCommon} Roadmap";
+2 -1
View File
@@ -40,7 +40,8 @@ $lang->product->plans = 'Plans';
$lang->product->releases = 'Releases';
$lang->product->docs = 'Doc';
$lang->product->bugs = 'Bug Liés';
$lang->product->projects = "{$lang->executionCommon}s Liés";
$lang->product->projects = "Linked Project";
$lang->product->executions = "{$lang->execution->common}s Liés";
$lang->product->cases = 'CasTests';
$lang->product->builds = 'Build';
$lang->product->roadmap = "Roadmap {$lang->productCommon}";
+2 -1
View File
@@ -40,7 +40,8 @@ $lang->product->plans = 'Kế hoạch';
$lang->product->releases = 'Phát hành';
$lang->product->docs = 'Tài liệu';
$lang->product->bugs = 'Bug liên kết';
$lang->product->projects = "{$lang->executionCommon} liên kết";
$lang->product->projects = "Linked Project";
$lang->product->executions = "{$lang->execution->common} liên kết";
$lang->product->cases = 'Tình huống';
$lang->product->builds = 'Bản dựng';
$lang->product->roadmap = "Lộ trình {$lang->productCommon}";
+2 -1
View File
@@ -44,7 +44,8 @@ $lang->product->plans = "计划数";
$lang->product->releases = '发布数';
$lang->product->docs = '文档数';
$lang->product->bugs = '相关Bug';
$lang->product->projects = "关联{$lang->executionCommon}数";
$lang->product->projects = "关联项目数";
$lang->product->executions = "关联{$lang->execution->common}数";
$lang->product->cases = '用例数';
$lang->product->builds = '版本数';
$lang->product->roadmap = "{$lang->productCommon}路线图";
+44 -20
View File
@@ -261,21 +261,36 @@ class productModel extends model
*
* @param string $mode
* @param string $programID
* @param string $orderBy program_asc
* @return array
*/
public function getPairs($mode = '', $programID = 0)
public function getPairs($mode = '', $programID = 0, $orderBy = '')
{
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getProductPairs();
$orderBy = !empty($this->config->product->orderBy) ? $this->config->product->orderBy : 'isClosed';
$products = $this->dao->select('*, IF(INSTR(" closed", status) < 2, 0, 1) AS isClosed')
->from(TABLE_PRODUCT)
->where('deleted')->eq(0)
->beginIF($programID)->andWhere('program')->eq($programID)->fi()
->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('status')->ne('closed')->fi()
->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->products)->fi()
->orderBy($orderBy)
->fetchPairs('id', 'name');
if($orderBy == 'program_asc')
{
$products = $this->dao->select('t1.id as id, t1.name as name, t1.*, IF(INSTR(" closed", t1.status) < 2, 0, 1) AS isClosed')->from(TABLE_PRODUCT)->alias('t1')
->leftJoin(TABLE_PROGRAM)->alias('t2')->on('t1.program = t2.id')
->where('t1.deleted')->eq(0)
->beginIF($programID)->andWhere('t1.program')->eq($programID)->fi()
->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('t1.status')->ne('closed')->fi()
->beginIF(!$this->app->user->admin)->andWhere('t1.id')->in($this->app->user->view->products)->fi()
->orderBy('t2.order_asc, t1.line_desc, t1.order_desc')
->fetchPairs('id', 'name');
}
else
{
$orderBy = !empty($this->config->product->orderBy) ? $this->config->product->orderBy : 'isClosed';
$products = $this->dao->select('*, IF(INSTR(" closed", status) < 2, 0, 1) AS isClosed')
->from(TABLE_PRODUCT)
->where('deleted')->eq(0)
->beginIF($programID)->andWhere('program')->eq($programID)->fi()
->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('status')->ne('closed')->fi()
->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->products)->fi()
->orderBy($orderBy)
->fetchPairs('id', 'name');
}
return $products;
}
@@ -1257,16 +1272,25 @@ class productModel extends model
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
->where('t2.deleted')->eq(0)
->andWhere('t1.product')->eq($productID)
->andWhere('t2.type')->eq('project')
->fetch();
$product->stories = $stories;
$product->plans = $plans ? $plans->count : 0;
$product->releases = $releases ? $releases->count : 0;
$product->builds = $builds ? $builds->count : 0;
$product->cases = $cases ? $cases->count : 0;
$product->projects = $projects ? $projects->count : 0;
$product->bugs = $bugs ? $bugs->count : 0;
$product->docs = $docs ? $docs->count : 0;
$executions = $this->dao->select('count("t1.*") AS count')->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
->where('t2.deleted')->eq(0)
->andWhere('t1.product')->eq($productID)
->andWhere('t2.type')->in('sprint,stage')
->fetch();
$product->stories = $stories;
$product->plans = $plans ? $plans->count : 0;
$product->releases = $releases ? $releases->count : 0;
$product->builds = $builds ? $builds->count : 0;
$product->cases = $cases ? $cases->count : 0;
$product->projects = $projects ? $projects->count : 0;
$product->executions = $executions ? $executions->count : 0;
$product->bugs = $bugs ? $bugs->count : 0;
$product->docs = $docs ? $docs->count : 0;
return $product;
}
@@ -1540,7 +1564,7 @@ class productModel extends model
public function getProductLink($module, $method, $extra, $branch = false)
{
$link = '';
if(strpos('programplan,product,roadmap,bug,testcase,testtask,story,qa,testsuite,testreport,build,projectrelease,projectstory', ',' . $module . ',') !== false)
if(strpos(',programplan,product,roadmap,bug,testcase,testtask,story,qa,testsuite,testreport,build,projectrelease,projectstory,', ',' . $module . ',') !== false)
{
if($module == 'product' && $method == 'project')
{
@@ -1569,7 +1593,7 @@ class productModel extends model
elseif($module == 'programplan')
{
$extra = $extra ? $extra : 'gantt';
$link = helper::createLink($module, 'browse', "projectID=%s&productID=%s&type=$extra" . ($branch ? "&branch=%s" : ''));
$link = helper::createLink($module, 'browse', "projectID=%s&productID=%s&type=$extra");
}
elseif($module == 'story' && $method == 'report')
{
+3 -2
View File
@@ -40,7 +40,7 @@
<th class='w-80px'><?php echo $lang->project->begin;?></th>
<th class='w-80px'><?php echo $lang->project->end;?></th>
<th class='w-70px'><?php echo $lang->project->status;?></th>
<th class="w-70px"><?php echo $lang->project->budget;?></th>
<th class="w-80px text-center"><?php echo $lang->project->budget;?></th>
<th class="w-60px text-center"><?php echo $lang->project->estimate;?></th>
<th class="w-60px text-center"><?php echo $lang->project->consume;?></th>
<th class='w-50px'><?php echo $lang->project->progress;?></th>
@@ -78,7 +78,8 @@
</td>
<?php $projectBudget = in_array($this->app->getClientLang(), ['zh-cn','zh-tw']) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2);?>
<?php $budgetTitle = $project->budget != 0 ? zget($this->lang->project->currencySymbol, $project->budgetUnit) . ' ' . $projectBudget : $this->lang->project->future;?>
<td title='<?php echo $budgetTitle;?>' class='text-ellipsis text-right padding-right'><?php echo $budgetTitle;?></td>
<?php $textStyle = $project->budget != 0 ? 'text-right' : 'text-center';?>
<td title='<?php echo $budgetTitle;?>' class="text-ellipsis <?php echo $textStyle;?>"><?php echo $budgetTitle;?></td>
<td class="text-right padding-right" title="<?php echo $project->hours->totalEstimate . ' ' . $lang->execution->workHour;?>"><?php echo $project->hours->totalEstimate . $lang->execution->workHourUnit;?></td>
<td class="text-right padding-right" title="<?php echo $project->hours->totalConsumed . ' ' . $lang->execution->workHour;?>"><?php echo $project->hours->totalConsumed . $lang->execution->workHourUnit;?></td>
<td class='padding-right text-center'>
+8 -4
View File
@@ -114,8 +114,8 @@
<tr>
<th><?php echo $lang->story->statusList['changed'] . $space . $lang->story->common;?></th>
<td><strong><?php echo $product->stories['changed']?></strong></td>
<th><?php echo $lang->product->projects?></th>
<td><strong><?php echo $product->projects?></strong></td>
<th><?php echo $lang->product->releases?></th>
<td><strong><?php echo $product->releases?></strong></td>
<th><?php echo $lang->product->cases?></th>
<td><strong><?php echo $product->cases?></strong></td>
</tr>
@@ -130,8 +130,12 @@
<tr>
<th><?php echo $lang->story->statusList['closed'] . $space . $lang->story->common;?></th>
<td><strong><?php echo $product->stories['closed']?></strong></td>
<th><?php echo $lang->product->releases?></th>
<td><strong><?php echo $product->releases?></strong></td>
<?php if($config->systemMode == 'new'):?>
<th><?php echo $lang->product->projects?></th>
<td><strong><?php echo $product->projects?></strong></td>
<?php endif;?>
<th><?php echo $lang->product->executions?></th>
<td><strong><?php echo $product->executions?></strong></td>
</tr>
</tbody>
</table>
+1 -1
View File
@@ -20,7 +20,7 @@ $typeInfo = $type == 'file' ? '&type=file' : '';
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
<?php $browseLink = $app->session->revisionList != false ? $app->session->revisionList : $this->repo->createLink('browse', "repoID={$repoID}&branchID=$branchID&objectID=$objectID{$preDir}");?>
<?php echo html::a($browseLink, "<i class='icon icon-back'></i>" . $lang->goback, '', "class='btn btn-link' data-app='{$app->openApp}'");?>
<?php echo html::a($browseLink, "<i class='icon icon-back'></i>" . $lang->goback, '', "class='btn btn-link'");?>
<div class="divider"></div>
<div class="page-title">
<?php echo $lang->repo->revisionA . ' ' . ($repo->SCM == 'Subversion' ? $revision : $this->repo->getGitRevisionName($revision, $log->commit));?>
+1 -1
View File
@@ -1523,7 +1523,7 @@ class testcase extends control
$file = $file[0];
$fileName = $this->file->savePath . $this->file->getSaveName($file['pathname']);
helper::saveFile($file['tmpname'], $fileName);
move_uploaded_file($file['tmpname'], $fileName);
$rows = $this->file->parseCSV($fileName);
$fields = $this->testcase->getImportFields($productID);
+4 -1
View File
@@ -11,6 +11,7 @@
*/
?>
<?php include '../../common/view/header.lite.html.php';?>
<?php js::set('openApp', $app->openApp);?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2><?php echo $lang->testcase->createBug;?></h2>
@@ -30,7 +31,9 @@ function createBug(obj)
var onlybody = config.onlybody;
config.onlybody = 'no';
window.open(createLink('bug', 'create', params + ',stepIdList=' + stepIdList), '_parent');
var link = createLink('bug', 'create', params + ',stepIdList=' + stepIdList);
if(openApp == 'my') window.parent.$.apps.open(link, 'qa')
window.open(link, '_parent');
config.onlybody = onlybody;
}
+12
View File
@@ -260,6 +260,18 @@ class testreport extends control
die(js::locate('back'));
}
if($this->app->openApp == 'qa')
{
$productID = $this->product->saveState(key($productIdList), $this->products);
$this->loadModel('qa')->setMenu($this->products, $productID);
}
elseif($this->app->openApp == 'project')
{
$projects = $this->project->getPairsByProgram();
$projectID = $this->project->saveState($execution->project, $projects);
$this->project->setMenu($projectID);
}
$builds = $this->build->getByList($buildIdList);
$stories = !empty($builds) ? $this->testreport->getStories4Test($builds) : $this->story->getExecutionStories($execution->id);;
+2 -1
View File
@@ -116,7 +116,8 @@
<?php
if(common::canBeChanged('report', $report))
{
if(common::hasPriv('testreport', 'create')) echo html::a(inLink('create', "objectID=$report->objectID&objectType=$report->objectType&extra=$report->id"), "<i class='icon-refresh'></i>", '', "class='btn' title='{$lang->testreport->recreate}' data-app='{$this->app->openApp}'");
$extra = $report->objectType == 'execution' ? "&extra=$report->tasks" : '';
if(common::hasPriv('testreport', 'create')) echo html::a(inLink('create', "objectID=$report->objectID&objectType=$report->objectType" . $extra), "<i class='icon-refresh'></i>", '', "class='btn' title='{$lang->testreport->recreate}' data-app='{$this->app->openApp}'");
common::printIcon('testreport', 'edit', "reportID=$report->id", '', 'button');
common::printIcon('testreport', 'delete', "reportID=$report->id", '', 'button', 'trash', 'hiddenwin');
}
+1 -1
View File
@@ -1628,7 +1628,7 @@ class testtaskModel extends model
$file = $file[0];
$fileName = $this->file->savePath . $this->file->getSaveName($file['pathname']);
helper::saveFile($file['tmpname'], $fileName);
move_uploaded_file($file['tmpname'], $fileName);
if(simplexml_load_file($fileName) === false)
{
dao::$errors[] = $this->lang->testtask->cannotBeParsed;
+8 -2
View File
@@ -279,8 +279,11 @@ class todo extends control
{
$confirmNote = 'confirm' . ucfirst($todo->type);
$confirmURL = $this->createLink($todo->type, 'view', "id=$todo->idvalue");
if($todo->type == 'bug') $app = 'qa';
if($todo->type == 'task') $app = 'execution';
if($todo->type == 'story') $app = 'product';
$cancelURL = $this->server->HTTP_REFERER;
die(js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->idvalue), $confirmURL, $cancelURL, 'parent', 'parent'));
die(js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->idvalue), $confirmURL, $cancelURL, 'window.parent.$.apps.open', 'parent', $app));
}
if(isonlybody())die(js::reload('parent.parent'));
die(js::reload('parent'));
@@ -446,8 +449,11 @@ class todo extends control
{
$confirmNote = 'confirm' . ucfirst($todo->type);
$confirmURL = $this->createLink($todo->type, 'view', "id=$todo->idvalue");
if($todo->type == 'bug') $app = 'qa';
if($todo->type == 'task') $app = 'execution';
if($todo->type == 'story') $app = 'product';
$cancelURL = $this->server->HTTP_REFERER;
die(js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->idvalue), $confirmURL, $cancelURL, 'parent', 'parent'));
die(js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->idvalue), $confirmURL, $cancelURL, 'window.parent.$.apps.open', 'parent', $app));
}
if(isonlybody())die(js::reload('parent.parent'));
die(js::reload('parent'));
+1 -1
View File
@@ -4304,7 +4304,7 @@ class upgradeModel extends model
$lib->name = $this->lang->doclib->main['project'];
$lib->type = 'project';
$lib->main = '1';
$lib->acl = 'default';
$lib->acl = $project->acl;
$this->dao->insert(TABLE_DOCLIB)->data($lib)->exec();
$this->loadModel('action')->create('project', $projectID, 'openedbysystem');
+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
*/
+58 -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,65 @@
* @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";
function run($result)
{
global $_result;
$_result = $result;
return true;
}
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";
}
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: ""