This commit is contained in:
lanzongjun
2023-04-27 18:15:44 +08:00
17 changed files with 262 additions and 124 deletions
+2 -2
View File
@@ -338,12 +338,12 @@ class blockModel extends model
*/
public function update(object $formData): int|false
{
$this->dao->update(TABLE_BLOCK)->data($formData)->exec();
$this->dao->update(TABLE_BLOCK)->data($formData)->autoCheck()->exec();
if(dao::isError()) return false;
$this->loadModel('score')->create('block', 'set');
return $formData->id;
return (int)$formData->id;
}
/**
+16
View File
@@ -23,6 +23,22 @@ class blockTest
return $blockID;
}
/**
* Update a block.
*
* @param object $block
* @access public
* @return int|false
*/
public function updateTest($block)
{
$blockID = $this->objectModel->update($block);
if(dao::isError()) return dao::getError();
return $blockID;
}
/**
* Test save params.
*
+15 -1
View File
@@ -4,6 +4,18 @@ include dirname(__FILE__, 5) . "/test/lib/init.php";
include dirname(__FILE__, 2) . '/block.class.php';
su('admin');
function initData()
{
$config = zdTable('config');
$config->id->range('1');
$config->owner->range('system');
$config->module->range('sso');
$config->key->range('key');
$config->value->range('858640a724c2c981983935eb2bbc4ad8');
$config->gen(1);
}
/**
title=测试 blockModel->checkAPI();
@@ -14,7 +26,9 @@ pid=1
测试正确的哈希值 >> 1
测试错误的哈希值 >> 0
*/
*/
initData();
$block = new blockTest();
+1 -1
View File
@@ -68,4 +68,4 @@ $blockTest = new blockTest();
$newBlockID = $blockTest->createTest($block);
r($tester->block->getByID($newBlockID)) && p('account,vision,module,title,source,block,order') && e('admin,rnd,my,区块123,my,bug,5'); // 测试获取正常的block的内容
r($blockTest->createTest($accoutTooLangBlock)) && p('account:0') && e('『所属用户』长度应当不超过『30』,且大于『0』。'); // 测试account 字段字符超出长度
r($blockTest->createTest($accoutTooLangBlock)) && p('account:0') && e('『所属用户』长度应当不超过『30』,且大于『0』。'); // 测试account 字段字符超出长度
+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . "/test/lib/init.php";
include dirname(__FILE__, 2) . '/block.class.php';
su('admin');
function initData()
{
$block = zdTable('block');
$block->id->range('2');
$block->account->range('test');
$block->vision->range('rnd');
$block->module->range('test');
$block->title->prefix('区块')->range('2');
$block->source->range('my');
$block->block->range('bug');
$block->order->range('5');
$block->gen(1);
}
/**
title=14:11:23 ERROR: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry &
timeout=0
cid=39
- 执行block模块的getByID方法,参数是$newBlockID
- 属性account @admin
- 属性vision @rnd
- 属性module @my
- 属性title @区块123
- 属性source @my
- 属性block @bug
- 属性order @5
- 执行blockTest模块的create方法,参数是$accoutTooLangBlock,属性account @『所属用户』长度应当不超过『30』,且大于『0』。
*/
global $tester;
$tester->loadModel('block');
initData();
$newBlock = new stdclass();
$newBlock->id = '2';
$newBlock->account = 'newadmin';
$newBlock->vision = 'lite';
$newBlock->module = 'newmy';
$newBlock->title = 'new区块';
$newBlock->source = 'newmy';
$newBlock->params = '';
$newBlock->block = 'newbug';
$newBlock->order = '5';
$accoutTooLangBlock = new stdclass();
$accoutTooLangBlock->id = '2';
$accoutTooLangBlock->account = 'adminadminadminadminadminadminadminadmin1';
$accoutTooLangBlock->vision = 'rnd';
$accoutTooLangBlock->module = 'my';
$accoutTooLangBlock->title = 'long account';
$accoutTooLangBlock->source = 'my';
$accoutTooLangBlock->block = 'bug';
$accoutTooLangBlock->order = '5';
$blockTest = new blockTest();
$newBlockID = $blockTest->updateTest($newBlock);
r($tester->block->getByID($newBlockID)) && p('account,vision,module,title,source,block,order') && e("{$newBlock->account},{$newBlock->vision},{$newBlock->module},{$newBlock->title},{$newBlock->source},{$newBlock->block},{$newBlock->order}"); // 测试获取正常的block的内容
r($blockTest->updateTest($accoutTooLangBlock)) && p('account:0') && e('『所属用户』长度应当不超过『30』,且大于『0』。'); // 测试account 字段字符超出长度
+2
View File
@@ -318,3 +318,5 @@ $config->product->statisticFields['plans'] = array('plans');
$config->product->statisticFields['releases'] = array('releases');
$config->product->skipRedirectMethod = ',create,index,showerrornone,ajaxgetdropmenu,kanban,all,manageline,export,ajaxgetplans,';
include dirname(__FILE__) . DS . 'config' . DS . 'form.php';
+18
View File
@@ -0,0 +1,18 @@
<?php
global $lang;
$config->product->form = new stdclass();
$config->product->form->create = array();
$config->product->form->create['program'] = array('type' => 'int', 'control' => 'select', 'required' => false, 'options' => array());
$config->product->form->create['line'] = array('type' => 'int', 'control' => 'select', 'required' => false, 'default' => 0, 'options' => array());
$config->product->form->create['lineName'] = array('type' => 'string', 'control' => 'input', 'required' => false, 'filter' => 'trim');
$config->product->form->create['name'] = array('type' => 'string', 'control' => 'input', 'required' => true, 'filter' => 'trim');
$config->product->form->create['code'] = array('type' => 'string', 'control' => 'input', 'required' => true, 'filter' => 'trim');
$config->product->form->create['PO'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'options' => '');
$config->product->form->create['QD'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'options' => '');
$config->product->form->create['RD'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'options' => '');
$config->product->form->create['reviewer'] = array('type' => 'string', 'control' => 'multi-select', 'required' => false, 'options' => 'users');
$config->product->form->create['type'] = array('type' => 'string', 'control' => 'select', 'required' => false, 'default' => 'normal', 'options' => $lang->product->typeList);
$config->product->form->create['status'] = array('type' => 'string', 'control' => 'hidden', 'required' => false, 'default' => 'normal');
$config->product->form->create['desc'] = array('type' => 'string', 'control' => 'textarea', 'required' => false);
$config->product->form->create['acl'] = array('type' => 'string', 'control' => 'acl', 'required' => false, 'default' => 'private', 'options' => $lang->product->aclList);
$config->product->form->create['whitelist'] = array('type' => 'string', 'control' => 'multi-select', 'required' => false, 'options' => 'users');
+14 -52
View File
@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* The control file of product module of ZenTaoPMS.
*
@@ -393,6 +394,7 @@ class product extends control
}
/**
* 创建产品。可以是顶级产品,也可以是项目集下的产品。
* Create a product.
*
* @param int $programID
@@ -400,10 +402,19 @@ class product extends control
* @access public
* @return void
*/
public function create($programID = 0, $extra = '')
public function create(string $programID = '0', string $extra = '')
{
$programID = (int)$programID;
if(!empty($_POST))
{
$data = form::data($this->config->product->form->create);
$data = $this->productZen->prepareCreateExtras($data);
if(!$data) return $this->productZen->errorBeforeEdit();
$result = $this->product->create($data);
if(!$result) return $this->productZen->errorAfterEdit();
return $this->productZen->responseAfterEdit($result);
$productID = $this->product->create();
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->loadModel('action')->create('product', $productID, 'opened');
@@ -421,57 +432,8 @@ class product extends control
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $locate));
}
if($this->app->tab == 'program') $this->loadModel('program')->setMenu($programID);
if($this->app->getViewType() == 'mhtml')
{
if($this->app->rawModule == 'projectstory' and $this->app->rawMethod == 'story')
{
$this->loadModel('project')->setMenu();
}
else
{
$this->product->setMenu('');
}
}
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
$this->loadModel('user');
$poUsers = $this->user->getPairs('nodeleted|pofirst|noclosed', '', $this->config->maxCount);
if(!empty($this->config->user->moreLink)) $this->config->moreLinks["PO"] = $this->config->user->moreLink;
$qdUsers = $this->user->getPairs('nodeleted|qdfirst|noclosed', '', $this->config->maxCount);
if(!empty($this->config->user->moreLink)) $this->config->moreLinks["QD"] = $this->config->user->moreLink;
$rdUsers = $this->user->getPairs('nodeleted|devfirst|noclosed', '', $this->config->maxCount);
if(!empty($this->config->user->moreLink)) $this->config->moreLinks["RD"] = $this->config->user->moreLink;
$lines = array();
if($programID and $this->config->systemMode == 'ALM') $lines = array('') + $this->product->getLinePairs($programID);
if($this->app->tab == 'doc') unset($this->lang->doc->menu->product['subMenu']);
$gobackLink = '';
if(isset($output['from']) and $output['from'] == 'qa') $gobackLink = $this->createLink('qa', 'index');
if(isset($output['from']) and $output['from'] == 'global') $gobackLink = $this->createLink('product', 'all');
$this->view->title = $this->lang->product->create;
$this->view->position[] = $this->view->title;
$this->view->gobackLink = $gobackLink;
$this->view->groups = $this->loadModel('group')->getPairs();
$this->view->programID = $programID;
$this->view->poUsers = $poUsers;
$this->view->qdUsers = $qdUsers;
$this->view->rdUsers = $rdUsers;
$this->view->fields = $this->product->buildFormFields($this->config->product->create->fields);
$this->view->users = $this->user->getPairs('nodeleted|noclosed');
$this->view->programs = array('') + $this->loadModel('program')->getTopPairs('', 'noclosed');
$this->view->lines = $lines;
$this->view->URSRPairs = $this->loadModel('custom')->getURSRPairs();
unset($this->lang->product->typeList['']);
$this->display();
$this->productZen->setMenu4Create($programID);
$this->productZen->buildCreateForm($programID, $extra);
}
/**
+6 -40
View File
@@ -1095,41 +1095,6 @@ class productModel extends model
return $this->loadModel('story')->batchGetStoryStage($storyIdList);
}
/**
* Build form fields.
*
* @param array $fields
* @param object $project
* @access public
* @return void
*/
public function buildFormFields($fields, $product = null)
{
$this->loadModel('user');
$poUsers = $this->user->getPairs('nodeleted|pofirst|noclosed', '', $this->config->maxCount);
$qdUsers = $this->user->getPairs('nodeleted|qdfirst|noclosed', '', $this->config->maxCount);
$rdUsers = $this->user->getPairs('nodeleted|devfirst|noclosed', '', $this->config->maxCount);
$users = $this->user->getPairs('nodeleted|noclosed');
foreach($fields as $field => $attr)
{
if(isset($attr['options']) and $attr['options'] == 'users') $fields[$field]['options'] = $users;
$fields[$field]['name'] = $field;
$fields[$field]['title'] = $this->lang->product->$field;
if($product and isset($product->$field)) $fields[$field]['default'] = $product->$field;
}
$fields['program']['options'] = array('') + $this->loadModel('program')->getTopPairs('', 'noclosed');
$fields['PO']['options'] = $poUsers;
$fields['QD']['options'] = $qdUsers;
$fields['RD']['options'] = $rdUsers;
if($product and $product->program)$fields['line']['options'] = array('') + $this->getLinePairs($product->program);
if(empty($product->program) or $this->config->systemMode != 'ALM') unset($fields['line']);
return $fields;
}
/**
* Build search form.
*
@@ -2035,15 +2000,16 @@ class productModel extends model
*
* @param int $programID
* @access public
* @return array
* @return int[]
*/
public function getLinePairs($programID = 0)
public function getLinePairs(int $programID = 0): array
{
if($programID <= 0) return array();
return $this->dao->select('id,name')->from(TABLE_MODULE)
->where('type')->eq('line')
->beginIF($programID)->andWhere('root')->eq($programID)->fi()
->andWhere('root')->eq($programID)
->andWhere('deleted')->eq(0)
->fetchPairs();
->fetchPairs('id', 'name');
}
/*
@@ -2517,7 +2483,7 @@ class productModel extends model
* @access public
* @return void
*/
public function setMenu($productID, $branch = '', $module = 0, $moduleType = '', $extra = '')
public function setMenu($productID = 0, $branch = '', $module = 0, $moduleType = '', $extra = '')
{
if(!$this->app->user->admin and strpos(",{$this->app->user->view->products},", ",$productID,") === false and $productID != 0 and !defined('TUTORIAL')) return $this->accessDenied($this->lang->product->accessDenied);
+20 -16
View File
@@ -3,28 +3,32 @@
include dirname(__FILE__, 5) . "/test/lib/init.php";
include dirname(__FILE__, 2) . '/product.class.php';
function initData()
{
$module = zdTable('module');
$module->id->range('1-1000');
$module->root->range('1-5'); //产品线所属项目集
$module->name->prefix("产品线")->range('1-1000');
$module->type->range("line");
$module->parent->range("0");
$module->gen(10);
}
initData();
/**
title=productModel->getLinePairs();
cid=1
pid=1
测试获取程序集1的信息 >> 产品线1,产品线11
测试获取程序集2的信息 >> 产品线2,产品线12
测试获取程序集3的信息 >> 产品线3,产品线13
测试获取程序集4的信息 >> 产品线4,产品线14
测试获取程序集5的信息 >> 产品线5,产品线15
测试获取不存在程序集的信息 >> 0
*/
$programIDList = array('1', '2', '3', '4', '5', '1000001');
$product = new productTest('admin');
r($product->getLinePairsTest($programIDList[0])) && p('1,11') && e('产品线1,产品线11'); // 测试获取程序集1的信息
r($product->getLinePairsTest($programIDList[1])) && p('2,12') && e('产品线2,产品线12'); // 测试获取程序集2的信息
r($product->getLinePairsTest($programIDList[2])) && p('3,13') && e('产品线3,产品线13'); // 测试获取程序集3的信息
r($product->getLinePairsTest($programIDList[3])) && p('4,14') && e('产品线4,产品线14'); // 测试获取程序集4的信息
r($product->getLinePairsTest($programIDList[4])) && p('5,15') && e('产品线5,产品线15'); // 测试获取程序集5的信息
r($product->getLinePairsTest($programIDList[5])) && p('1,11') && e('0'); // 测试获取不存在程序集的信息
r($product->getLinePairsTest(-1)) && p() && e('0'); // 测试获取程序集-1的信息
r($product->getLinePairsTest(0)) && p() && e('0'); // 测试获取程序集0的信息
r($product->getLinePairsTest(1)) && p('1,6') && e('产品线1,产品线6'); // 测试获取程序集1的信息
r($product->getLinePairsTest(2)) && p('2,7') && e('产品线2,产品线7'); // 测试获取程序集2的信息
r($product->getLinePairsTest(3)) && p('3,8') && e('产品线3,产品线8'); // 测试获取程序集3的信息
r($product->getLinePairsTest(4)) && p('4,9') && e('产品线4,产品线9'); // 测试获取程序集4的信息
r($product->getLinePairsTest(10001)) && p() && e('0'); // 测试获取不存在程序集的信息
@@ -0,0 +1,56 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . "/test/lib/init.php";
include dirname(__FILE__, 2) . '/product.class.php';
function initData()
{
/* Generate product data. */
$product = zdTable('product');
$product->id->range('1000-1010');
$product->program->range('1-10');
$product->name->prefix('product_')->range('1-10');
$product->code->prefix('product_code_')->range('1-10');
$product->order->range('1-10');
$product->gen(10);
}
initData();
/**
title=productTao->getPagerProductsIn();
cid=1
pid=1
- 步骤1降序排序 @1009,10
- 步骤2不存在的数据 @0
- 步骤3升序排序 @1007,8
- 步骤4分页取2行数据 @2
*/
$productIDs = array(1007, 1008, 1009, 10000);
$product = new productTest('admin');
/* Desc. */
$result = $product->objectModel->getPagerProductsIn($productIDs, null, 'order_desc');
r(array_shift($result)) && p('id,order') && e('1009,10');
/* Not exist data. */
r(isset($result[10000])) && p('empty') && e('0');
/* Asc. */
$result = $product->objectModel->getPagerProductsIn($productIDs, null, 'order_asc');
r(array_shift($result)) && p('id,order') && e('1007,8');
/* Pager. */
global $tester;
$tester->app->loadClass('pager', true);
$tester->app->setModuleName('product');
$tester->app->setMethodName('all');
$pager = new pager(0, 2, 1);
$result = $product->objectModel->getPagerProductsIn($productIDs, $pager, 'order_desc');
r(count($result)) && p('') && e('2');
+1 -1
View File
@@ -596,7 +596,7 @@ class programModel extends model
}
$query = str_replace('`id`','t1.id', $this->session->projectQuery);
$projectList = $this->dao->select('t1.*')->from(TABLE_PROJECT)->alias('t1')
$projectList = $this->dao->select('DISTINCT t1.*')->from(TABLE_PROJECT)->alias('t1')
->leftJoin(TABLE_TEAM)->alias('t2')->on('t1.id=t2.root')
->leftJoin(TABLE_STAKEHOLDER)->alias('t3')->on('t1.id=t3.objectID')
->where('t1.deleted')->eq('0')
+28 -4
View File
@@ -10,11 +10,35 @@ title=测试 projectModel->activate();
cid=1
pid=1
激活id为4的项目
激活id为5的项目
激活id为2的项目
激活id为3的项目
*/
function initData()
{
$project = zdTable('project');
$project->id->range('2-5');
$project->project->range('2-5');
$project->name->prefix("项目")->range('2-5');
$project->code->prefix("project")->range('2-5');
$project->model->range("scrum");
$project->auth->range("[]");
$project->path->range("[]");
$project->type->range("project");
$project->grade->range("1");
$project->days->range("1");
$project->status->range("closed, suspended");
$project->desc->range("[]");
$project->budget->range("100000,200000");
$project->budgetUnit->range("CNY");
$project->percent->range("0-0");
$project->gen(2);
}
initData();
global $tester;
$tester->loadModel('project');
$project = new Project();
@@ -28,6 +52,6 @@ $data->comment = 'fgasgqasfdgasfgasg';
$data->readjustTime = 1;
$data->readjustTask = 1;
r($project->activate(1287, $data)) && p('0:field,old,new') && e('status,closed,doing');
r($project->activate(1288, $data)) && p('0:field,old,new') && e('status,suspended,doing');
r($project->activate(2, $data)) && p('0:field,old,new') && e('status,closed,doing');
r($project->activate(3, $data)) && p('0:field,old,new') && e('status,suspended,doing');
+1 -1
View File
@@ -46,4 +46,4 @@ $tester->loadModel('project');
initData();
r($tester->project->getByID(2, 'project')) && p('code,type') && e('project2,project'); //获取ID等于11的项目
r($tester->project->getByID(1, 'project')) && p('code') && e('0'); //获取不存在的项目
r($tester->project->getByID(1, 'project')) && p('code') && e('0'); //获取不存在的项目
+1
View File
@@ -139,6 +139,7 @@ class taskTao extends taskModel
$tasks = $this->dao->select("id,{$field}")->from(TABLE_TASK)
->where($condition)
->fetchAll('id');
return $tasks;
}
/**
+1 -1
View File
@@ -3,4 +3,4 @@ sonar.sourceEncoding=UTF-8
sonar.qualitygate.wait=true
sonar.coverage.exclusions=**/*.*
sonar.inclusions=**/**.php
sonar.exclusions=**/*.bak,**/*.sql,**/*.js,**/*.css,**/*.yaml,**/*.zip,**/*.out,**/lang/*
sonar.exclusions=**/*.bak,**/*.sql,**/*.js,**/*.css,**/*.yaml,**/*.zip,**/*.out,**/lang/*,**/test/*
+6 -5
View File
@@ -260,13 +260,14 @@ class yaml
*/
public function gen($rows, $dataDirYaml = '', $isClear = true)
{
$runFileDir = dirname(getcwd() . DS . $_SERVER['SCRIPT_FILENAME']);
$runFileName = str_replace(strrchr($_SERVER['SCRIPT_FILENAME'], "."), "", $_SERVER['SCRIPT_FILENAME']);
$pos = strripos($runFileName, DS);
if($pos !== false) $runFileName = mb_substr($runFileName, $pos+1);
if(!is_dir("$runFileDir/data")) mkdir("$runFileDir/data", 0777, true);
$runFileDir = dirname($runFileName);
if(!is_dir("{$runFileDir}/data")) mkdir("{$runFileDir}/data", 0777);
$yamlFile = "{$runFileDir}/data/{$this->tableName}_{$runFileName}.yaml";
$yamlDataArr = array();
@@ -318,15 +319,15 @@ class yaml
$dbUser = $this->config->db->user;
$dbPWD = $this->config->db->password;
$command = "$zdPath -c %s -d %s -n %d -t %s -dns mysql://%s:%s@%s:%s/%s#utf8";
$command = "$zdPath -c %s -d %s -n %d -t %s -dns mysql://%s:%s@%s:%s/%s#utf8";
if($isClear === true)
{
/* Truncate table to reset auto increment number. */
system(sprintf("mysql -u%s -p%s -h%s -P%s %s -e 'truncate %s' 2>/dev/null", $dbUser, $dbPWD, $dbHost, $dbPort, $dbName, $tableName));
$command .= ' --clear';
}
$execYaml = sprintf($command, $configYaml, $yamlFile, $rows, $tableName, $dbUser, $dbPWD, $dbHost, $dbPort, $dbName);
$execDump = sprintf($dumpCommand, $dbUser, $dbPWD, $dbHost, $dbPort, $dbName, $tableName);
$execYaml = sprintf($command, $configYaml, $yamlFile, $rows, $tableName, $dbUser, $dbPWD, $dbHost, $dbPort, $dbName);
$execDump = sprintf($dumpCommand, $dbUser, $dbPWD, $dbHost, $dbPort, $dbName, $tableName);
system($execDump);
system($execYaml);
}