Merge branch 'master' into 'apiext'
# Conflicts: # config/routes.php
This commit is contained in:
+3
-1
@@ -3,6 +3,7 @@ config/my.php
|
||||
www/data/
|
||||
www/install.php
|
||||
www/upgrade.php
|
||||
www/checklist.php
|
||||
www/ok.txt
|
||||
tools/*
|
||||
release/*
|
||||
@@ -15,6 +16,7 @@ test/data/sql/
|
||||
.gitkeep
|
||||
.bak
|
||||
.idea
|
||||
.vscode
|
||||
.gitignore
|
||||
.DS_Store
|
||||
vendor/
|
||||
@@ -22,6 +24,6 @@ docker
|
||||
.docker-sync
|
||||
composer.lock
|
||||
.editorconfig
|
||||
|
||||
CodeSniffer.conf
|
||||
test/runtime/*
|
||||
test/www
|
||||
|
||||
+57
-4
@@ -9,7 +9,7 @@
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class bugEntry extends entry
|
||||
class bugEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
@@ -20,12 +20,64 @@ class bugEntry extends entry
|
||||
*/
|
||||
public function get($bugID)
|
||||
{
|
||||
$this->resetOpenApp($this->param('tab', 'product'));
|
||||
|
||||
$control = $this->loadController('bug', 'view');
|
||||
$control->view($bugID);
|
||||
|
||||
$data = $this->getData();
|
||||
$bug = $data->data->bug;
|
||||
$this->send(200, $this->format($bug, 'activatedDate:time,openedDate:time,assignedDate:time,resolvedDate:time,closedDate:time,lastEditedDate:time,deadline:date,deleted:bool'));
|
||||
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$bug = $data->data->bug;
|
||||
|
||||
/* Set product name */
|
||||
$bug->productName = $data->data->product->name;
|
||||
|
||||
/* Set module title */
|
||||
$moduleTitle = '';
|
||||
if(empty($bug->module)) $moduleTitle = '/';
|
||||
if($bug->module)
|
||||
{
|
||||
$modulePath = $data->data->modulePath;
|
||||
foreach($modulePath as $key => $module)
|
||||
{
|
||||
$moduleTitle .= $module->name;
|
||||
if(isset($modulePath[$key + 1])) $moduleTitle .= '/';
|
||||
}
|
||||
}
|
||||
$bug->moduleTitle = $moduleTitle;
|
||||
|
||||
$openedBuilds = array();
|
||||
foreach(explode(',', $bug->openedBuild) as $buildID)
|
||||
{
|
||||
if(empty($buildID)) continue;
|
||||
|
||||
$openedBuild = new stdclass();
|
||||
$openedBuild->id = $buildID;
|
||||
$openedBuild->title = zget($data->data->builds, $buildID, '');
|
||||
|
||||
$openedBuilds[] = $openedBuild;
|
||||
}
|
||||
$bug->openedBuild = $openedBuilds;
|
||||
|
||||
if($bug->resolvedBuild)
|
||||
{
|
||||
$resolvedBuild = new stdclass();
|
||||
$resolvedBuild->id = $bug->resolvedBuild;
|
||||
$resolvedBuild->title = zget($data->data->builds, $bug->resolvedBuild, '');
|
||||
$bug->resolvedBuild = $resolvedBuild;
|
||||
}
|
||||
|
||||
$bug->actions = $this->loadModel('action')->processActionForAPI($data->data->actions, $data->data->users, $this->lang->bug);
|
||||
|
||||
$preAndNext = $data->data->preAndNext;
|
||||
$bug->preAndNext = array();
|
||||
$bug->preAndNext['pre'] = $preAndNext->pre ? $preAndNext->pre->id : '';
|
||||
$bug->preAndNext['next'] = $preAndNext->next ? $preAndNext->next->id : '';
|
||||
|
||||
$this->send(200, $this->format($bug, 'activatedDate:time,openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,mailto:userList,resolvedBy:user,resolvedDate:time,closedBy:user,closedDate:time,lastEditedBy:user,lastEditedDate:time,deadline:date,deleted:bool'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,6 +94,7 @@ class bugEntry extends entry
|
||||
/* Set $_POST variables. */
|
||||
$fields = 'title,project,execution,openedBuild,assignedTo,pri,severity,type,story,resolvedBy,closedBy,resolution,product,plan,task';
|
||||
$this->batchSetPost($fields, $oldBug);
|
||||
$this->setPost('notifyEmail', implode(',', $this->request('notifyEmail', array())));
|
||||
|
||||
$control = $this->loadController('bug', 'edit');
|
||||
$control->edit($bugID);
|
||||
@@ -52,7 +105,7 @@ class bugEntry extends entry
|
||||
if(!isset($data->status)) return $this->sendError(400, 'error');
|
||||
|
||||
$bug = $this->bug->getByID($bugID);
|
||||
$this->send(200, $this->format($bug, 'activatedDate:time,openedDate:time,assignedDate:time,resolvedDate:time,closedDate:time,lastEditedDate:time,deadline:date,deleted:bool'));
|
||||
$this->send(200, $this->format($bug, 'activatedDate:time,openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,mailto:userList,resolvedBy:user,resolvedDate:time,closedBy:user,closedDate:time,lastEditedBy:user,lastEditedDate:time,deadline:date,deleted:bool'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+32
-34
@@ -9,42 +9,22 @@
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class bugsEntry extends entry
|
||||
class bugsEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $projectID
|
||||
* @param int $executionID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($productID = 0, $projectID = 0, $executionID = 0)
|
||||
public function get($productID = 0)
|
||||
{
|
||||
if(!$productID) $productID = $this->param('product', 0);
|
||||
if(!$projectID) $projectID = $this->param('project', 0);
|
||||
if(!$executionID) $executionID = $this->param('execution', 0);
|
||||
if(empty($productID)) $productID = $this->param('product', 0);
|
||||
if(empty($productID)) return $this->sendError(400, 'Need product id.');
|
||||
|
||||
if($projectID)
|
||||
{
|
||||
$control = $this->loadController('project', 'bug');
|
||||
$control->bug($projectID, $productID, $this->param('order', 'status,id_desc'), $this->param('build', 0), $this->param('status', 'all'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
}
|
||||
elseif($executionID)
|
||||
{
|
||||
$control = $this->loadController('execution', 'bug');
|
||||
$control->bug($executionID, $productID, $this->param('order', 'status,id_desc'), $this->param('build', 0), $this->param('status', 'all'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
}
|
||||
elseif($productID)
|
||||
{
|
||||
$control = $this->loadController('bug', 'browse');
|
||||
$control->browse($productID, $this->param('branch', ''), $this->param('status', ''), 0, $this->param('order', ''), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->sendError(400, 'Need product or project or execution id.');
|
||||
}
|
||||
$control = $this->loadController('bug', 'browse');
|
||||
$control->browse($productID, $this->param('branch', 'all'), $this->param('status', ''), 0, $this->param('order', 'id_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
|
||||
$data = $this->getData();
|
||||
|
||||
@@ -55,16 +35,33 @@ class bugsEntry extends entry
|
||||
$result = array();
|
||||
foreach($bugs as $bug)
|
||||
{
|
||||
$result[] = $this->format($bug, 'activatedDate:time,openedDate:time,assignedDate:time,resolvedDate:time,closedDate:time,lastEditedDate:time,deadline:date,deleted:bool');
|
||||
$status = array('code' => $bug->status, 'name' => $this->lang->bug->statusList[$bug->status]);
|
||||
if($bug->status == 'active' and $bug->confirmed) $status = array('code' => 'confirmed', 'name' => $this->lang->bug->labelConfirmed);
|
||||
if($bug->resolution == 'postponed') $status = array('code' => 'postponed', 'name' => $this->lang->bug->labelPostponed);
|
||||
if(!empty($bug->delay)) $status = array('code' => 'delay', 'name' => $this->lang->bug->overdueBugs);
|
||||
$bug->status = $status['code'];
|
||||
$bug->statusName = $status['name'];
|
||||
|
||||
$result[$bug->id] = $this->format($bug, 'activatedDate:time,openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,mailto:userList,resolvedBy:user,resolvedDate:time,closedBy:user,closedDate:time,lastEditedBy:user,lastEditedDate:time,deadline:date,deleted:bool');
|
||||
}
|
||||
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'bugs' => $result));
|
||||
$storyChangeds = $this->dao->select('t1.id')->from(TABLE_BUG)->alias('t1')
|
||||
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
|
||||
->where('t1.id')->in(array_keys($result))
|
||||
->andWhere('t1.story')->ne('0')
|
||||
->andWhere('t1.storyVersion != t2.version')
|
||||
->fetchPairs('id', 'id');
|
||||
foreach($storyChangeds as $bugID)
|
||||
{
|
||||
$status = array('code' => 'storyChanged', 'name' => $this->lang->bug->changed);
|
||||
$result[$bugID]->status = $status['code'];
|
||||
$result[$bugID]->statusName = $status['name'];
|
||||
}
|
||||
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'bugs' => array_values($result)));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail')
|
||||
{
|
||||
return $this->sendError(400, $data->message);
|
||||
}
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
@@ -86,18 +83,19 @@ class bugsEntry extends entry
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
$this->setPost('product', $productID);
|
||||
$this->setPost('notifyEmail', implode(',', $this->request('notifyEmail', array())));
|
||||
|
||||
$control = $this->loadController('bug', 'create');
|
||||
$this->requireFields('title,pri,severity,type,openedBuild');
|
||||
|
||||
$control->create($productID);
|
||||
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->result) and !isset($data->id)) return $this->sendError(400, $data->message);
|
||||
|
||||
$bug = $this->loadModel('bug')->getByID($data->id);
|
||||
|
||||
$this->send(200, $this->format($bug, 'activatedDate:time,openedDate:time,assignedDate:time,resolvedDate:time,closedDate:time,lastEditedDate:time'));
|
||||
$this->send(200, $this->format($bug, 'activatedDate:time,openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,mailto:userList,resolvedBy:user,resolvedDate:time,closedBy:user,closedDate:time,lastEditedBy:user,lastEditedDate:time,deadline:date,deleted:bool'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,10 @@ class buildEntry extends Entry
|
||||
$control->view($buildID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->status) and $data->status == 'success') return $this->send(200, $this->format($data->data->build, 'stories:idList,bugs:idList,deleted:bool'));
|
||||
if(isset($data->status) and $data->status == 'success') return $this->send(200, $this->format($data->data->build, 'builder:user,stories:idList,bugs:idList,deleted:bool'));
|
||||
|
||||
/* Exception handling. */
|
||||
if(isset($data->status) and $data->status == 'fail')
|
||||
{
|
||||
return isset($data->code) and $data->code == 404 ? $this->send404() : $this->sendError(400, $data->message);
|
||||
}
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$this->sendError(400, 'error');
|
||||
}
|
||||
@@ -58,7 +55,7 @@ class buildEntry extends Entry
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$build = $this->build->getByID($buildID);
|
||||
$this->send(200, $build);
|
||||
$this->send(200, $this->format($build, 'builder:user,stories:idList,bugs:idList,deleted:bool'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,25 +20,23 @@ class buildsEntry extends entry
|
||||
*/
|
||||
public function get($projectID = 0)
|
||||
{
|
||||
if(!$projectID) $projectID = $this->param('project', 0);
|
||||
if(empty($projectID)) $projectID = $this->param('project', 0);
|
||||
if(empty($projectID)) return $this->sendError(400, "Need project id.");
|
||||
|
||||
$control = $this->loadController('project', 'build');
|
||||
$control->build($projectID, $this->param('type', 'all'), $this->param('param', 0));
|
||||
$control->build($projectID, $this->param('type', 'all'), $this->param('param', 0), $this->param('order', 't1.date_desc,t1.id_desc'));
|
||||
$data = $this->getData();
|
||||
|
||||
if(!isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$result = array();
|
||||
foreach($data->data->projectBuilds as $productID => $builds)
|
||||
{
|
||||
foreach($builds as $build)
|
||||
{
|
||||
$result[] = $this->format($build, 'bugs:idList,stories:idList,deleted:bool');
|
||||
}
|
||||
foreach($builds as $build) $result[] = $this->format($build, 'bugs:idList,stories:idList,builder:user,deleted:bool');
|
||||
}
|
||||
|
||||
return $this->send(200, $result);
|
||||
return $this->send(200, array('total' => count($result), 'builds' => $result));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +59,7 @@ class buildsEntry extends entry
|
||||
$control = $this->loadController('build', 'create');
|
||||
$this->requireFields('execution,product,name,builder,date');
|
||||
|
||||
$control->create(0,0,$projectID);
|
||||
$control->create(0, 0, $projectID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
@@ -36,6 +36,9 @@ class configEntry extends baseEntry
|
||||
case 'timezone':
|
||||
$config['value'] = $this->config->timezone;
|
||||
break;
|
||||
case 'systemMode':
|
||||
$config['value'] = $this->config->systemMode;
|
||||
break;
|
||||
default:
|
||||
$this->sendError(400, 'No configuration.');
|
||||
return;
|
||||
|
||||
@@ -21,10 +21,11 @@ class configsEntry extends baseEntry
|
||||
{
|
||||
$configs = array();
|
||||
|
||||
$configs[] = array('key' => 'language', 'value' => $this->config->default->lang);
|
||||
$configs[] = array('key' => 'version', 'value' => $this->config->version);
|
||||
$configs[] = array('key' => 'charset', 'value' => $this->config->charset);
|
||||
$configs[] = array('key' => 'timezone', 'value' => $this->config->timezone);
|
||||
$configs[] = array('key' => 'language', 'value' => $this->config->default->lang);
|
||||
$configs[] = array('key' => 'version', 'value' => $this->config->version);
|
||||
$configs[] = array('key' => 'charset', 'value' => $this->config->charset);
|
||||
$configs[] = array('key' => 'timezone', 'value' => $this->config->timezone);
|
||||
$configs[] = array('key' => 'systemMode', 'value' => $this->config->systemMode);
|
||||
|
||||
$this->send(200, $configs);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* The doc entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class docEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $docID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($docID)
|
||||
{
|
||||
$this->resetOpenApp($this->param('tab', 'doc'));
|
||||
|
||||
$control = $this->loadController('doc', 'view');
|
||||
$control->view($docID);
|
||||
|
||||
$data = $this->getData();
|
||||
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$doc = $data->data->doc;
|
||||
|
||||
unset($doc->draft);
|
||||
if(!empty($doc->files)) $doc->files = array_values((array)$doc->files);
|
||||
|
||||
/* Set lib name */
|
||||
$doc->libName = $data->data->lib->name;
|
||||
|
||||
$preAndNext = $data->data->preAndNext;
|
||||
$doc->preAndNext = array();
|
||||
$doc->preAndNext['pre'] = $preAndNext->pre ? $preAndNext->pre->id : '';
|
||||
$doc->preAndNext['next'] = $preAndNext->next ? $preAndNext->next->id : '';
|
||||
|
||||
$this->send(200, $this->format($doc, 'addedBy:user,addedDate:time,assignedTo:user,assignedDate:date,editedBy:user,editedDate:time,mailto:userList'));
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT method.
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function put($storyID)
|
||||
{
|
||||
$oldStory = $this->loadModel('story')->getByID($storyID);
|
||||
|
||||
/* Set $_POST variables. */
|
||||
$fields = 'type';
|
||||
$this->batchSetPost($fields, $oldStory);
|
||||
$this->setPost('parent', 0);
|
||||
|
||||
$control = $this->loadController('story', 'edit');
|
||||
$control->edit($storyID);
|
||||
|
||||
$this->getData();
|
||||
$story = $this->story->getByID($storyID);
|
||||
$this->sendSuccess(200, $this->format($story, 'openedDate:time,assignedDate:time,reviewedDate:time,lastEditedDate:time,closedDate:time,deleted:bool'));
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE method.
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function delete($storyID)
|
||||
{
|
||||
$control = $this->loadController('story', 'delete');
|
||||
$control->delete($storyID, 'yes');
|
||||
|
||||
$this->getData();
|
||||
$this->sendSuccess(200, 'success');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* The doclibs entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class doclibsEntry extends Entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
$type = $this->param('type', 0);
|
||||
$objectID = $this->param('objectID', 0);
|
||||
|
||||
$libs = $this->loadModel('doc')->getLibs($type, $this->param('extra', ''), $this->param('appendLibs', ''), $objectID);
|
||||
$result = array();
|
||||
foreach($libs as $libID => $libName)
|
||||
{
|
||||
$lib = new stdclass();
|
||||
$lib->id = $libID;
|
||||
$lib->name = $libName;
|
||||
$result[] = $lib;
|
||||
}
|
||||
krsort($result);
|
||||
|
||||
return $this->send(200, array('libs' => array_values($result)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* The docs entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class docsEntry extends Entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($libID = 0)
|
||||
{
|
||||
if(empty($libID)) $libID = $this->param('lib', 0);
|
||||
if(empty($libID)) return $this->sendError(400, 'Need lib id.');
|
||||
|
||||
$docTree = $this->loadModel('doc')->getDocTree($libID);
|
||||
|
||||
foreach($docTree as $i => $module)
|
||||
{
|
||||
if(empty($module->id))
|
||||
{
|
||||
unset($docTree[$i]);
|
||||
foreach($module->children as $doc) $docTree[] = $doc;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->send(200, array('docs' => array_values($docTree)));
|
||||
}
|
||||
}
|
||||
@@ -27,14 +27,36 @@ class executionEntry extends Entry
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail')
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$execution = $this->format($data->data->execution, 'openedBy:user,openedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,PM:user,PO:user,RD:user,QD:user,whitelist:userList,begin:date,end:date,realBegan:date,realEnd:date,deleted:bool');
|
||||
|
||||
$execution->progress = ($execution->totalConsumed + $execution->totalLeft) ? round($execution->totalConsumed / ($execution->totalConsumed + $execution->totalLeft) * 100, 1) : 0;
|
||||
$execution->teamMembers = array_values((array)$data->data->teamMembers);
|
||||
$execution->products = array();
|
||||
foreach($data->data->products as $productID => $executionProduct)
|
||||
{
|
||||
return isset($data->code) and $data->code == 404 ? $this->send404() : $this->sendError(400, $data->message);
|
||||
$product = new stdclass();
|
||||
$product->id = $executionProduct->id;
|
||||
$product->name = $executionProduct->name;
|
||||
$product->plans = array();
|
||||
foreach($executionProduct->plans as $planID)
|
||||
{
|
||||
$plan = new stdclass();
|
||||
$plan->id = $planID;
|
||||
$plan->name = $data->data->planGroups->{$productID}->{$planID};
|
||||
$product->plans[] = $plan;
|
||||
}
|
||||
$execution->products[] = $product;
|
||||
}
|
||||
|
||||
$execution = $this->format($data->data->execution, 'openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time,begin:date,end:date,realBegan:date,realEnd:date,deleted:bool');
|
||||
$this->loadModel('testcase');
|
||||
$execution->caseReview = ($this->config->testcase->needReview or !empty($this->config->testcase->forceReview));
|
||||
|
||||
if(!$fields) $this->send(200, $execution);
|
||||
|
||||
$users = $data->data->users;
|
||||
|
||||
/* Set other fields. */
|
||||
$fields = explode(',', strtolower($fields));
|
||||
foreach($fields as $field)
|
||||
@@ -63,6 +85,14 @@ class executionEntry extends Entry
|
||||
|
||||
$execution->stories = array_values($stories);
|
||||
break;
|
||||
case 'actions':
|
||||
$actions = $data->data->actions;
|
||||
$execution->actions = $this->loadModel('action')->processActionForAPI($actions, $users, $this->lang->execution);
|
||||
break;
|
||||
case "dynamics":
|
||||
$dynamics = $data->data->dynamics;
|
||||
$execution->dynamics = $this->loadModel('action')->processDynamicForAPI($dynamics);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +111,7 @@ class executionEntry extends Entry
|
||||
$oldExecution = $this->loadModel('execution')->getByID($executionID);
|
||||
|
||||
/* Set $_POST variables. */
|
||||
$fields = 'project,code,name,begin,end,lifetime,desc,days,acl';
|
||||
$fields = 'project,code,name,begin,end,lifetime,desc,days,acl,status';
|
||||
$this->batchSetPost($fields, $oldExecution);
|
||||
|
||||
$this->setPost('whitelist', $this->request('whitelist', explode(',', $oldExecution->whitelist)));
|
||||
@@ -94,7 +124,7 @@ class executionEntry extends Entry
|
||||
if(!isset($data->result)) return $this->sendError(400, 'error');
|
||||
|
||||
$execution = $this->execution->getByID($executionID);
|
||||
$this->send(200, $this->format($execution, 'openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time'));
|
||||
$this->send(200, $this->format($execution, 'openedBy:user,openedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,PM:user,PO:user,RD:user,QD:user,whitelist:userList,begin:date,end:date,realBegan:date,realEnd:date,deleted:bool'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* The execution bugs entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class executionBugsEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $executionID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($executionID = 0)
|
||||
{
|
||||
if(!$executionID) $executionID = $this->param('execution', 0);
|
||||
if(empty($executionID)) return $this->sendError(400, 'Need execution id.');
|
||||
|
||||
$control = $this->loadController('execution', 'bug');
|
||||
$control->bug($executionID, $this->param('product', 0), $this->param('order', 'status,id_desc'), $this->param('build', 0), $this->param('status', 'all'), 0, 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$bugs = $data->data->bugs;
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
foreach($bugs as $bug)
|
||||
{
|
||||
$status = array('code' => $bug->status, 'name' => $this->lang->bug->statusList[$bug->status]);
|
||||
if($bug->status == 'active' and $bug->confirmed) $status = array('code' => 'confirmed', 'name' => $this->lang->bug->labelConfirmed);
|
||||
if($bug->resolution == 'postponed') $status = array('code' => 'postponed', 'name' => $this->lang->bug->labelPostponed);
|
||||
if(!empty($bug->delay)) $status = array('code' => 'delay', 'name' => $this->lang->bug->overdueBugs);
|
||||
$bug->status = $status['code'];
|
||||
$bug->statusName = $status['name'];
|
||||
|
||||
$result[$bug->id] = $this->format($bug, 'activatedDate:time,openedDate:time,assignedDate:time,resolvedDate:time,closedDate:time,lastEditedDate:time,deadline:date,deleted:bool');
|
||||
}
|
||||
|
||||
$storyChangeds = $this->dao->select('t1.id')->from(TABLE_BUG)->alias('t1')
|
||||
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
|
||||
->where('t1.id')->in(array_keys($result))
|
||||
->andWhere('t1.story')->ne('0')
|
||||
->andWhere('t1.storyVersion != t2.version')
|
||||
->fetchPairs('id', 'id');
|
||||
foreach($storyChangeds as $bugID)
|
||||
{
|
||||
$status = array('code' => 'storyChanged', 'name' => $this->lang->bug->changed);
|
||||
$result[$bugID]->status = $status['code'];
|
||||
$result[$bugID]->statusName = $status['name'];
|
||||
}
|
||||
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'bugs' => array_values($result)));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* The execution builds entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class executionBuildsEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $executionID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($executionID = 0)
|
||||
{
|
||||
if(empty($executionID)) $executionID = $this->param('execution', 0);
|
||||
if(empty($executionID)) return $this->sendError(400, "Need execution id.");
|
||||
|
||||
$control = $this->loadController('execution', 'build');
|
||||
$control->build($executionID, $this->param('status', 'all'), $this->param('param', 0), $this->param('order', 't1.date_desc,t1.id_desc'));
|
||||
$data = $this->getData();
|
||||
|
||||
if(!isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$result = array();
|
||||
foreach($data->data->executionBuilds as $builds)
|
||||
{
|
||||
foreach($builds as $build) $result[] = $this->format($build, 'builder:user,bugs:idList,stories:idList,deleted:bool');
|
||||
}
|
||||
|
||||
return $this->send(200, array('total' => count($result), 'builds' => $result));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* The execution cases entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class executionCasesEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $executionID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($executionID = 0)
|
||||
{
|
||||
if(!$executionID) $executionID = $this->param('execution', 0);
|
||||
if(empty($executionID)) return $this->sendError(400, 'Need execution id.');
|
||||
|
||||
$control = $this->loadController('execution', 'testcase');
|
||||
$control->testcase($executionID, $this->param('status', 'all'), $this->param('order', 'id_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$cases = $data->data->cases;
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
foreach($cases as $case)
|
||||
{
|
||||
$case->statusName = 'name' => $this->lang->testcase->statusList[$case->status];
|
||||
$result[] = $this->format($case, 'openedDate:time,reviewedDate:date,lastEditedDate:time,lastRunDate:time');
|
||||
}
|
||||
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'cases' => $result));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
}
|
||||
+101
-24
@@ -21,25 +21,54 @@ class executionsEntry extends entry
|
||||
public function get($projectID = 0)
|
||||
{
|
||||
$appendFields = $this->param('fields', '');
|
||||
$withProject = $this->param('withProject', '');
|
||||
if(strpos(strtolower(",{$appendFields},"), ',dropmenu,') !== false) return $this->getDropMenu();
|
||||
|
||||
$control = $this->loadController('execution', 'all');
|
||||
$control->all($this->param('status', 'all'), $this->param('project', $projectID), $this->param('order', 'id_desc'), 0, 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
if($projectID)
|
||||
{
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
foreach($data->data->executionStats as $execution)
|
||||
{
|
||||
$execution = $this->filterFields($execution, 'id,name,project,code,type,parent,begin,end,status,openedBy,openedDate,' . $appendFields);
|
||||
$result[] = $this->format($execution, 'openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time,begin:date,end:date,realBegan:date,realEnd:date,deleted:bool');
|
||||
}
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'executions' => $result));
|
||||
}
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
$control = $this->loadController('project', 'execution');
|
||||
$control->execution($this->param('status', 'undone'), $projectID, $this->param('order', 'id_desc'), $this->param('product', 0), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
|
||||
return $this->sendError(400, 'error');
|
||||
/* Response */
|
||||
$data = $this->getData();
|
||||
if(!$data or !isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$executions = $data->data->executionStats;
|
||||
$pager = $data->data->pager;
|
||||
$projects = $data->data->projects;
|
||||
}
|
||||
else
|
||||
{
|
||||
$control = $this->loadController('execution', 'all');
|
||||
$control->all($this->param('status', 'all'), $this->param('project', $projectID), $this->param('order', 'id_desc'), 0, 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
|
||||
if(!$data or !isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$executions = $data->data->executionStats;
|
||||
$pager = $data->data->pager;
|
||||
$projects = $data->data->projects;
|
||||
}
|
||||
|
||||
$result = array();
|
||||
foreach($data->data->executionStats as $execution)
|
||||
{
|
||||
foreach($execution->hours as $field => $value) $execution->$field = $value;
|
||||
|
||||
$execution = $this->filterFields($execution, 'id,name,project,code,type,parent,begin,end,status,openedBy,openedDate,delay,progress,' . $appendFields);
|
||||
$result[] = $this->format($execution, 'openedBy:user,openedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,PM:user,PO:user,RD:user,QD:user,whitelist:userList,begin:date,end:date,realBegan:date,realEnd:date,deleted:bool');
|
||||
}
|
||||
|
||||
$data = array();
|
||||
$data['page'] = $pager->pageID;
|
||||
$data['total'] = $pager->recTotal;
|
||||
$data['limit'] = $pager->recPerPage;
|
||||
$data['executions'] = $result;
|
||||
if(!empty($withProject)) $data['projects'] = $projects;
|
||||
|
||||
return $this->send(200, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,15 +84,17 @@ class executionsEntry extends entry
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
$projectID = $this->param('project', $projectID);
|
||||
$this->setPost('project', $projectID);
|
||||
$this->setPost('acl', $this->request('acl', 'private'));
|
||||
$this->setPost('project', $projectID);
|
||||
$this->setPost('acl', $this->request('acl', 'private'));
|
||||
$this->setPost('PO', $this->request('PO', ''));
|
||||
$this->setPost('PM', $this->request('PM', ''));
|
||||
$this->setPost('QD', $this->request('QD', ''));
|
||||
$this->setPost('RD', $this->request('RD', ''));
|
||||
$this->setPost('whitelist', $this->request('whitelist', array()));
|
||||
$this->setPost('products', $this->request('products', array()));
|
||||
$this->setPost('plans', $this->request('plans', array()));
|
||||
|
||||
$control = $this->loadController('execution', 'create');
|
||||
$this->requireFields('name,code,begin,end,days');
|
||||
$this->setPost('products', $this->request('products', array()));
|
||||
$this->setPost('plans', $this->request('plans', array()));
|
||||
|
||||
$control = $this->loadController('execution', 'create'); $this->requireFields('name,code,begin,end,days');
|
||||
$control->create($projectID);
|
||||
|
||||
$data = $this->getData();
|
||||
@@ -71,6 +102,52 @@ class executionsEntry extends entry
|
||||
|
||||
$execution = $this->loadModel('execution')->getByID($data->id);
|
||||
|
||||
$this->send(201, $this->format($execution, 'openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time'));
|
||||
$this->send(201, $this->format($execution, 'openedBy:user,openedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,PM:user,PO:user,RD:user,QD:user,whitelist:userList,begin:date,end:date,realBegan:date,realEnd:date,deleted:bool'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get drop menu.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getDropMenu()
|
||||
{
|
||||
$control = $this->loadController('execution', 'ajaxGetDropMenu');
|
||||
$control->ajaxGetDropMenu($this->request('executionID', 0), $this->request('module', 'execution'), $this->request('method', 'task'), $this->request('extra', ''));
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$account = $this->app->user->account;
|
||||
$projects = $data->data->projects;
|
||||
$dropMenu = array('involved' => array(), 'other' => array(), 'closed' => array());
|
||||
foreach($data->data->executions as $projectID => $projectExecutions)
|
||||
{
|
||||
foreach($projectExecutions as $execution)
|
||||
{
|
||||
if(helper::diffDate(date('Y-m-d'), $execution->end) > 0) $execution->delay = true;
|
||||
$teams = $execution->teams;
|
||||
$execution = $this->filterFields($execution, 'id,project,model,type,name,code,status,PM,delay');
|
||||
|
||||
$projectName = zget($projects, $execution->project, '');
|
||||
if($projectName) $execution->name = $projectName . '/' . $execution->name;
|
||||
|
||||
if($execution->status == 'closed')
|
||||
{
|
||||
$dropMenu['closed'][] = $execution;
|
||||
}
|
||||
elseif($execution->status != 'done' and $execution->status != 'closed' and ($execution->PM == $account or isset($teams->$account)))
|
||||
{
|
||||
$dropMenu['involved'][] = $execution;
|
||||
}
|
||||
else
|
||||
{
|
||||
$dropMenu['other'][] = $execution;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->send(200, $dropMenu);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class executionStoriesEntry extends entry
|
||||
class executionStoriesEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
@@ -20,8 +20,11 @@ class executionStoriesEntry extends entry
|
||||
*/
|
||||
public function get($executionID)
|
||||
{
|
||||
if(empty($executionID)) $this->param('execution', 0);
|
||||
if(empty($executionID)) return $this->sendError(400, 'Need execution id.');
|
||||
|
||||
$control = $this->loadController('execution', 'story');
|
||||
$control->story($executionID, $this->param('order', ''), $this->param('type', 'all'), 0, $this->param('total', 0), $this->param('limit', 20), $this->param('page', 1));
|
||||
$control->story($executionID, $this->param('order', 'id_desc'), $this->param('status', 'all'), 0, 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
@@ -31,15 +34,12 @@ class executionStoriesEntry extends entry
|
||||
$result = array();
|
||||
foreach($stories as $story)
|
||||
{
|
||||
$result[] = $this->format($story, 'openedDate:time,assignedDate:time,reviewedDate:time,lastEditedDate:time,closedDate:time');
|
||||
$result[] = $this->format($story, 'openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,reviewedBy:user,reviewedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,deleted:bool,mailto:userList');
|
||||
}
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'executionStories' => $result));
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'stories' => $result));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail')
|
||||
{
|
||||
return $this->sendError(400, $data->message);
|
||||
}
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
@@ -11,6 +11,23 @@
|
||||
*/
|
||||
class fileEntry extends Entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($fileID)
|
||||
{
|
||||
$control = $this->loadController('file', 'download');
|
||||
$control->download($fileID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$this->send(200, $data);
|
||||
}
|
||||
/**
|
||||
* PUT method.
|
||||
*
|
||||
|
||||
@@ -27,10 +27,7 @@ class filesEntry extends Entry
|
||||
$data = $this->getData();
|
||||
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'error')
|
||||
{
|
||||
return isset($data->code) and $data->code == 404 ? $this->send404() : $this->sendError(400, $data->message);
|
||||
}
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$this->send(200, array('id' => $data->id));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* The repo entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author xiawenlong <xiawenlong@cnezsoft.com>
|
||||
* @package repo
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class gitlabWebhookEntry extends baseEntry
|
||||
{
|
||||
|
||||
/**
|
||||
* Repo webhook.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function post()
|
||||
{
|
||||
$repoID= $this->param('repoID');
|
||||
if(empty($id)) return;
|
||||
|
||||
$this->loadModel('repo');
|
||||
|
||||
$repo = $this->repo->getRepoByID($repoID);
|
||||
if(empty($repo)) return;
|
||||
|
||||
$headers = getallheaders(); /* Fetch all HTTP request headers. */
|
||||
$event = isset($headers['X-Gitlab-Event']) ? $headers['X-Gitlab-Event'] : '';
|
||||
$token = isset($headers['X-Gitlab-Token']) ? $headers['X-Gitlab-Token'] : '';
|
||||
if(empty($event) || empty($token)) return;
|
||||
|
||||
$this->repo->handleWebhook($event, $token, $this->requestBody, $repo);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,7 +30,7 @@ class issueEntry extends Entry
|
||||
$data = $this->getData();
|
||||
if(!$data or (isset($data->message) and $data->message == '404 Not found')) return $this->send404();
|
||||
if(isset($data->status) and $data->status == 'success') return $this->send(200, $this->format($data->data->issue, 'createdDate:time,editedDate:time,assignedDate:time'));
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$this->sendError(400, 'error');
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class issuesEntry extends entry
|
||||
$data = $this->getData();
|
||||
|
||||
if(!isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* The meetings entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class meetingsEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($projectID = 0)
|
||||
{
|
||||
if(empty($projectID)) $projectID = $this->param('project', 0);
|
||||
if(empty($projectID)) return $this->sendError(400, 'Need project id.');
|
||||
|
||||
$project = $this->loadModel('project')->getByID($projectID);
|
||||
if(!$project) return $this->send404();
|
||||
|
||||
/* Get meetings by project. */
|
||||
$control = $this->loadController('meeting', 'browse');
|
||||
$control->browse($projectID, $this->param('status', 'all'), '', $this->param('order', 'id_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
|
||||
if(!isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
foreach($data->data->meetings as $risk)
|
||||
{
|
||||
$result[] = $this->format($risk, 'createdDate:time,editedDate:time');
|
||||
}
|
||||
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'meetings' => $result));
|
||||
}
|
||||
|
||||
/**
|
||||
* POST method.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function post($projectID = 0)
|
||||
{
|
||||
$project = $this->loadModel('project')->getByID($projectID);
|
||||
if(!$project) return $this->send404();
|
||||
|
||||
$fields = 'source,name,category,strategy,status,impact,probability,rate,identifiedDate,plannedClosedDate,actualClosedDate,resolvedBy,assignedTo,prevention,remedy,resolution';
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
$this->setPost('impact', $this->request('impact', 3));
|
||||
$this->setPost('probability', $this->request('probability', 3));
|
||||
$this->setPost('rate', $this->request('rate', 9));
|
||||
$this->setPost('pri', 'middle');
|
||||
|
||||
$control = $this->loadController('risk', 'create');
|
||||
$this->requireFields('name');
|
||||
|
||||
$control->create($projectID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->result) and !isset($data->id)) return $this->sendError(400, $data->message);
|
||||
|
||||
$risk = $this->loadModel('risk')->getByID($data->id);
|
||||
|
||||
$this->send(201, $this->format($risk, 'createdDate:time,editedDate:time'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* The ping entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class pingEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
$this->send(200, array('token' => session_id(), 'tokenLife' => ini_get('session.gc_maxlifetime')));
|
||||
}
|
||||
}
|
||||
@@ -27,16 +27,17 @@ class productEntry extends Entry
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail')
|
||||
{
|
||||
return isset($data->code) and $data->code == 404 ? $this->send404() : $this->sendError(400, $data->message);
|
||||
}
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$product = $this->format($data->data->product, 'createdDate:time,whitelist:userList,createdBy:user,PO:user,RD:user,QD:user,feedback:user');
|
||||
|
||||
$this->loadModel('testcase');
|
||||
$product->caseReview = ($this->config->testcase->needReview or !empty($this->config->testcase->forceReview));
|
||||
|
||||
$product = $this->format($data->data->product, 'createdDate:time');
|
||||
if(!$fields) return $this->send(200, $product);
|
||||
|
||||
/* Set other fields. */
|
||||
$fields = explode(',', $fields);
|
||||
$fields = explode(',', strtolower($fields));
|
||||
foreach($fields as $field)
|
||||
{
|
||||
switch($field)
|
||||
@@ -50,6 +51,29 @@ class productEntry extends Entry
|
||||
$product->modules = $data->data->tree;
|
||||
}
|
||||
break;
|
||||
case 'actions':
|
||||
$product->addComment = common::hasPriv('action', 'comment') ? true : false;
|
||||
|
||||
$actions = $data->data->actions;
|
||||
$product->actions = $this->loadModel('action')->processActionForAPI($actions, $users, $this->lang->product);
|
||||
break;
|
||||
case 'lastexecution':
|
||||
$execution = $this->dao->select('t2.id,t2.name')->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')
|
||||
->orderBy('t2.id desc')
|
||||
->limit(1)
|
||||
->fetch();
|
||||
if($execution)
|
||||
{
|
||||
$workhour = $this->loadModel('project')->computerProgress(array($execution->id => $execution));
|
||||
if(isset($workhour[$execution->id])) $execution->progress = $workhour[$execution->id]->progress;
|
||||
}
|
||||
|
||||
$product->lastExecution = $execution;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +102,7 @@ class productEntry extends Entry
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$product = $this->product->getByID($productID);
|
||||
$this->send(200, array('product' => $this->format($product, 'createdDate:time')));
|
||||
$this->send(200, $this->format($product, 'createdDate:time'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,12 +27,13 @@ class productplanEntry extends Entry
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail')
|
||||
{
|
||||
return isset($data->code) and $data->code == 404 ? $this->send404() : $this->sendError(400, $data->message);
|
||||
}
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$plan = $this->format($data->data->plan, 'begin:date,end:date,deleted:bool');
|
||||
$plan = $data->data->plan;
|
||||
$plan->stories = $data->data->planStories;
|
||||
$plan->bugs = $data->data->planBugs;
|
||||
|
||||
$plan = $this->format($plan, 'begin:date,end:date,deleted:bool,stories:array,bugs:array');
|
||||
|
||||
return $this->send(200, $plan);
|
||||
}
|
||||
@@ -58,8 +59,19 @@ class productplanEntry extends Entry
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$plan = $this->productplan->getByID($planID);
|
||||
$this->sendSuccess(200, $this->format($plan, 'begin:date,end:date'));
|
||||
/* Get plan info. */
|
||||
$control = $this->loadController('productplan', 'view');
|
||||
$control->view($planID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$plan = $data->data->plan;
|
||||
$plan->stories = $data->data->planStories;
|
||||
$plan->bugs = $data->data->planBugs;
|
||||
|
||||
$this->send(200, $this->format($plan, 'begin:date,end:date,deleted:bool,stories:array,bugs:array'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* The productplanlinkbugs entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class productplanLinkBugsEntry extends entry
|
||||
{
|
||||
/**
|
||||
* POST method.
|
||||
*
|
||||
* @param int $planID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function post($planID)
|
||||
{
|
||||
$fields = 'bugs';
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
$control = $this->loadController('productplan', 'linkBug');
|
||||
$control->linkBug($planID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'success')
|
||||
{
|
||||
$control = $this->loadController('productplan', 'view');
|
||||
$control->view($planID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$plan = $data->data->plan;
|
||||
$plan->stories = $data->data->planStories;
|
||||
$plan->bugs = $data->data->planBugs;
|
||||
|
||||
$plan = $this->format($plan, 'begin:date,end:date,deleted:bool,stories:array,bugs:array');
|
||||
|
||||
return $this->send(200, $plan);
|
||||
}
|
||||
|
||||
$this->sendError(400, array('message' => isset($data->message) ? $data->message : 'error'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* The productplanlinkstories entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class productplanLinkStoriesEntry extends entry
|
||||
{
|
||||
/**
|
||||
* POST method.
|
||||
*
|
||||
* @param int $planID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function post($planID)
|
||||
{
|
||||
$fields = 'stories';
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
$control = $this->loadController('productplan', 'linkStory');
|
||||
$control->linkStory($planID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'success')
|
||||
{
|
||||
$control = $this->loadController('productplan', 'view');
|
||||
$control->view($planID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$plan = $data->data->plan;
|
||||
$plan->stories = $data->data->planStories;
|
||||
$plan->bugs = $data->data->planBugs;
|
||||
|
||||
$plan = $this->format($plan, 'begin:date,end:date,deleted:bool,stories:array,bugs:array');
|
||||
|
||||
return $this->send(200, $plan);
|
||||
}
|
||||
|
||||
$this->sendError(400, array('message' => isset($data->message) ? $data->message : 'error'));
|
||||
}
|
||||
}
|
||||
@@ -32,13 +32,62 @@ class productplansEntry extends entry
|
||||
{
|
||||
$result = array();
|
||||
$plans = $data->data->plans;
|
||||
foreach($plans as $plan) $result[] = $plan;
|
||||
$pager = $data->data->pager;
|
||||
|
||||
return $this->send(200, array('plans' => $result));
|
||||
foreach($plans as $plan)
|
||||
{
|
||||
if($plan->parent > 0 and isset($result[$plan->parent]))
|
||||
{
|
||||
$parentPlan = $result[$plan->parent];
|
||||
|
||||
if(!isset($parentPlan->children) or !is_array($parentPlan->children)) $parentPlan->children = array();
|
||||
$parentPlan->children[] = $plan;
|
||||
$result[$plan->parent] = $parentPlan;
|
||||
}
|
||||
else
|
||||
{
|
||||
$result[$plan->id] = $this->format($plan, 'begin:date,end:date,deleted:bool,project:int');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'plans' => array_values($result)));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
|
||||
/**
|
||||
* POST method.
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function post($productID = 0)
|
||||
{
|
||||
if(!$productID) $productID = $this->param('product', 0);
|
||||
if(!$productID) return $this->sendError(400, 'No product id.');
|
||||
|
||||
$fields = 'branch,begin,end,title,desc';
|
||||
$this->batchSetPost($fields);
|
||||
$this->setPost('product', $productID);
|
||||
$this->setPost('parent', $this->request('parent', 0));
|
||||
$this->setPost('branch', $this->request('branch', 0));
|
||||
|
||||
$control = $this->loadController('productplan', 'create');
|
||||
$control->create($productID, $this->param('branch', 0), $this->param('parent', 0));
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'success')
|
||||
{
|
||||
$plan = $this->loadModel('productplan')->getByID($data->id);
|
||||
$plan->stories = array();
|
||||
$plan->bugs = array();
|
||||
return $this->send(200, $this->format($plan, 'begin:date,end:date,deleted:bool,project:int'));
|
||||
}
|
||||
|
||||
$this->sendError(400, array('message' => isset($data->message) ? $data->message : 'error'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* The productplanunlinkbugs entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class productplanUnlinkBugsEntry extends entry
|
||||
{
|
||||
/**
|
||||
* POST method.
|
||||
*
|
||||
* @param int $planID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function post($planID)
|
||||
{
|
||||
$productplan = $this->loadModel('productplan');
|
||||
foreach($this->request('bugs', array()) as $bugID)
|
||||
{
|
||||
$productplan->unlinkBug($bugID, $planID);
|
||||
if(dao::isError()) return $this->sendError('error');
|
||||
}
|
||||
|
||||
$control = $this->loadController('productplan', 'view');
|
||||
$control->view($planID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$plan = $data->data->plan;
|
||||
$plan->stories = $data->data->planStories;
|
||||
$plan->bugs = $data->data->planBugs;
|
||||
|
||||
$plan = $this->format($plan, 'begin:date,end:date,deleted:bool,stories:array,bugs:array');
|
||||
|
||||
return $this->send(200, $plan);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* The productplanunlinkstories entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class productplanUnlinkStoriesEntry extends entry
|
||||
{
|
||||
/**
|
||||
* POST method.
|
||||
*
|
||||
* @param int $planID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function post($planID)
|
||||
{
|
||||
$productplan = $this->loadModel('productplan');
|
||||
foreach($this->request('stories', array()) as $storyID)
|
||||
{
|
||||
$productplan->unlinkStory($storyID, $planID);
|
||||
if(dao::isError()) return $this->sendError('error');
|
||||
}
|
||||
|
||||
$control = $this->loadController('productplan', 'view');
|
||||
$control->view($planID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$plan = $data->data->plan;
|
||||
$plan->stories = $data->data->planStories;
|
||||
$plan->bugs = $data->data->planBugs;
|
||||
|
||||
$plan = $this->format($plan, 'begin:date,end:date,deleted:bool,stories:array,bugs:array');
|
||||
|
||||
return $this->send(200, $plan);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
/**
|
||||
* The product projects entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class productProjectsEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($productID = 0)
|
||||
{
|
||||
if(empty($productID)) $productID = $this->param('product', 0);
|
||||
if(empty($productID)) return $this->sendError('400', "Need product id");
|
||||
$appendFields = $this->param('fields', '');
|
||||
|
||||
$control = $this->loadController('product', 'project');
|
||||
$control->project($this->param('status', 'all'), $productID, $this->param('branch', 0), $this->param('involved', 0), $this->param('order', 'order_desc'));
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$result = array();
|
||||
foreach($data->data->projectStats as $project)
|
||||
{
|
||||
foreach($project->hours as $field => $value) $project->$field = $value;
|
||||
|
||||
$project = $this->filterFields($project, 'id,name,code,model,type,budget,budgetUnit,parent,begin,end,status,openedBy,openedDate,PM,delay,progress,' . $appendFields);
|
||||
$result[] = $this->format($project, 'openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time');
|
||||
}
|
||||
|
||||
$data = array();
|
||||
$data['total'] = count($result);
|
||||
$data['projects'] = $result;
|
||||
|
||||
$withUser = $this->param('withUser', '');
|
||||
if(!empty($withUser)) $data['users'] = $users;
|
||||
|
||||
return $this->send(200, $data);
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
// TODO There is no handle for 401.
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
|
||||
/**
|
||||
* POST method.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function post()
|
||||
{
|
||||
$fields = 'name,begin,end,products';
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
$this->setPost('code', $this->request('code', ''));
|
||||
$this->setPost('acl', $this->request('acl', 'private'));
|
||||
$this->setPost('parent', $this->request('program', 0));
|
||||
$this->setPost('whitelist', $this->request('whitelist', array()));
|
||||
$this->setPost('PM', $this->request('PM', ''));
|
||||
$this->setPost('model', $this->request('model', 'scrum'));
|
||||
|
||||
$control = $this->loadController('project', 'create');
|
||||
$this->requireFields('name,code,begin,end,products');
|
||||
|
||||
$control->create($this->request('model', 'scrum'));
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
if(!isset($data->result)) return $this->sendError(400, 'error');
|
||||
|
||||
$project = $this->loadModel('project')->getByID($data->id);
|
||||
|
||||
$this->send(201, $this->format($project, 'openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get drop menu.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getDropMenu()
|
||||
{
|
||||
$control = $this->loadController('project', 'ajaxGetDropMenu');
|
||||
$control->ajaxGetDropMenu($this->request('projectID', 0), $this->request('module', 'project'), $this->request('method', 'browse'));
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$dropMenu = array('owner' => array(), 'other' => array(), 'closed' => array());
|
||||
foreach($data->data->projects as $programID => $projects)
|
||||
{
|
||||
foreach($projects as $project)
|
||||
{
|
||||
if(helper::diffDate(date('Y-m-d'), $project->end) > 0) $project->delay = true;
|
||||
$project = $this->filterFields($project, 'id,model,type,name,code,parent,status,PM,delay');
|
||||
|
||||
if($project->status == 'closed')
|
||||
{
|
||||
$dropMenu['closed'][] = $project;
|
||||
}
|
||||
elseif($project->PM == $this->app->user->account)
|
||||
{
|
||||
$dropMenu['owner'][] = $project;
|
||||
}
|
||||
else
|
||||
{
|
||||
$dropMenu['other'][] = $project;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->send(200, $dropMenu);
|
||||
}
|
||||
}
|
||||
+163
-19
@@ -20,23 +20,24 @@ class productsEntry extends entry
|
||||
*/
|
||||
public function get($programID = 0)
|
||||
{
|
||||
$fields = $this->param('fields', '');
|
||||
if(strpos(strtolower(",{$fields},"), ',dropmenu,') !== false) return $this->getDropMenu();
|
||||
|
||||
if(!$programID) $programID = $this->param('program', 0);
|
||||
$mergeChildren = $this->param('mergeChildren', '');
|
||||
|
||||
if($programID)
|
||||
{
|
||||
$control = $this->loadController('program', 'product');
|
||||
$control->product($programID, $this->param('status', 'all'), $this->param('order', 'order_asc'), 0, 10000);
|
||||
$control->product($programID, $this->param('status', 'all'), $this->param('order', 'order_asc'), 0, $this->param('limit', '20'), $this->param('page', '1'));
|
||||
|
||||
/* Response */
|
||||
$data = $this->getData();
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$result = array();
|
||||
$products = $data->data->products;
|
||||
foreach($products as $product) $result[] = $this->format($product, 'createdDate:time');
|
||||
if(!$data or !isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$products = $data->data->products;
|
||||
|
||||
return $this->send(200, array('products' => $result));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -45,19 +46,51 @@ class productsEntry extends entry
|
||||
|
||||
/* Response */
|
||||
$data = $this->getData();
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$result = array();
|
||||
$products = $data->data->productStats;
|
||||
foreach($products as $product) $result[] = $this->format($product, 'createdDate:time');
|
||||
if(!$data or !isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
return $this->send(200, array('products' => $result));
|
||||
}
|
||||
$products = $data->data->productStats;
|
||||
if($mergeChildren) $products = $data->data->productStructure;
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
$result = array();
|
||||
if($mergeChildren)
|
||||
{
|
||||
$programs = $this->mergeChildren($products);
|
||||
return $this->send(200, $programs);
|
||||
}
|
||||
else
|
||||
{
|
||||
$accounts = array();
|
||||
foreach($products as $product)
|
||||
{
|
||||
$accounts[$product->PO] = $product->PO;
|
||||
$accounts[$product->QD] = $product->QD;
|
||||
$accounts[$product->RD] = $product->RD;
|
||||
$accounts[$product->createdBy] = $product->createdBy;
|
||||
if(isset($product->feedback)) $accounts[$product->feedback] = $product->feedback;
|
||||
if(!empty($product->mailto))
|
||||
{
|
||||
foreach(explode(',', $product->mailto) as $account)
|
||||
{
|
||||
$account = trim($account);
|
||||
if(empty($account)) continue;
|
||||
$accounts[$account] = $account;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->sendError(400, 'error');
|
||||
$result[] = $this->format($product, 'createdDate:time,whitelist:userList,createdBy:user,PO:user,RD:user,QD:user');
|
||||
}
|
||||
|
||||
$data = array();
|
||||
$data['total'] = count($result);
|
||||
$data['products'] = $result;
|
||||
|
||||
$withUser = $this->param('withUser', '');
|
||||
if(!empty($withUser)) $data['users'] = $this->loadModel('user')->getListByAccounts($accounts, 'account');
|
||||
|
||||
return $this->send(200, $data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,12 +113,123 @@ class productsEntry extends entry
|
||||
$control->create($this->request('program', 0));
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
/* Response */
|
||||
$product = $this->loadModel('product')->getByID($data->id);
|
||||
$product = $this->format($product, 'createdDate:time,whitelist:[]string');
|
||||
$product = $this->format($product, 'createdDate:time,whitelist:userList,createdBy:user,PO:user,RD:user,QD:user');
|
||||
|
||||
$this->send(200, $product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get dropmenu.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getDropMenu()
|
||||
{
|
||||
$control = $this->loadController('product', 'ajaxGetDropMenu');
|
||||
$control->ajaxGetDropMenu($this->request('productID', 0), $this->request('module', 'product'), $this->request('method', 'browse'), $this->request('extra', ''), $this->request('from', ''));
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$dropMenu = array('owner' => array(), 'other' => array(), 'closed' => array());
|
||||
foreach($data->data->products as $programID => $products)
|
||||
{
|
||||
foreach($products as $product)
|
||||
{
|
||||
$product = $this->filterFields($product, 'id,program,name,code,status,PO');
|
||||
|
||||
if($product->status == 'closed')
|
||||
{
|
||||
$dropMenu['closed'][] = $product;
|
||||
}
|
||||
elseif($product->PO == $this->app->user->account)
|
||||
{
|
||||
$dropMenu['owner'][] = $product;
|
||||
}
|
||||
else
|
||||
{
|
||||
$dropMenu['other'][] = $product;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->send(200, $dropMenu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge children products.
|
||||
*
|
||||
* @param array $products
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function mergeChildren($products)
|
||||
{
|
||||
$programs = array();
|
||||
foreach($products as $programID => $program)
|
||||
{
|
||||
$programs[$programID] = new stdclass();
|
||||
if(!empty($programID))
|
||||
{
|
||||
$programs[$programID]->id = $programID;
|
||||
$programs[$programID]->name = $program->programName;
|
||||
$programs[$programID]->type = 'program';
|
||||
}
|
||||
|
||||
$unclosedTotal = 0;
|
||||
foreach($program as $field => $value)
|
||||
{
|
||||
if(!isset($programs[$programID]->children)) $programs[$programID]->children = array();
|
||||
if(isset($value->products))
|
||||
{
|
||||
$lineID = $field;
|
||||
if(empty($lineID))
|
||||
{
|
||||
foreach($value->products as $product)
|
||||
{
|
||||
unset($product->desc);
|
||||
$programs[$programID]->children[$product->id] = $product;
|
||||
if($product->status != 'closed') $unclosedTotal += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$line = new stdclass();
|
||||
$line->id = $lineID;
|
||||
$line->name = $value->lineName;
|
||||
$line->type = 'line';
|
||||
|
||||
$line->children = array();
|
||||
foreach($value->products as $product)
|
||||
{
|
||||
unset($product->desc);
|
||||
$line->children[$product->id] = $product;
|
||||
if($product->status != 'closed') $unclosedTotal += 1;
|
||||
}
|
||||
if(isset($line->children)) $line->children = array_values($line->children);
|
||||
|
||||
$programs[$programID]->children[$lineID] = $line;
|
||||
}
|
||||
if(isset($programs[$programID]->children)) $programs[$programID]->children = array_values($programs[$programID]->children);
|
||||
$programs[$programID]->unclosedTotal = $unclosedTotal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$topProducts = array();
|
||||
if(isset($programs[0]))
|
||||
{
|
||||
$topProducts = $programs[0]->children;
|
||||
unset($programs[0]);
|
||||
}
|
||||
|
||||
$programs = array_values($programs);
|
||||
foreach($topProducts as $product) $programs[] = $product;
|
||||
|
||||
return $programs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,4 +11,60 @@
|
||||
*/
|
||||
class programEntry extends Entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $programID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($programID)
|
||||
{
|
||||
$program = $this->loadModel('program')->getByID($programID);
|
||||
if(!$program) return $this->send404();
|
||||
|
||||
$this->send(200, $this->format($program, 'begin:date,end:date,PO:user,PM:user,QD:user,RD:user,realBegan:date,realEnd:date,openedBy:user,openedDate:time,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,deleted:bool,whitelist:userList'));
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT method.
|
||||
*
|
||||
* @param int $programID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function put($programID)
|
||||
{
|
||||
$oldProgram = $this->loadModel('program')->getByID($programID);
|
||||
|
||||
/* Set $_POST variables. */
|
||||
$fields = 'name,PM,budget,budgetUnit,desc,parent,begin,end,realBegan,realEnd,acl,whitelist';
|
||||
$this->batchSetPost($fields, $oldProgram);
|
||||
$this->setPost('parent', $this->request('parent', 0));
|
||||
|
||||
$control = $this->loadController('program', 'edit');
|
||||
$control->edit($programID);
|
||||
|
||||
$this->getData();
|
||||
$program = $this->program->getByID($programID);
|
||||
$this->send(200, $this->format($program, 'begin:date,end:date,PO:user,PM:user,QD:user,RD:user,realBegan:date,realEnd:date,openedBy:user,openedDate:time,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,deleted:bool,whitelist:userList'));
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE method.
|
||||
*
|
||||
* @param int $programID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function delete($programID)
|
||||
{
|
||||
$control = $this->loadController('program', 'delete');
|
||||
$control->delete(0, $programID, 'true');
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$this->sendSuccess(200, 'success');
|
||||
}
|
||||
}
|
||||
|
||||
+94
-10
@@ -9,7 +9,7 @@
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class ProgramsEntry extends Entry
|
||||
class programsEntry extends Entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
@@ -19,25 +19,109 @@ class ProgramsEntry extends Entry
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
$_COOKIE['showClosed'] = $this->param('showClosed', 0);
|
||||
$mergeChildren = $this->param('mergeChildren', 0);
|
||||
|
||||
$this->config->systemMode = 'new';
|
||||
|
||||
$fields = $this->param('fields', '');
|
||||
if(stripos(strtolower(",{$fields},"), ",dropmenu,") !== false) return $this->getDropMenu();
|
||||
|
||||
$program = $this->loadController('program', 'browse');
|
||||
$program->browse($this->param('status', 'all'), $this->param('order', 'order_asc'));
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
if(!$data or !isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$programs = $data->data->programs;
|
||||
$progressList = $data->data->progressList;
|
||||
$users = $data->data->users;
|
||||
$result = array();
|
||||
foreach($programs as $program)
|
||||
{
|
||||
$programs = $data->data->programs;
|
||||
$result = array();
|
||||
foreach($programs as $program)
|
||||
if(isset($progressList->{$program->id})) $program->progress = $progressList->{$program->id};
|
||||
$program = $this->format($program, 'begin:date,end:date,PO:user,PM:user,QD:user,RD:user,realBegan:date,realEnd:date,openedBy:user,openedDate:time,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,deleted:bool,whitelist:userList');
|
||||
|
||||
if($mergeChildren)
|
||||
{
|
||||
$result[] = $this->format($program, 'begin:date,end:date,realBegan:date,realEnd:date,openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time,deleted:bool');
|
||||
unset($program->desc);
|
||||
$program->end = $program->end == LONG_TIME ? $this->lang->program->longTime : $program->end;
|
||||
|
||||
$programBudget = in_array($this->app->getClientLang(), array('zh-cn','zh-tw')) ? round((float)$program->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$program->budget, 2);
|
||||
$program->labelBudget = $program->budget != 0 ? zget($this->lang->project->currencySymbol, $program->budgetUnit) . ' ' . $programBudget : $this->lang->project->future;
|
||||
|
||||
if(empty($program->parent)) $result[$program->id] = $program;
|
||||
if(isset($programs->{$program->parent}))
|
||||
{
|
||||
$parentProgram = $programs->{$program->parent};
|
||||
if(!isset($parentProgram->children)) $parentProgram->children = array();
|
||||
$parentProgram->children[] = $program;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$result[] = $program;
|
||||
}
|
||||
return $this->send(200, array('programs' => $result));
|
||||
}
|
||||
if(isset($data->status) and $data->status == 'fail')
|
||||
return $this->send(200, array('programs' => array_values($result)));
|
||||
}
|
||||
|
||||
/**
|
||||
* POST method.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function post()
|
||||
{
|
||||
$fields = 'name,PM,budget,budgetUnit,desc,begin,end';
|
||||
$this->batchSetPost($fields);
|
||||
$this->setPost('acl', $this->request('acl', 'open'));
|
||||
$this->setPost('whitelist', $this->request('whitelist', array()));
|
||||
|
||||
$control = $this->loadController('program', 'create');
|
||||
$this->requireFields('name,begin,end');
|
||||
|
||||
$control->create($this->request('parent', 0));
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$program = $this->loadModel('program')->getByID($data->id);
|
||||
$this->send(201, $this->format($program, 'begin:date,end:date,PO:user,PM:user,QD:user,RD:user,realBegan:date,realEnd:date,openedBy:user,openedDate:time,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,deleted:bool,whitelist:userList'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get drop menu.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getDropMenu()
|
||||
{
|
||||
$programs = $this->dao->select('id,name,parent,path,grade,`order`')->from(TABLE_PROJECT)
|
||||
->where('deleted')->eq('0')
|
||||
->andWhere('type')->eq('program')
|
||||
->andWhere('id')->in($this->app->user->view->programs)
|
||||
->beginIF(empty($_COOKIE['showClosed']))->andWhere('status')->ne('closed')->fi()
|
||||
->orderBy('grade desc, `order`')
|
||||
->fetchAll('id');
|
||||
|
||||
$dropMenu = array();
|
||||
foreach($programs as $programID => $program)
|
||||
{
|
||||
return $this->sendError(400, $data->message);
|
||||
if(empty($program->parent))
|
||||
{
|
||||
$dropMenu[] = $program;
|
||||
}
|
||||
elseif(isset($programs[$program->parent]))
|
||||
{
|
||||
if(!isset($programs[$program->parent]->children)) $programs[$program->parent]->children = array();
|
||||
$programs[$program->parent]->children[] = $program;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->sendError(400, 'error');
|
||||
$this->send(200, $dropMenu);
|
||||
}
|
||||
}
|
||||
|
||||
+59
-11
@@ -20,20 +20,68 @@ class projectEntry extends entry
|
||||
*/
|
||||
public function get($projectID)
|
||||
{
|
||||
$fields = strtolower($this->param('fields'));
|
||||
|
||||
$control = $this->loadController('project', 'view');
|
||||
$control->view($projectID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or !isset($data->status)) return $this->sendError(400, 'error');
|
||||
|
||||
if(isset($data->status) and $data->status == 'success') return $this->send(200, $this->format($data->data->project, 'begin:date,end:date,realBegan:date,realEnd:date,openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time,deleted:bool'));
|
||||
if(isset($data->status) and $data->status == 'fail')
|
||||
if(!$data or !isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$project = $this->format($data->data->project, 'openedBy:user,openedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,realBegan:date,realEnd:date,PM:user,whitelist:userList,deleted:bool');
|
||||
|
||||
$this->loadModel('testcase');
|
||||
$project->caseReview = ($this->config->testcase->needReview or !empty($this->config->testcase->forceReview));
|
||||
|
||||
if(empty($fields)) return $this->send(200, $project);
|
||||
|
||||
/* Set other fields. */
|
||||
$fields = explode(',', $fields);
|
||||
foreach($fields as $field)
|
||||
{
|
||||
if(isset($data->code) and $data->code == 404) $this->send404();
|
||||
return $this->sendError(400, $data->message);
|
||||
switch($field)
|
||||
{
|
||||
case 'team':
|
||||
$teams = array();
|
||||
$accounts = array();
|
||||
foreach($data->data->teamMembers as $account => $team)
|
||||
{
|
||||
$team = $this->filterFields($team, "account,role,join,realname");
|
||||
|
||||
$teams[$account] = $team;
|
||||
$accounts[$account] = $account;
|
||||
}
|
||||
$users = $this->loadModel('user')->getListByAccounts($accounts, 'account');
|
||||
foreach($teams as $account => $team)
|
||||
{
|
||||
$user = zget($users, $account, '');
|
||||
$team->avatar = $user->avatar;
|
||||
}
|
||||
|
||||
$project->teams = $teams;
|
||||
break;
|
||||
case "stat":
|
||||
$project->stat = $data->data->statData;
|
||||
break;
|
||||
case "workhour":
|
||||
$workhour = $data->data->workhour;
|
||||
$workhour->progress = ($workhour->totalConsumed + $workhour->totalLeft) ? floor($workhour->totalConsumed / ($workhour->totalConsumed + $workhour->totalLeft) * 1000) / 1000 * 100 : 0;
|
||||
$project->workhour = $workhour;
|
||||
break;
|
||||
case "actions":
|
||||
$actions = $data->data->actions;
|
||||
$project->actions = $this->loadModel('action')->processActionForAPI($actions, (array)$data->data->users, $this->lang->project);
|
||||
break;
|
||||
case "dynamics":
|
||||
$dynamics = $data->data->dynamics;
|
||||
$project->dynamics = $this->loadModel('action')->processDynamicForAPI($dynamics);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->sendError(400, 'error');
|
||||
return $this->send(200, $project);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,7 +94,7 @@ class projectEntry extends entry
|
||||
public function put($projectID)
|
||||
{
|
||||
$oldProject = $this->loadModel('project')->getByID($projectID);
|
||||
$linkedProducts = $this->project->getProducts($projectID);
|
||||
$linkedProducts = $this->loadModel('product')->getProducts($projectID);
|
||||
|
||||
/* Set $_POST variables. */
|
||||
$fields = 'name,begin,end,acl,parent,desc,PM,whitelist';
|
||||
@@ -56,8 +104,8 @@ class projectEntry extends entry
|
||||
$plans = array();
|
||||
foreach($linkedProducts as $product)
|
||||
{
|
||||
$products[] = $product->id;
|
||||
$plans[] = $product->plan;
|
||||
$products[] = $product->id;
|
||||
foreach($product->plans as $planID) $plans[] = $planID;
|
||||
}
|
||||
$this->setPost('products', $products);
|
||||
$this->setPost('plans', $plans);
|
||||
@@ -66,11 +114,11 @@ class projectEntry extends entry
|
||||
$control->edit($projectID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
if(!isset($data->result)) return $this->sendError(400, 'error');
|
||||
|
||||
$project = $this->project->getByID($projectID);
|
||||
$this->send(200, $this->format($project, 'openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time'));
|
||||
$this->send(200, $this->format($project, 'openedBy:user,openedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,realBegan:date,realEnd:date,PM:user,whitelist:userList,deleted:bool'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* The project bugs entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class projectBugsEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($projectID = 0)
|
||||
{
|
||||
if(empty($projectID)) $projectID = $this->param('project', 0);
|
||||
if(empty($projectID)) return $this->sendError(400, 'Need project id.');
|
||||
|
||||
$control = $this->loadController('project', 'bug');
|
||||
$control->bug($projectID, $this->param('product', 0), $this->param('order', 'status,id_desc'), $this->param('build', 0), $this->param('status', 'all'), 0, 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$bugs = $data->data->bugs;
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
foreach($bugs as $bug)
|
||||
{
|
||||
$status = array('code' => $bug->status, 'name' => $this->lang->bug->statusList[$bug->status]);
|
||||
if($bug->status == 'active' and $bug->confirmed) $status = array('code' => 'confirmed', 'name' => $this->lang->bug->labelConfirmed);
|
||||
if($bug->resolution == 'postponed') $status = array('code' => 'postponed', 'name' => $this->lang->bug->labelPostponed);
|
||||
if(!empty($bug->delay)) $status = array('code' => 'delay', 'name' => $this->lang->bug->overdueBugs);
|
||||
$bug->status = $status['code'];
|
||||
$bug->statusName = $status['name'];
|
||||
|
||||
$result[$bug->id] = $this->format($bug, 'activatedDate:time,openedDate:time,assignedDate:time,resolvedDate:time,closedDate:time,lastEditedDate:time,deadline:date,deleted:bool');
|
||||
}
|
||||
|
||||
$storyChangeds = $this->dao->select('t1.id')->from(TABLE_BUG)->alias('t1')
|
||||
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
|
||||
->where('t1.id')->in(array_keys($result))
|
||||
->andWhere('t1.story')->ne('0')
|
||||
->andWhere('t1.storyVersion != t2.version')
|
||||
->fetchPairs('id', 'id');
|
||||
foreach($storyChangeds as $bugID)
|
||||
{
|
||||
$status = array('code' => 'storyChanged', 'name' => $this->lang->bug->changed);
|
||||
$result[$bugID]->status = $status['code'];
|
||||
$result[$bugID]->statusName = $status['name'];
|
||||
}
|
||||
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'bugs' => array_values($result)));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* The project cases entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class projectCasesEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($projectID = 0)
|
||||
{
|
||||
if(!$projectID) $projectID = $this->param('project', 0);
|
||||
if(empty($projectID)) return $this->sendError(400, 'Need project id.');
|
||||
|
||||
$this->resetOpenApp('project');
|
||||
$this->app->session->set('project', $projectID, $this->app->tab);
|
||||
|
||||
$control = $this->loadController('project', 'testcase');
|
||||
$control->testcase($projectID, $this->param('product', 0), $this->param('branch', 0), $this->param('status', 'all'), 0, $this->param('order', 'id_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$cases = $data->data->cases;
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
foreach($cases as $case)
|
||||
{
|
||||
$case->statusName = $this->lang->testcase->statusList[$case->status];
|
||||
$result[] = $this->format($case, 'openedDate:time,reviewedDate:date,lastEditedDate:time,lastRunDate:time');
|
||||
}
|
||||
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'cases' => $result));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class projectreleasesEntry extends entry
|
||||
class projectReleasesEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
@@ -20,7 +20,26 @@ class projectreleasesEntry extends entry
|
||||
*/
|
||||
public function get($projectID = 0)
|
||||
{
|
||||
$this->fetch('releases', 'get', array('productID' => 0, 'projectID' => $projectID));
|
||||
if(empty($projectID)) $projectID = $this->param('project');
|
||||
if(empty($projectID)) return $this->sendError(400, 'Need project id.');
|
||||
|
||||
$control = $this->loadController('projectrelease', 'browse');
|
||||
$control->browse($projectID, $this->param('execution', 0), $this->param('status', 'all'), $this->param('order', 't1.date_desc'));
|
||||
|
||||
/* Response */
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$result = array();
|
||||
$releases = $data->data->releases;
|
||||
foreach($releases as $release) $result[] = $this->format($release, 'deleted:bool,date:date,mailto:userList');
|
||||
|
||||
return $this->send(200, array('total' => count($result), 'releases' => $result));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+73
-10
@@ -22,26 +22,50 @@ class projectsEntry extends entry
|
||||
{
|
||||
if(!$programID) $programID = $this->param('program', 0);
|
||||
$appendFields = $this->param('fields', '');
|
||||
if(stripos(strtolower(",{$appendFields},"), ',dropmenu,') !== false) return $this->getDropMenu();
|
||||
|
||||
$control = $this->loadController('project', 'browse');
|
||||
$control->browse($programID, $this->param('status', 'all'), 0, $this->param('order', 'order_asc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
$_COOKIE['involved'] = $this->param('involved', 0);
|
||||
|
||||
$this->config->systemMode = 'new';
|
||||
|
||||
if($programID)
|
||||
{
|
||||
$control = $this->loadController('program', 'project');
|
||||
$control->project($programID, $this->param('status', 'all'), $this->param('order', 'order_asc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
}
|
||||
else
|
||||
{
|
||||
$control = $this->loadController('project', 'browse');
|
||||
$control->browse($programID, $this->param('status', 'all'), 0, $this->param('order', 'order_asc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$pager = $data->data->pager;
|
||||
$users = $data->data->users;
|
||||
$result = array();
|
||||
foreach($data->data->projectStats as $project)
|
||||
{
|
||||
$project = $this->filterFields($project, 'id,name,code,type,parent,begin,end,status,openedBy,openedDate,' . $appendFields);
|
||||
$result[] = $this->format($project, 'openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time');
|
||||
foreach($project->hours as $field => $value) $project->$field = $value;
|
||||
|
||||
$result[] = $this->format($project, 'openedBy:user,openedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,realBegan:date,realEnd:date,PM:user,whitelist:userList,deleted:bool');
|
||||
}
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => (int)$pager->recPerPage, 'projects' => $result));
|
||||
|
||||
$data = array();
|
||||
$data['page'] = $pager->pageID;
|
||||
$data['total'] = $pager->recTotal;
|
||||
$data['limit'] = (int)$pager->recPerPage;
|
||||
$data['projects'] = $result;
|
||||
|
||||
$withUser = $this->param('withUser', '');
|
||||
if(!empty($withUser)) $data['users'] = $users;
|
||||
|
||||
return $this->send(200, $data);
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
// TODO There is no handle for 401.
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
|
||||
@@ -74,6 +98,45 @@ class projectsEntry extends entry
|
||||
|
||||
$project = $this->loadModel('project')->getByID($data->id);
|
||||
|
||||
$this->send(201, $this->format($project, 'openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time'));
|
||||
$this->send(201, $this->format($project, 'openedBy:user,openedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,realBegan:date,realEnd:date,PM:user,whitelist:userList,deleted:bool'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get drop menu.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getDropMenu()
|
||||
{
|
||||
$control = $this->loadController('project', 'ajaxGetDropMenu');
|
||||
$control->ajaxGetDropMenu($this->request('projectID', 0), $this->request('module', 'project'), $this->request('method', 'browse'));
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$dropMenu = array('owner' => array(), 'other' => array(), 'closed' => array());
|
||||
foreach($data->data->projects as $programID => $projects)
|
||||
{
|
||||
foreach($projects as $project)
|
||||
{
|
||||
if(helper::diffDate(date('Y-m-d'), $project->end) > 0) $project->delay = true;
|
||||
$project = $this->filterFields($project, 'id,model,type,name,code,parent,status,PM,delay');
|
||||
|
||||
if($project->status == 'closed')
|
||||
{
|
||||
$dropMenu['closed'][] = $project;
|
||||
}
|
||||
elseif($project->PM == $this->app->user->account)
|
||||
{
|
||||
$dropMenu['owner'][] = $project;
|
||||
}
|
||||
else
|
||||
{
|
||||
$dropMenu['other'][] = $project;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->send(200, $dropMenu);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* The project entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package project
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class projectStoriesEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($projectID)
|
||||
{
|
||||
if(!$projectID) $projectID = $this->param('project');
|
||||
if(!$projectID) return $this->sendError(400, 'Need product id.');
|
||||
|
||||
$control = $this->loadController('projectstory', 'story');
|
||||
$control->story($projectID, $this->param('product', 0), $this->param('branch', ''), $this->param('status', 'unclosed'), 0, 'story', $this->param('order', 'id_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$stories = $data->data->stories;
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
foreach($stories as $story)
|
||||
{
|
||||
$result[] = $this->format($story, 'openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,reviewedBy:user,reviewedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,deleted:bool,mailto:userList');
|
||||
}
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'stories' => $result));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
}
|
||||
@@ -25,10 +25,7 @@ class releaseEntry extends Entry
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail')
|
||||
{
|
||||
return isset($data->code) and $data->code == 404 ? $this->send404() : $this->sendError(400, $data->message);
|
||||
}
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$release = $this->format($data->data->release, 'date:date,deleted:bool');
|
||||
|
||||
|
||||
@@ -15,26 +15,16 @@ class releasesEntry extends entry
|
||||
* GET method.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($productID = 0, $projectID = 0)
|
||||
public function get($productID = 0)
|
||||
{
|
||||
if(!$productID) $productID = $this->param('product');
|
||||
if(!$projectID) $projectID = $this->param('project');
|
||||
if(!$productID and !$projectID) return $this->sendError(400, 'Need product or project id.');
|
||||
if(empty($productID)) $productID = $this->param('product');
|
||||
if(empty($productID)) return $this->sendError(400, 'Need product id.');
|
||||
|
||||
if($projectID)
|
||||
{
|
||||
$control = $this->loadController('projectrelease', 'browse');
|
||||
$control->browse($projectID, 0, $this->param('status', 'all'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$control = $this->loadController('release', 'browse');
|
||||
$control->browse($productID, $this->param('branch', 0), $this->param('status', 'all'));
|
||||
}
|
||||
$control = $this->loadController('release', 'browse');
|
||||
$control->browse($productID, $this->param('branch', 0), $this->param('status', 'all'), $this->param('order', 't1.date_desc'));
|
||||
|
||||
/* Response */
|
||||
$data = $this->getData();
|
||||
@@ -42,13 +32,12 @@ class releasesEntry extends entry
|
||||
{
|
||||
$result = array();
|
||||
$releases = $data->data->releases;
|
||||
foreach($releases as $release) $result[] = $this->format($release, 'deleted:bool,date:date');
|
||||
foreach($releases as $release) $result[] = $this->format($release, 'deleted:bool,date:date,mailto:userList');
|
||||
|
||||
return $this->send(200, array('releases' => $result));
|
||||
return $this->send(200, array('total' => count($result), 'releases' => $result));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,6 +278,7 @@ class reportsEntry extends entry
|
||||
{
|
||||
$product->storyStat = array();
|
||||
foreach(array_keys($storyStatusList) as $storyStatus) $product->storyStat[$storyStatus] = isset($productStoryStat[$productID][$storyStatus]) ? $productStoryStat[$productID][$storyStatus] : 0;
|
||||
$product->progress = $product->storyStat['closed'] == 0 ? 0 : round($product->storyStat['closed'] / array_sum($product->storyStat) * 100, 1);
|
||||
}
|
||||
|
||||
foreach(array_keys($productStatusList) as $status)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* The repos entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class reposEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
$control = $this->loadController('repo', 'maintain');
|
||||
$control->maintain(0, $this->param('order', 'id_desc'), 0, $this->param('limit', 100), $this->param('page', 1));
|
||||
|
||||
/* Response */
|
||||
$data = $this->getData();
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$result = array();
|
||||
$pager = $data->data->pager;
|
||||
$repos = $data->data->repoList;
|
||||
foreach($repos as $repo) $result[] = $this->format($repo, 'deleted:bool,lastSync:datetime,synced:bool,product:idList');
|
||||
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'repos' => $result));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ class riskEntry extends Entry
|
||||
$data = $this->getData();
|
||||
if(!$data or (isset($data->message) and $data->message == '404 Not found')) return $this->send404();
|
||||
if(isset($data->status) and $data->status == 'success') return $this->send(200, $this->format($data->data->risk, 'createdDate:time,editedDate:time'));
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$this->sendError(400, 'error');
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class risksEntry extends entry
|
||||
}
|
||||
|
||||
if(!isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/**
|
||||
* The stakeholder entry point of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package entries
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class stakeholdersEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $programID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($programID = 0)
|
||||
{
|
||||
if(!$programID) $programID = $this->param('program', 0);
|
||||
|
||||
if($programID)
|
||||
{
|
||||
$control = $this->loadController('program', 'stakeholder');
|
||||
$control->stakeholder($programID, $this->param('order', 't1.id_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$this->app->loadLang('stakeholder');
|
||||
$pager = $data->data->pager;
|
||||
$users = $data->data->users;
|
||||
$result = array();
|
||||
foreach($data->data->stakeholders as $stakeholder)
|
||||
{
|
||||
$stakeholder->roleName = zget($this->lang->user->roleList, $stakeholder->role, '');
|
||||
$stakeholder->typeName = zget($this->lang->stakeholder->fromList, $stakeholder->from, '');
|
||||
|
||||
$result[] = $stakeholder;
|
||||
}
|
||||
|
||||
$data = array();
|
||||
$data['page'] = $pager->pageID;
|
||||
$data['total'] = $pager->recTotal;
|
||||
$data['limit'] = (int)$pager->recPerPage;
|
||||
$data['stakeholders'] = $result;
|
||||
|
||||
$withUser = $this->param('withUser', '');
|
||||
if(!empty($withUser)) $data['users'] = $users;
|
||||
|
||||
return $this->send(200, $data);
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
|
||||
/**
|
||||
* POST method.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function post()
|
||||
{
|
||||
$fields = 'name,begin,end,products';
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
$this->setPost('code', $this->request('code', ''));
|
||||
$this->setPost('acl', $this->request('acl', 'private'));
|
||||
$this->setPost('parent', $this->request('program', 0));
|
||||
$this->setPost('whitelist', $this->request('whitelist', array()));
|
||||
$this->setPost('PM', $this->request('PM', ''));
|
||||
$this->setPost('model', $this->request('model', 'scrum'));
|
||||
|
||||
$control = $this->loadController('project', 'create');
|
||||
$this->requireFields('name,code,begin,end,products');
|
||||
|
||||
$control->create($this->request('model', 'scrum'));
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
if(!isset($data->result)) return $this->sendError(400, 'error');
|
||||
|
||||
$project = $this->loadModel('project')->getByID($data->id);
|
||||
|
||||
$this->send(201, $this->format($project, 'openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get drop menu.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getDropMenu()
|
||||
{
|
||||
$control = $this->loadController('project', 'ajaxGetDropMenu');
|
||||
$control->ajaxGetDropMenu($this->request('projectID', 0), $this->request('module', 'project'), $this->request('method', 'browse'));
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$dropMenu = array('owner' => array(), 'other' => array(), 'closed' => array());
|
||||
foreach($data->data->projects as $programID => $projects)
|
||||
{
|
||||
foreach($projects as $project)
|
||||
{
|
||||
if(helper::diffDate(date('Y-m-d'), $project->end) > 0) $project->delay = true;
|
||||
$project = $this->filterFields($project, 'id,model,type,name,code,parent,status,PM,delay');
|
||||
|
||||
if($project->status == 'closed')
|
||||
{
|
||||
$dropMenu['closed'][] = $project;
|
||||
}
|
||||
elseif($project->PM == $this->app->user->account)
|
||||
{
|
||||
$dropMenu['owner'][] = $project;
|
||||
}
|
||||
else
|
||||
{
|
||||
$dropMenu['other'][] = $project;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->send(200, $dropMenu);
|
||||
}
|
||||
}
|
||||
+20
-37
@@ -9,53 +9,36 @@
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class storiesEntry extends entry
|
||||
class storiesEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($productID = 0, $projectID = 0)
|
||||
public function get($productID = 0)
|
||||
{
|
||||
if(!$productID) $productID = $this->param('product');
|
||||
if(!$projectID) $projectID = $this->param('project');
|
||||
if(!$productID and !$projectID) return $this->sendError(400, 'Need product or project id.');
|
||||
if(!$productID) return $this->sendError(400, 'Need product id.');
|
||||
|
||||
if($projectID)
|
||||
{
|
||||
$control = $this->loadController('projectstory', 'story');
|
||||
$control->story($projectID, $productID, $this->param('branch', 0), $this->param('type', ''), 0, 'story', $this->param('order', ''), $this->param('total', 0), $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
}
|
||||
else
|
||||
{
|
||||
$control = $this->loadController('product', 'browse');
|
||||
$control->browse($productID, $this->param('branch', 0), $this->param('type', ''), 0, 'story', $this->param('order', ''), $this->param('total', 0), $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
}
|
||||
$control = $this->loadController('product', 'browse');
|
||||
$control->browse($productID, $this->param('branch', ''), $this->param('status', 'unclosed'), 0, $this->param('type', 'story'), $this->param('order', 'id_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$stories = $data->data->stories;
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
foreach($stories as $story)
|
||||
{
|
||||
$result[] = $this->format($story, 'openedDate:time,assignedDate:time,reviewedDate:time,lastEditedDate:time,closedDate:time,deleted:bool');
|
||||
}
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'stories' => $result));
|
||||
}
|
||||
$data = $this->getData();
|
||||
if(!$data or !isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail')
|
||||
$stories = $data->data->stories;
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
foreach($stories as $story)
|
||||
{
|
||||
return $this->sendError(400, $data->message);
|
||||
if(isset($story->children)) $story->children = array_values((array)$story->children);
|
||||
$result[] = $this->format($story, 'openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,reviewedBy:user,reviewedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,deleted:bool,mailto:userList');
|
||||
}
|
||||
|
||||
return $this->sendError(400, 'error');
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'stories' => $result));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,7 +58,8 @@ class storiesEntry extends entry
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
/* If reviewer is not post, set needNotReview. */
|
||||
if(empty($this->request('reviewer'))) $this->setPost('needNotReview', 1);
|
||||
$reviewer = $this->request('reviewer');
|
||||
if(empty($reviewer)) $this->setPost('needNotReview', 1);
|
||||
$this->setPost('product', $productID);
|
||||
$this->setPost('type', $this->param('type', 'story'));
|
||||
|
||||
@@ -83,13 +67,12 @@ class storiesEntry extends entry
|
||||
$this->requireFields('title,spec,pri,category');
|
||||
|
||||
$control->create($productID);
|
||||
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
if(isset($data->result) and !isset($data->id)) return $this->sendError(400, $data->message);
|
||||
|
||||
$story = $this->loadModel('story')->getByID($data->id);
|
||||
|
||||
$this->send(200, $this->format($story, 'openedDate:time,assignedDate:time,reviewedDate:time,lastEditedDate:time,closedDate:time,deleted:bool'));
|
||||
$this->send(200, $this->format($story, 'openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,reviewedBy:user,reviewedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,deleted:bool,mailto:userList'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,67 @@ class storyEntry extends Entry
|
||||
*/
|
||||
public function get($storyID)
|
||||
{
|
||||
$this->resetOpenApp($this->param('tab', 'product'));
|
||||
|
||||
$control = $this->loadController('story', 'view');
|
||||
$control->view($storyID);
|
||||
|
||||
$data = $this->getData();
|
||||
$data = $this->getData();
|
||||
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$story = $data->data->story;
|
||||
$this->send(200, $this->format($story, 'openedDate:time,assignedDate:time,reviewedDate:time,lastEditedDate:time,closedDate:time'));
|
||||
|
||||
if(!empty($story->children)) $story->children = array_values((array)$story->children);
|
||||
if(isset($story->planTitle)) $story->planTitle = array_values((array)$story->planTitle);
|
||||
if($story->parent > 0) $story->parentPri = $this->dao->select('pri')->from(TABLE_STORY)->where('id')->eq($story->parent)->fetch('pri');
|
||||
|
||||
/* Set product name */
|
||||
$story->productName = $data->data->product->name;
|
||||
|
||||
/* Set module title */
|
||||
$moduleTitle = '';
|
||||
if(empty($story->module)) $moduleTitle = '/';
|
||||
if($story->module)
|
||||
{
|
||||
$modulePath = $data->data->modulePath;
|
||||
foreach($modulePath as $key => $module)
|
||||
{
|
||||
$moduleTitle .= $module->name;
|
||||
if(isset($modulePath[$key + 1])) $moduleTitle .= '/';
|
||||
}
|
||||
}
|
||||
$story->moduleTitle = $moduleTitle;
|
||||
|
||||
$storyTasks = array();
|
||||
foreach($story->tasks as $executionTasks)
|
||||
{
|
||||
foreach($executionTasks as $task)
|
||||
{
|
||||
if(!isset($data->data->executions->{$task->execution})) continue;
|
||||
$storyTasks[] = $this->filterFields($task, 'id,name,type');
|
||||
}
|
||||
}
|
||||
$story->tasks = $storyTasks;
|
||||
|
||||
$story->bugs = array();
|
||||
foreach($data->data->bugs as $bug) $story->bugs[] = $this->filterFields($bug, 'id,title');
|
||||
|
||||
$story->cases = array();
|
||||
foreach($data->data->cases as $case) $story->cases[] = $this->filterFields($case, 'id,title');
|
||||
|
||||
$story->requirements = array();
|
||||
foreach($data->data->relations as $relation) $story->requirements[] = $this->filterFields($relation, 'id,title');
|
||||
|
||||
$story->actions = $this->loadModel('action')->processActionForAPI($data->data->actions, $data->data->users, $this->lang->story);
|
||||
|
||||
$preAndNext = $data->data->preAndNext;
|
||||
$story->preAndNext = array();
|
||||
$story->preAndNext['pre'] = $preAndNext->pre ? $preAndNext->pre->id : '';
|
||||
$story->preAndNext['next'] = $preAndNext->next ? $preAndNext->next->id : '';
|
||||
|
||||
$this->send(200, $this->format($story, 'openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,reviewedBy:user,reviewedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,deleted:bool,mailto:userList'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +104,7 @@ class storyEntry extends Entry
|
||||
|
||||
$this->getData();
|
||||
$story = $this->story->getByID($storyID);
|
||||
$this->sendSuccess(200, $this->format($story, 'openedDate:time,assignedDate:time,reviewedDate:time,lastEditedDate:time,closedDate:time,deleted:bool'));
|
||||
$this->send(200, $this->format($story, 'openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,reviewedBy:user,reviewedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,deleted:bool,mailto:userList'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,12 +35,13 @@ class storyChangeEntry extends Entry
|
||||
}
|
||||
|
||||
$control = $this->loadController('story', 'change');
|
||||
$this->requireFields('title,spec');
|
||||
$this->requireFields('title,spec,verify');
|
||||
|
||||
$control->change($storyID);
|
||||
|
||||
|
||||
$data = $this->getData();
|
||||
if($data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$story = $this->loadModel('story')->getByID($storyID);
|
||||
|
||||
|
||||
@@ -39,6 +39,38 @@ class tabsEntry extends baseEntry
|
||||
$menus[] = $menu;
|
||||
}
|
||||
}
|
||||
elseif($moduleName == 'product')
|
||||
{
|
||||
$this->app->loadLang('product');
|
||||
$tabs = array('story', 'plan', 'project', 'release', 'requirement', 'doc', 'view');
|
||||
|
||||
foreach($tabs as $menuKey)
|
||||
{
|
||||
if($menuKey == 'requirement' and empty($this->config->URAndSR)) continue;
|
||||
if(isset($this->lang->product->menu->$menuKey))
|
||||
{
|
||||
list($label, $module, $method) = explode('|', $this->lang->product->menu->$menuKey['link']);
|
||||
if(!common::hasPriv($module, $method)) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!common::hasPriv('product', $menuKey)) continue;
|
||||
}
|
||||
|
||||
$label = zget($this->lang->product, $menuKey, '');
|
||||
if($menuKey == 'view') $label = $this->lang->overview;
|
||||
if($menuKey == 'doc') $label = $this->lang->doc->common;
|
||||
if($menuKey == 'project') $label = $this->lang->project->common;
|
||||
if($menuKey == 'story') $label = $this->lang->createObjects['story'];
|
||||
if($menuKey == 'requirement') $label = $this->lang->URCommon;
|
||||
|
||||
$menu = new stdclass();
|
||||
$menu->code = $menuKey;
|
||||
$menu->name = $label;
|
||||
|
||||
$menus[] = $menu;
|
||||
}
|
||||
}
|
||||
|
||||
$this->send(200, array('tabs' => $menus));
|
||||
}
|
||||
|
||||
+61
-6
@@ -20,19 +20,74 @@ class taskEntry extends Entry
|
||||
*/
|
||||
public function get($taskID)
|
||||
{
|
||||
$this->resetOpenApp($this->param('tab', 'execution'));
|
||||
|
||||
$control = $this->loadController('task', 'view');
|
||||
$control->view($taskID);
|
||||
|
||||
$data = $this->getData();
|
||||
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail')
|
||||
{
|
||||
return isset($data->code) and $data->code == 404 ? $this->send404() : $this->sendError(400, $data->message);
|
||||
}
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$task = $data->data->task;
|
||||
$this->send(200, $this->format($task, 'openedDate:time,assignedDate:time,realStarted:time,finishedDate:time,canceledDate:time,closedDate:time,lastEditedDate:time,deleted:bool'));
|
||||
|
||||
if(!empty($task->children)) $task->children = array_values((array)$task->children);
|
||||
if($task->parent > 0) $task->parentPri = $this->dao->select('pri')->from(TABLE_TASK)->where('id')->eq($task->parent)->fetch('pri');
|
||||
|
||||
/* Set execution name */
|
||||
$task->executionName = $data->data->execution->name;
|
||||
|
||||
/* Set module title */
|
||||
$moduleTitle = '';
|
||||
if(empty($task->module)) $moduleTitle = '/';
|
||||
if($task->module)
|
||||
{
|
||||
$modulePath = $data->data->modulePath;
|
||||
foreach($modulePath as $key => $module)
|
||||
{
|
||||
$moduleTitle .= $module->name;
|
||||
if(isset($modulePath[$key + 1])) $moduleTitle .= '/';
|
||||
}
|
||||
}
|
||||
$task->moduleTitle = $moduleTitle;
|
||||
|
||||
$queryAccounts = array();
|
||||
if($task->assignedTo) $queryAccounts[$task->assignedTo] = $task->assignedTo;
|
||||
if(!empty($task->team))
|
||||
{
|
||||
foreach($task->team as $account => $team) $queryAccounts[$account] = $account;
|
||||
}
|
||||
$usersWithAvatar = $this->loadModel('user')->getListByAccounts($queryAccounts, 'account');
|
||||
|
||||
if(!empty($task->team))
|
||||
{
|
||||
$teams = array();
|
||||
foreach($task->team as $account => $team)
|
||||
{
|
||||
$user = zget($usersWithAvatar, $account, '');
|
||||
$team->realname = $user ? $user->realname : $account;
|
||||
$team->avatar = $user ? $user->avatar : '';
|
||||
$team->estimate = round($team->estimate, 1);
|
||||
$team->consumed = round($team->consumed, 1);
|
||||
$team->left = round($team->left, 1);
|
||||
|
||||
$allHours = $team->consumed + $team->left;
|
||||
$team->progress = empty($allHours) ? 0 : round($team->consumed / $allHours * 100, 1);
|
||||
|
||||
$teams[] = $team;
|
||||
}
|
||||
$task->team = $teams;
|
||||
}
|
||||
|
||||
$task->actions = $this->loadModel('action')->processActionForAPI($data->data->actions, $data->data->users, $this->lang->task);
|
||||
|
||||
$preAndNext = $data->data->preAndNext;
|
||||
$task->preAndNext = array();
|
||||
$task->preAndNext['pre'] = $preAndNext->pre ? $preAndNext->pre->id : '';
|
||||
$task->preAndNext['next'] = $preAndNext->next ? $preAndNext->next->id : '';
|
||||
|
||||
$this->send(200, $this->format($task, 'deadline:date,openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,realStarted:time,finishedBy:user,finishedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,lastEditedBy:user,lastEditedDate:time,deleted:bool,mailto:userList'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,7 +110,7 @@ class taskEntry extends Entry
|
||||
|
||||
$this->getData();
|
||||
$task = $this->task->getByID($taskID);
|
||||
$this->send(200, $this->format($task, 'openedDate:time,assignedDate:time,realStarted:time,finishedDate:time,canceledDate:time,closedDate:time,lastEditedDate:time'));
|
||||
$this->send(200, $this->format($task, 'deadline:date,openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,realStarted:time,finishedBy:user,finishedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,lastEditedBy:user,lastEditedDate:time,deleted:bool,mailto:userList'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,9 +29,10 @@ class taskAssignToEntry extends Entry
|
||||
$this->requireFields('assignedTo');
|
||||
|
||||
$control->assignTo($task->execution, $taskID);
|
||||
|
||||
|
||||
$data = $this->getData();
|
||||
if($data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$task = $this->loadModel('task')->getByID($taskID);
|
||||
|
||||
|
||||
@@ -34,9 +34,10 @@ class taskFinishEntry extends Entry
|
||||
$control = $this->loadController('task', 'finish');
|
||||
$this->requireFields('assignedTo,currentConsumed,realStarted,finishedDate');
|
||||
$control->finish($taskID);
|
||||
|
||||
|
||||
$data = $this->getData();
|
||||
if($data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$task = $this->loadModel('task')->getByID($taskID);
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ class tasksEntry extends entry
|
||||
{
|
||||
/* Get tasks by execution. */
|
||||
$control = $this->loadController('execution', 'task');
|
||||
$control->task($executionID, $this->param('status', 'all'), 0, $this->param('order', ''), $this->param('total', 0), $this->param('limit', 100), $this->param('page', 1));
|
||||
$control->task($executionID, $this->param('status', 'all'), 0, $this->param('order', 'id_desc'), 0, $this->param('limit', 100), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
}
|
||||
|
||||
@@ -42,13 +42,13 @@ class tasksEntry extends entry
|
||||
$result = array();
|
||||
foreach($tasks as $task)
|
||||
{
|
||||
$result[] = $this->format($task, 'openedDate:time,assignedDate:time,realStarted:time,finishedDate:time,canceledDate:time,closedDate:time,lastEditedDate:time,deleted:bool');
|
||||
if(isset($task->children)) $task->children = array_values((array)$task->children);
|
||||
$result[] = $this->format($task, 'deadline:date,openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,realStarted:time,finishedBy:user,finishedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,lastEditedBy:user,lastEditedDate:time,deleted:bool,mailto:userList');
|
||||
}
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'tasks' => $result));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
|
||||
@@ -77,6 +77,6 @@ class tasksEntry extends entry
|
||||
|
||||
$task = $this->loadModel('task')->getByID($data->id);
|
||||
|
||||
$this->send(201, $this->format($task, 'openedDate:time,assignedDate:time,realStarted:time,finishedDate:time,canceledDate:time,closedDate:time,lastEditedDate:time'));
|
||||
$this->send(201, $this->format($task, 'deadline:date,openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,realStarted:time,finishedBy:user,finishedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,lastEditedBy:user,lastEditedDate:time,deleted:bool,mailto:userList'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,10 @@ class taskStartEntry extends Entry
|
||||
$control = $this->loadController('task', 'start');
|
||||
$this->requireFields('left');
|
||||
$control->start($taskID);
|
||||
|
||||
|
||||
$data = $this->getData();
|
||||
if($data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$task = $this->loadModel('task')->getByID($taskID);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class testcaseEntry extends entry
|
||||
class testcaseEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
@@ -25,13 +25,53 @@ class testcaseEntry extends entry
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or (isset($data->message) and $data->message == '404 Not found')) return $this->send404();
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
if(!isset($data->case)) $this->sendError(400, 'error');
|
||||
|
||||
$case = $data->case;
|
||||
$case->steps = (isset($case->steps) and !empty($case->steps)) ? array_values(get_object_vars($case->steps)) : array();
|
||||
|
||||
$this->send(200, $this->format($case, 'openedDate:time,lastEditedDate:time,lastRunDate:time,scriptedDate:date,reviewedDate:date,deleted:bool'));
|
||||
$this->send(200, $this->format($case, 'openedBy:user,openedDate:time,lastEditedBy:user,lastEditedDate:time,lastRunDate:time,scriptedDate:date,reviewedBy:user,reviewedDate:date,steps:array,deleted:bool'));
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT method.
|
||||
*
|
||||
* @param int $caseID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function put($caseID)
|
||||
{
|
||||
$oldCase = $this->loadModel('testcase')->getByID($caseID);
|
||||
|
||||
/* Set $_POST variables. */
|
||||
$fields = 'title,pri,story,type,stage,product,module,branch,precondition';
|
||||
$this->batchSetPost($fields, $oldCase);
|
||||
|
||||
/* Set steps and expects. */
|
||||
if(isset($this->requestBody->steps))
|
||||
{
|
||||
$steps = array();
|
||||
$expects = array();
|
||||
$stepType = array();
|
||||
foreach($this->requestBody->steps as $step)
|
||||
{
|
||||
$steps[] = $step->desc;
|
||||
$expects[] = $step->expect;
|
||||
$stepType[] = 'item';
|
||||
}
|
||||
$this->setPost('steps', $steps);
|
||||
$this->setPost('expects', $expects);
|
||||
$this->setPost('stepType', $stepType);
|
||||
}
|
||||
|
||||
$control = $this->loadController('testcase', 'edit');
|
||||
$control->edit($caseID);
|
||||
|
||||
$this->getData();
|
||||
$case = $this->testcase->getByID($caseID);
|
||||
$this->send(200, $this->format($case, 'openedBy:user,openedDate:time,lastEditedBy:user,lastEditedDate:time,lastRunDate:time,scriptedDate:date,reviewedBy:user,reviewedDate:date,steps:array,deleted:bool'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,28 +15,16 @@ class testcasesEntry extends entry
|
||||
* GET method.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $projectID
|
||||
* @param int $executionID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function get($productID = 0, $projectID = 0, $executionID = 0)
|
||||
public function get($productID = 0)
|
||||
{
|
||||
if(!$productID) $productID = $this->param('product', 0);
|
||||
if(!$projectID) $projectID = $this->param('project', 0);
|
||||
if(!$executionID) $executionID = $this->param('execution', 0);
|
||||
if(!$productID and !$projectID and !$executionID) return $this->sendError(400, 'Need product or project or execution id.');
|
||||
if(empty($productID)) $productID = $this->param('product', 0);
|
||||
if(empty($productID)) return $this->sendError(400, 'Need product id.');
|
||||
|
||||
if($executionID)
|
||||
{
|
||||
$control = $this->loadController('execution', 'testcase');
|
||||
$control->testcase($executionID, $this->param('status', 'all'), $this->param('order', 'id_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
$control = $this->loadController('testcase', 'browse');
|
||||
$control->browse($productID, $this->param('branch', ''), $this->param('status', 'all'), 0, $this->param('order', 'id_desc'), 0, $this->param('limit', 20), $this->param('page', 1), $projectID);
|
||||
}
|
||||
$control = $this->loadController('testcase', 'browse');
|
||||
$control->browse($productID, $this->param('branch', ''), $this->param('status', 'all'), 0, $this->param('order', 'id_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
|
||||
$data = $this->getData();
|
||||
|
||||
@@ -47,14 +35,14 @@ class testcasesEntry extends entry
|
||||
$result = array();
|
||||
foreach($cases as $case)
|
||||
{
|
||||
$result[] = $this->format($case, 'openedDate:time,lastEditedDate:time,lastRunDate:time,scriptedDate:date,reviewedDate:date,deleted:bool');
|
||||
$case->statusName = $this->lang->testcase->statusList[$case->status];
|
||||
$result[] = $this->format($case, 'openedBy:user,openedDate:time,lastEditedBy:user,lastEditedDate:time,lastRunDate:time,scriptedDate:date,reviewedBy:user,reviewedDate:date,deleted:bool');
|
||||
}
|
||||
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'testcases' => $result));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
return $this->sendError(400, 'error');
|
||||
}
|
||||
|
||||
@@ -104,6 +92,6 @@ class testcasesEntry extends entry
|
||||
$case = $this->loadModel('testcase')->getByID($data->id);
|
||||
$case->steps = (isset($case->steps) and !empty($case->steps)) ? array_values($case->steps) : array();
|
||||
|
||||
$this->send(200, $this->format($case, 'openedDate:time,lastEditedDate:time,lastRunDate:time,scriptedDate:date,reviewedDate:date,deleted:bool'));
|
||||
$this->send(200, $this->format($case, 'openedBy:user,openedDate:time,lastEditedBy:user,lastEditedDate:time,lastRunDate:time,scriptedDate:date,reviewedBy:user,reviewedDate:date,deleted:bool'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class testtaskEntry extends entry
|
||||
class testtaskEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
@@ -24,12 +24,12 @@ class testtaskEntry extends entry
|
||||
$control->view($testtaskID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
if(!isset($data->data->task)) $this->sendError(400, 'error');
|
||||
|
||||
$testtask = $data->data->task;
|
||||
|
||||
$this->send(200, $this->format($testtask, 'realFinishedDate:time'));
|
||||
$this->send(200, $this->format($testtask, 'begin:date,end:date,mailto:userList,owner:user,realFinishedDate:time'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,13 +29,13 @@ class testtasksEntry extends entry
|
||||
$data = $this->getData();
|
||||
|
||||
if(!isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
foreach($data->data->tasks as $testtask)
|
||||
{
|
||||
$result[] = $this->format($testtask, 'realFinishedDate:time');
|
||||
$result[] = $this->format($testtask, 'begin:date,end:date,mailto:userList,owner:user,realFinishedDate:time');
|
||||
}
|
||||
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'testtasks' => $result));
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class todoEntry extends entry
|
||||
class todoEntry extends entry
|
||||
{
|
||||
/**
|
||||
* GET method.
|
||||
@@ -25,7 +25,8 @@ class todoEntry extends entry
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or (isset($data->message) and $data->message == '404 Not found')) return $this->send404();
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$todo = $data->data->todo;
|
||||
$this->send(200, $this->format($todo, 'assignedDate:time,finishedDate:time,closedDate:time'));
|
||||
@@ -45,7 +46,7 @@ class todoEntry extends entry
|
||||
/* Set $_POST variables. */
|
||||
$fields = 'date,type,name,pri,desc,status,begin,end,private';
|
||||
$this->batchSetPost($fields, $oldTodo);
|
||||
|
||||
|
||||
$this->setPost('idvalue', 0);
|
||||
$this->setPost('date', $this->request('date', date("Y-m-d", strtotime($oldTodo->date))));
|
||||
$this->setPost('begin', $this->request('begin') ? str_replace(':', '', $this->request('begin')) : $oldTodo->begin);
|
||||
@@ -57,7 +58,7 @@ class todoEntry extends entry
|
||||
$data = $this->getData();
|
||||
|
||||
if(!isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$todo = $this->todo->getByID($todoID);
|
||||
$this->send(200, $this->format($todo, 'assignedDate:time,finishedDate:time,closedDate:time'));
|
||||
|
||||
@@ -24,7 +24,8 @@ class todoActivateEntry extends Entry
|
||||
$control->activate($todoID);
|
||||
|
||||
$data = $this->getData();
|
||||
if($data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$todo = $this->loadModel('todo')->getByID($todoID);
|
||||
$this->send(200, $this->format($todo, 'assignedDate:time,finishedDate:time,closedDate:time'));
|
||||
|
||||
@@ -24,7 +24,8 @@ class todoFinishEntry extends Entry
|
||||
$control->finish($todoID);
|
||||
|
||||
$data = $this->getData();
|
||||
if($data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(!$data or !isset($data->status)) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$todo = $this->loadModel('todo')->getByID($todoID);
|
||||
$this->send(200, $this->format($todo, 'assignedDate:time,finishedDate:time,closedDate:time'));
|
||||
|
||||
@@ -24,7 +24,7 @@ class todosEntry extends entry
|
||||
$data = $this->getData();
|
||||
|
||||
if(!isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
|
||||
+103
-9
@@ -14,7 +14,7 @@ class userEntry extends Entry
|
||||
/**
|
||||
* GET method.
|
||||
*
|
||||
* @param int $userID
|
||||
* @param int|string $userID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -23,6 +23,13 @@ class userEntry extends Entry
|
||||
/* Get my info defaultly. */
|
||||
if(!$userID) return $this->getInfo($this->param('fields', ''));
|
||||
|
||||
if(!is_numeric($userID))
|
||||
{
|
||||
$user = $this->loadModel('user')->getById($userID, 'account');
|
||||
if(!$user) return $this->send404();
|
||||
$userID = $user->id;
|
||||
}
|
||||
|
||||
/* Get user by id. */
|
||||
$control = $this->loadController('user', 'profile');
|
||||
$control->profile($userID);
|
||||
@@ -71,7 +78,7 @@ class userEntry extends Entry
|
||||
$products = $this->my->getProducts('ownbyme');
|
||||
if($products)
|
||||
{
|
||||
$info->product['total'] = $products->allCount;
|
||||
$info->product['total'] = $products->unclosedCount;
|
||||
$info->product['products'] = $products->products;
|
||||
}
|
||||
break;
|
||||
@@ -95,6 +102,41 @@ class userEntry extends Entry
|
||||
$info->project['projects'] = $projects->projects;
|
||||
}
|
||||
break;
|
||||
case 'lastproject':
|
||||
$info->lastProject = array('total' => 0, 'projects' => array());
|
||||
|
||||
$control = $this->loadController('project', 'ajaxGetDropMenu');
|
||||
$control->ajaxGetDropMenu(0, 'project', 'index');
|
||||
$data = $this->getData();
|
||||
|
||||
if($data->status == 'success')
|
||||
{
|
||||
$myProjects['owner'] = array();
|
||||
$myProjects['other'] = array();
|
||||
foreach($data->data->projects as $programID => $programProjects)
|
||||
{
|
||||
foreach($programProjects as $project)
|
||||
{
|
||||
if($project->status == 'closed') continue;
|
||||
|
||||
$project = $this->filterFields($project, 'id,model,type,name,code,parent,status,PM');
|
||||
if($project->PM == $this->app->user->account)
|
||||
{
|
||||
$myProjects['owner'][] = $project;
|
||||
}
|
||||
else
|
||||
{
|
||||
$myProjects['other'][] = $project;
|
||||
}
|
||||
}
|
||||
}
|
||||
$lastProjects = array_merge($myProjects['owner'], $myProjects['other']);
|
||||
$lastProjects = array_slice($lastProjects, 0, 3);
|
||||
|
||||
$info->lastProject['total'] = count($lastProjects);
|
||||
$info->lastProject['projects'] = $lastProjects;
|
||||
}
|
||||
break;
|
||||
case 'execution':
|
||||
$info->execution = array('total' => 0, 'executions' => array());
|
||||
if(!common::hasPriv('my', 'execution')) break;
|
||||
@@ -109,6 +151,41 @@ class userEntry extends Entry
|
||||
$info->execution['executions'] = array_values((array)$data->data->executions);
|
||||
}
|
||||
break;
|
||||
case 'lastexecution':
|
||||
$info->lastExecution = array('total' => 0, 'executions' => array());
|
||||
|
||||
$control = $this->loadController('execution', 'ajaxGetDropMenu');
|
||||
$control->ajaxGetDropMenu(0, 'execution', 'browse', '');
|
||||
$data = $this->getData();
|
||||
|
||||
$account = $this->app->user->account;
|
||||
if($data->status == 'success')
|
||||
{
|
||||
$myExecutions['owner'] = array();
|
||||
$myExecutions['other'] = array();
|
||||
foreach($data->data->executions as $projectID => $projectExecutions)
|
||||
{
|
||||
foreach($projectExecutions as $execution)
|
||||
{
|
||||
if($execution->status == 'done' or $execution->status == 'closed') continue;
|
||||
|
||||
if($execution->PM == $account or isset($execution->teams->$account))
|
||||
{
|
||||
$myExecutions['owner'][] = $this->filterFields($execution, 'id,model,type,name,code,parent,status,PM');
|
||||
}
|
||||
else
|
||||
{
|
||||
$myExecutions['other'][] = $this->filterFields($execution, 'id,model,type,name,code,parent,status,PM');
|
||||
}
|
||||
}
|
||||
}
|
||||
$lastExecutions = array_merge($myExecutions['owner'], $myExecutions['other']);
|
||||
$lastExecutions = array_slice($lastExecutions, 0, 3);
|
||||
|
||||
$info->lastExecution['total'] = count($lastExecutions);
|
||||
$info->lastExecution['executions'] = $lastExecutions;
|
||||
}
|
||||
break;
|
||||
case 'actions':
|
||||
$info->actions = $this->my->getActions();
|
||||
break;
|
||||
@@ -144,7 +221,8 @@ class userEntry extends Entry
|
||||
if($bug->status == 'active' and $bug->confirmed) $status = array('code' => 'confirmed', 'name' => $this->lang->bug->labelConfirmed);
|
||||
if($bug->resolution == 'postponed') $status = array('code' => 'postponed', 'name' => $this->lang->bug->labelPostponed);
|
||||
if(!empty($bug->delay)) $status = array('code' => 'delay', 'name' => $this->lang->bug->overdueBugs);
|
||||
$bug->status = $status;
|
||||
$bug->status = $status['code'];
|
||||
$bug->statusName = $status['name'];
|
||||
|
||||
$bugs[$bug->id] = $bug;
|
||||
}
|
||||
@@ -154,11 +232,12 @@ class userEntry extends Entry
|
||||
->where('t1.id')->in(array_keys($bugs))
|
||||
->andWhere('t1.story')->ne('0')
|
||||
->andWhere('t1.storyVersion != t2.version')
|
||||
->fetchAll();
|
||||
->fetchPairs('id', 'id');
|
||||
foreach($storyChangeds as $bugID)
|
||||
{
|
||||
$status = array('code' => 'storyChanged', 'name' => $this->lang->bug->storyChanged);
|
||||
$bugs[$bugID]->status = $status;
|
||||
$status = array('code' => 'storyChanged', 'name' => $this->lang->bug->changed);
|
||||
$bugs[$bugID]->status = $status['code'];
|
||||
$bugs[$bugID]->statusName = $status['name'];
|
||||
}
|
||||
|
||||
$info->bug['total'] = $data->data->pager->recTotal;
|
||||
@@ -194,7 +273,7 @@ class userEntry extends Entry
|
||||
$stories = array();
|
||||
foreach($data->data->stories as $story)
|
||||
{
|
||||
$story->status = array('code' => $story->status, 'name' => $this->lang->story->statusList[$story->status]);
|
||||
$story->statusName = $this->lang->story->statusList[$story->status];
|
||||
$stories[$story->id] = $story;
|
||||
}
|
||||
|
||||
@@ -279,17 +358,25 @@ class userEntry extends Entry
|
||||
/**
|
||||
* PUT method.
|
||||
*
|
||||
* @param int $userID
|
||||
* @param int|string $userID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function put($userID)
|
||||
{
|
||||
if(!is_numeric($userID))
|
||||
{
|
||||
$user = $this->loadModel('user')->getById($userID, 'account');
|
||||
if(!$user) return $this->send404();
|
||||
$userID = $user->id;
|
||||
}
|
||||
|
||||
$oldUser = $this->loadModel('user')->getByID($userID, 'id');
|
||||
|
||||
/* Set $_POST variables. */
|
||||
$fields = 'dept,realname,email,commiter,gender';
|
||||
$this->batchSetPost($fields, $oldUser);
|
||||
$this->setPost('account', $oldUser->account);
|
||||
|
||||
if($this->request('gender') and !in_array($this->request('gender'), array('f', 'm'))) return $this->sendError(400, "The value of gendar must be 'f' or 'm'");
|
||||
|
||||
@@ -310,12 +397,19 @@ class userEntry extends Entry
|
||||
/**
|
||||
* DELETE method.
|
||||
*
|
||||
* @param int $userID
|
||||
* @param int|string $userID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function delete($userID)
|
||||
{
|
||||
if(!is_numeric($userID))
|
||||
{
|
||||
$user = $this->loadModel('user')->getById($userID, 'account');
|
||||
if(!$user) return $this->send404();
|
||||
$userID = $user->id;
|
||||
}
|
||||
|
||||
$this->setPost('verifyPassword', md5($this->app->user->password . $this->app->session->rand));
|
||||
|
||||
$control = $this->loadController('user', 'delete');
|
||||
|
||||
@@ -73,7 +73,7 @@ class usersEntry extends entry
|
||||
$control->create();
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
if(isset($data->result) and !isset($data->id)) return $this->sendError(400, $data->message);
|
||||
|
||||
$user = $this->loadModel('user')->getByID($data->id, 'id');
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
chdir(dirname(dirname(dirname(__FILE__))));
|
||||
|
||||
include './framework/router.class.php';
|
||||
include './framework/control.class.php';
|
||||
include './framework/model.class.php';
|
||||
include './framework/helper.class.php';
|
||||
|
||||
/**
|
||||
* Gen api data
|
||||
*
|
||||
* @param string $fileName
|
||||
* @param array $data
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function genData($fileName, $data)
|
||||
{
|
||||
global $app;
|
||||
|
||||
$dataRoot = $app->getAppRoot() . 'db' . DS . 'api' . DS;
|
||||
$file = fopen($dataRoot . $fileName, 'w');
|
||||
|
||||
fwrite($file, serialize($data));
|
||||
fclose($file);
|
||||
}
|
||||
|
||||
/* Gen demo data to db/api. */
|
||||
$app = router::createApp('pms', dirname(dirname(dirname(__FILE__))), 'router');
|
||||
$dao = $app->loadClass('dao');
|
||||
|
||||
$structs = $dao->select('*')->from(TABLE_APISTRUCT)->fetchAll();;
|
||||
$structSpecs = $dao->select('*')->from(TABLE_APISTRUCT_SPEC)->fetchAll();
|
||||
$apis = $dao->select('*')->from(TABLE_API)->fetchAll();
|
||||
$apiSpecs = $dao->select('*')->from(TABLE_API_SPEC)->fetchAll();
|
||||
$modules = $dao->select('*')->from(TABLE_MODULE)->where('type')->eq('api')->fetchAll();
|
||||
|
||||
genData('apistruct', $structs);
|
||||
genData('apistruct_spec', $structSpecs);
|
||||
genData('api', $apis);
|
||||
genData('apispec', $apiSpecs);
|
||||
genData('module', $modules);
|
||||
+1
-1
@@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}}
|
||||
if(!function_exists('getWebRoot')){function getWebRoot(){}}
|
||||
|
||||
/* 基本设置。Basic settings. */
|
||||
$config->version = '15.7'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
|
||||
$config->version = '16.0.beta1'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
|
||||
$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP.
|
||||
$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time.
|
||||
$config->timezone = 'Asia/Shanghai'; // 时区设置。 The time zone setting, for more see http://www.php.net/manual/en/timezones.php.
|
||||
|
||||
+36
-15
@@ -63,6 +63,7 @@ $filter->search = new stdclass();
|
||||
$filter->gitlab = new stdclass();
|
||||
$filter->mr = new stdclass();
|
||||
$filter->ci = new stdclass();
|
||||
$filter->tree = new stdclass();
|
||||
|
||||
$filter->block->default = new stdclass();
|
||||
$filter->block->main = new stdclass();
|
||||
@@ -78,6 +79,7 @@ $filter->doc->create = new stdclass();
|
||||
$filter->doc->browse = new stdclass();
|
||||
$filter->doc->alllibs = new stdclass();
|
||||
$filter->doc->objectlibs = new stdclass();
|
||||
$filter->doc->tablecontents = new stdclass();
|
||||
$filter->doc->showfiles = new stdclass();
|
||||
$filter->doc->default = new stdclass();
|
||||
$filter->api->index = new stdClass();
|
||||
@@ -92,6 +94,8 @@ $filter->product->default = new stdclass();
|
||||
$filter->product->index = new stdclass();
|
||||
$filter->product->export = new stdclass();
|
||||
$filter->product->project = new stdclass();
|
||||
$filter->product->roadmap = new stdclass();
|
||||
$filter->product->dynamic = new stdclass();
|
||||
$filter->branch->default = new stdclass();
|
||||
$filter->program->default = new stdclass();
|
||||
$filter->program->pgmproject = new stdclass();
|
||||
@@ -112,6 +116,7 @@ $filter->qa->default = new stdclass();
|
||||
$filter->story->create = new stdclass();
|
||||
$filter->story->export = new stdclass();
|
||||
$filter->story->batchcreate = new stdclass();
|
||||
$filter->story->track = new stdclass();
|
||||
$filter->sso->getbindusers = new stdclass();
|
||||
$filter->sso->gettodolist = new stdclass();
|
||||
$filter->sso->getuserpairs = new stdclass();
|
||||
@@ -146,8 +151,10 @@ $filter->search->index = new stdclass();
|
||||
$filter->gitlab->webhook = new stdclass();
|
||||
$filter->gitlab->importissue = new stdclass();
|
||||
$filter->mr->diff = new stdclass();
|
||||
$filter->mr->browse = new stdclass();
|
||||
$filter->ci->checkCompileStatus = new stdclass();
|
||||
$filter->execution->export = new stdclass();
|
||||
$filter->tree->browse = new stdclass();
|
||||
|
||||
$filter->my->work->cookie['pagerMyTask'] = 'int';
|
||||
$filter->my->work->cookie['pagerMyRequirement'] = 'int';
|
||||
@@ -164,16 +171,16 @@ $filter->my->contribute->cookie['pagerMyTestcase'] = 'int';
|
||||
$filter->my->contribute->cookie['pagerMyTesttask'] = 'int';
|
||||
$filter->my->contribute->cookie['pagerMyDoc'] = 'int';
|
||||
|
||||
$filter->bug->batchcreate->cookie['preBranch'] = 'int';
|
||||
$filter->bug->batchcreate->cookie['preBranch'] = 'reg::word';
|
||||
$filter->bug->browse->cookie['bugModule'] = 'int';
|
||||
$filter->bug->browse->cookie['bugBranch'] = 'int';
|
||||
$filter->bug->browse->cookie['treeBranch'] = 'int';
|
||||
$filter->bug->browse->cookie['preBranch'] = 'int';
|
||||
$filter->bug->browse->cookie['treeBranch'] = 'reg::word';
|
||||
$filter->bug->browse->cookie['preBranch'] = 'reg::word';
|
||||
$filter->bug->browse->cookie['qaBugOrder'] = 'reg::orderBy';
|
||||
$filter->bug->browse->cookie['windowWidth'] = 'int';
|
||||
$filter->bug->default->cookie['lastProduct'] = 'int';
|
||||
$filter->bug->default->cookie['preProductID'] = 'int';
|
||||
$filter->bug->create->cookie['preBranch'] = 'int';
|
||||
$filter->bug->create->cookie['preBranch'] = 'reg::word';
|
||||
$filter->bug->create->cookie['lastBugModule'] = 'int';
|
||||
$filter->bug->export->cookie['checkedItem'] = 'reg::checked';
|
||||
|
||||
@@ -183,9 +190,13 @@ $filter->doc->create->cookie['lastDocModule'] = 'int';
|
||||
$filter->doc->browse->cookie['browseType'] = 'reg::browseType';
|
||||
$filter->doc->alllibs->cookie['browseType'] = 'reg::browseType';
|
||||
$filter->doc->objectlibs->cookie['browseType'] = 'reg::browseType';
|
||||
$filter->doc->objectlibs->cookie['preProductID'] = 'int';
|
||||
$filter->doc->objectlibs->cookie['preBranch'] = 'reg::word';
|
||||
$filter->doc->default->cookie['from'] = 'code';
|
||||
$filter->doc->default->cookie['product'] = 'int';
|
||||
$filter->doc->showfiles->cookie['docFilesViewType'] = 'code';
|
||||
$filter->doc->tablecontents->cookie['preProductID'] = 'int';
|
||||
$filter->doc->tablecontents->cookie['preBranch'] = 'reg::word';
|
||||
$filter->api->index->get['libID'] = 'int';
|
||||
$filter->api->index->get['module'] = 'int';
|
||||
$filter->api->index->get['apiID'] = 'int';
|
||||
@@ -197,24 +208,26 @@ $filter->api->edit->get['libID'] = 'int';
|
||||
$filter->api->edit->get['module'] = 'int';
|
||||
$filter->api->edit->get['apiID'] = 'int';
|
||||
|
||||
|
||||
$filter->file->download->cookie[$config->sessionVar] = 'code';
|
||||
|
||||
$filter->mail->ztcloud->cookie['ztCloudLicense'] = 'equal::yes';
|
||||
|
||||
$filter->product->browse->cookie['preBranch'] = 'int';
|
||||
$filter->product->browse->cookie['preBranch'] = 'reg::word';
|
||||
$filter->product->browse->cookie['preProductID'] = 'int';
|
||||
$filter->product->browse->cookie['productStoryOrder'] = 'reg::orderBy';
|
||||
$filter->product->browse->cookie['storyModule'] = 'int';
|
||||
$filter->product->browse->cookie['storyBranch'] = 'int';
|
||||
$filter->product->browse->cookie['treeBranch'] = 'int';
|
||||
$filter->product->browse->cookie['treeBranch'] = 'reg::word';
|
||||
$filter->product->default->cookie['lastProduct'] = 'int';
|
||||
$filter->product->default->cookie['preProductID'] = 'int';
|
||||
$filter->product->index->cookie['preBranch'] = 'int';
|
||||
$filter->product->index->cookie['preBranch'] = 'reg::word';
|
||||
$filter->product->export->cookie['checkedItem'] = 'reg::checked';
|
||||
$filter->product->project->cookie['involved'] = 'code';
|
||||
$filter->product->project->cookie['preBranch'] = 'reg::word';
|
||||
$filter->product->roadmap->cookie['preBranch'] = 'reg::word';
|
||||
$filter->product->dynamic->cookie['preBranch'] = 'reg::word';
|
||||
|
||||
$filter->branch->default->cookie['preBranch'] = 'int';
|
||||
$filter->branch->default->cookie['preBranch'] = 'reg::word';
|
||||
|
||||
$filter->program->default->cookie['lastPGM'] = 'int';
|
||||
$filter->program->default->cookie['lastPRJ'] = 'int';
|
||||
@@ -245,12 +258,14 @@ $filter->projectstory->story->cookie['storyModuleParam'] = 'int';
|
||||
$filter->projectstory->story->cookie['pagerProductBrowse'] = 'int';
|
||||
|
||||
$filter->qa->default->cookie['lastProduct'] = 'int';
|
||||
$filter->qa->default->cookie['preBranch'] = 'int';
|
||||
$filter->qa->default->cookie['preBranch'] = 'reg::word';
|
||||
$filter->qa->default->cookie['preProductID'] = 'int';
|
||||
|
||||
$filter->story->create->cookie['lastStoryModule'] = 'int';
|
||||
$filter->story->batchcreate->cookie['preProductID'] = 'int';
|
||||
$filter->story->export->cookie['checkedItem'] = 'reg::checked';
|
||||
$filter->story->track->cookie['preBranch'] = 'reg::word';
|
||||
$filter->story->track->cookie['preProductID'] = 'int';
|
||||
|
||||
$filter->task->create->cookie['lastTaskModule'] = 'int';
|
||||
$filter->task->export->cookie['checkedItem'] = 'reg::checked';
|
||||
@@ -264,12 +279,12 @@ $filter->execution->export->cookie['checkedItem'] = 'reg::checked';
|
||||
|
||||
$filter->testcase->browse->cookie['caseModule'] = 'int';
|
||||
$filter->testcase->browse->cookie['caseSuite'] = 'int';
|
||||
$filter->testcase->browse->cookie['preBranch'] = 'int';
|
||||
$filter->testcase->browse->cookie['preBranch'] = 'reg::word';
|
||||
$filter->testcase->create->cookie['lastCaseModule'] = 'int';
|
||||
$filter->testcase->default->cookie['lastProduct'] = 'int';
|
||||
$filter->testcase->default->cookie['preProductID'] = 'int';
|
||||
$filter->testcase->export->cookie['checkedItem'] = 'reg::checked';
|
||||
$filter->testcase->groupcase->cookie['preBranch'] = 'int';
|
||||
$filter->testcase->groupcase->cookie['preBranch'] = 'reg::word';
|
||||
|
||||
$filter->testreport->default->cookie['lastProduct'] = 'int';
|
||||
$filter->testreport->default->cookie['lastProject'] = 'int';
|
||||
@@ -282,7 +297,7 @@ $filter->testsuite->default->cookie['preProductID'] = 'int';
|
||||
$filter->testsuite->library->cookie['libCaseModule'] = 'int';
|
||||
$filter->testsuite->library->cookie['preCaseLibID'] = 'int';
|
||||
|
||||
$filter->testtask->browse->cookie['preBranch'] = 'int';
|
||||
$filter->testtask->browse->cookie['preBranch'] = 'reg::word';
|
||||
$filter->testtask->cases->cookie['preTaskID'] = 'int';
|
||||
$filter->testtask->cases->cookie['taskCaseModule'] = 'int';
|
||||
$filter->testtask->default->cookie['lastProduct'] = 'int';
|
||||
@@ -356,8 +371,8 @@ $filter->repo->diff->cookie['repoPairs'] = 'array';
|
||||
$filter->repo->view->cookie['repoPairs'] = 'array';
|
||||
$filter->repo->ajaxsynccommit->cookie['syncBranch'] = 'reg::any';
|
||||
|
||||
$filter->webhook->bind->get['selectedDepts'] = 'reg::checked';
|
||||
$filter->webhook->bind->cookie['selectedDepts'] = 'reg::checked';
|
||||
$filter->webhook->bind->get['selectedDepts'] = 'reg::any';
|
||||
$filter->webhook->bind->cookie['selectedDepts'] = 'reg::any';
|
||||
|
||||
$filter->search->index->get['words'] = 'reg::any';
|
||||
$filter->search->index->get['type'] = 'code';
|
||||
@@ -375,4 +390,10 @@ $filter->gitlab->importissue->get['repo'] = 'int';
|
||||
|
||||
$filter->mr->diff->cookie['arrange'] = 'reg::word';
|
||||
|
||||
$filter->mr->browse->get['mode'] = 'string';
|
||||
$filter->mr->browse->get['param'] = 'string';
|
||||
|
||||
$filter->ci->checkCompileStatus->get['gitlabOnly'] = 'string';
|
||||
|
||||
$filter->tree->browse->cookie['preProductID'] = 'int';
|
||||
$filter->tree->browse->cookie['preBranch'] = 'reg::word';
|
||||
|
||||
+59
-31
@@ -4,10 +4,12 @@
|
||||
*/
|
||||
$routes = array();
|
||||
|
||||
$routes['/tokens'] = 'tokens';
|
||||
$routes['/langs'] = 'langs';
|
||||
$routes['/views'] = 'views';
|
||||
$routes['/groups'] = 'groups';
|
||||
$routes['/tokens'] = 'tokens';
|
||||
$routes['/langs'] = 'langs';
|
||||
$routes['/views'] = 'views';
|
||||
$routes['/groups'] = 'groups';
|
||||
$routes['/ping'] = 'ping';
|
||||
$routes['/comments'] = 'comments';
|
||||
|
||||
$routes['/tabs/:module'] = 'tabs';
|
||||
|
||||
@@ -24,39 +26,47 @@ $routes['/products/:id'] = 'product';
|
||||
$routes['/productlines'] = 'productLines';
|
||||
$routes['/productlines/:id'] = 'productLine';
|
||||
|
||||
$routes['/productplans'] = 'productPlans';
|
||||
$routes['/products/:id/plans'] = 'productPlans';
|
||||
$routes['/productplans/:id'] = 'productPlan';
|
||||
$routes['/productplans'] = 'productPlans';
|
||||
$routes['/products/:id/plans'] = 'productPlans';
|
||||
$routes['/productplans/:id'] = 'productPlan';
|
||||
$routes['/productplans/:id/linkstories'] = 'productPlanLinkStories';
|
||||
$routes['/productplans/:id/unlinkstories'] = 'productPlanUnlinkStories';
|
||||
$routes['/productplans/:id/linkbugs'] = 'productPlanLinkBugs';
|
||||
$routes['/productplans/:id/unlinkbugs'] = 'productPlanUnlinkBugs';
|
||||
|
||||
$routes['/releases'] = 'releases';
|
||||
$routes['/product/:id/releases'] = 'releases';
|
||||
$routes['/projects/:id/releases'] = 'projectreleases';
|
||||
$routes['/products/:id/releases'] = 'releases';
|
||||
$routes['/projects/:id/releases'] = 'projectReleases';
|
||||
$routes['/releases/:id'] = 'release';
|
||||
|
||||
$routes['/stories'] = 'stories';
|
||||
$routes['/products/:id/stories'] = 'stories';
|
||||
$routes['/projects/:id/stories'] = 'projectStories';
|
||||
$routes['/executions/:id/stories'] = 'executionStories';
|
||||
$routes['/stories/:id'] = 'story';
|
||||
$routes['/stories/:id/change'] = 'storyChange';
|
||||
|
||||
$routes['/products/:id/bugs'] = 'bugs';
|
||||
$routes['/bugs'] = 'bugs';
|
||||
$routes['/bugs/:id'] = 'bug';
|
||||
$routes['/products/:id/bugs'] = 'bugs';
|
||||
$routes['/projects/:id/bugs'] = 'projectBugs';
|
||||
$routes['/executions/:id/bugs'] = 'executionBugs';
|
||||
$routes['/bugs'] = 'bugs';
|
||||
$routes['/bugs/:id'] = 'bug';
|
||||
|
||||
$routes['/programs/:id/projects'] = 'projects';
|
||||
$routes['/products/:id/projects'] = 'productProjects';
|
||||
$routes['/projects'] = 'projects';
|
||||
$routes['/projects/:id'] = 'project';
|
||||
|
||||
$routes['/projects/:project/executions'] = 'executions';
|
||||
$routes['/executions'] = 'executions';
|
||||
$routes['/executions/:id'] = 'execution';
|
||||
$routes['/projects/:id/executions'] = 'executions';
|
||||
$routes['/executions'] = 'executions';
|
||||
$routes['/executions/:id'] = 'execution';
|
||||
|
||||
$routes['/executions/:execution/tasks'] = 'tasks';
|
||||
$routes['/tasks'] = 'tasks';
|
||||
$routes['/tasks/:id'] = 'task';
|
||||
$routes['/tasks/:id/assignto'] = 'taskAssignTo';
|
||||
$routes['/tasks/:id/start'] = 'taskStart';
|
||||
$routes['/tasks/:id/finish'] = 'taskFinish';
|
||||
$routes['/executions/:id/tasks'] = 'tasks';
|
||||
$routes['/tasks'] = 'tasks';
|
||||
$routes['/tasks/:id'] = 'task';
|
||||
$routes['/tasks/:id/assignto'] = 'taskAssignTo';
|
||||
$routes['/tasks/:id/start'] = 'taskStart';
|
||||
$routes['/tasks/:id/finish'] = 'taskFinish';
|
||||
|
||||
$routes['/users'] = 'users';
|
||||
$routes['/users/:id'] = 'user';
|
||||
@@ -65,23 +75,28 @@ $routes['/user'] = 'user';
|
||||
$routes['/programs'] = 'programs';
|
||||
$routes['/programs/:id'] = 'program';
|
||||
|
||||
$routes['/products/:productID/issues'] = 'productIssues';
|
||||
$routes['/projects/:projectID/issues'] = 'issues';
|
||||
$routes['/issues'] = 'issues';
|
||||
$routes['/issues/:issueID'] = 'issue';
|
||||
$routes['/programs/:id/stakeholders'] = 'stakeholders';
|
||||
|
||||
$routes['/products/:id/issues'] = 'productIssues';
|
||||
$routes['/projects/:id/issues'] = 'issues';
|
||||
$routes['/issues'] = 'issues';
|
||||
$routes['/issues/:id'] = 'issue';
|
||||
|
||||
$routes['/todos'] = 'todos';
|
||||
$routes['/todos/:id'] = 'todo';
|
||||
$routes['/todos/:id/finish'] = 'todoFinish';
|
||||
$routes['/todos/:id/activate'] = 'todoActivate';
|
||||
|
||||
$routes['/projects/:projectID/builds'] = 'builds';
|
||||
$routes['/builds'] = 'builds';
|
||||
$routes['/builds/:id'] = 'build';
|
||||
$routes['/projects/:id/builds'] = 'builds';
|
||||
$routes['/executions/:id/builds'] = 'executionBuilds';
|
||||
$routes['/builds'] = 'builds';
|
||||
$routes['/builds/:id'] = 'build';
|
||||
|
||||
$routes['/products/:id/testcases'] = 'testcases';
|
||||
$routes['/testcases'] = 'testcases';
|
||||
$routes['/testcases/:id'] = 'testcase';
|
||||
$routes['/products/:id/testcases'] = 'testcases';
|
||||
$routes['/projects/:id/testcases'] = 'projectCases';
|
||||
$routes['/executions/:id/testcases'] = 'executionCases';
|
||||
$routes['/testcases'] = 'testcases';
|
||||
$routes['/testcases/:id'] = 'testcase';
|
||||
|
||||
$routes['/projects/:projectID/testtasks'] = 'testtasks';
|
||||
$routes['/testtasks'] = 'testtasks';
|
||||
@@ -91,9 +106,20 @@ $routes['/projects/:projectID/risks'] = 'risks';
|
||||
$routes['/risks'] = 'risks';
|
||||
$routes['/risks/:id'] = 'risk';
|
||||
|
||||
$routes['/projects/:id/meetings'] = 'meetings';
|
||||
$routes['/meetings'] = 'meetings';
|
||||
$routes['/meetings/:id'] = 'meeting';
|
||||
|
||||
$routes['/departments'] = 'departments';
|
||||
$routes['/departments/:id'] = 'department';
|
||||
|
||||
$routes['/doclibs'] = 'doclibs';
|
||||
$routes['/doclibs/:id'] = 'docs';
|
||||
$routes['/docs'] = 'docs';
|
||||
$routes['/docs/:id'] = 'doc';
|
||||
|
||||
$routes['/repos'] = 'repos';
|
||||
|
||||
$routes['/reports'] = 'reports';
|
||||
|
||||
$routes['/z/folders'] = 'zfolders';
|
||||
@@ -101,4 +127,6 @@ $routes['/z/folders/:id'] = 'zfolder';
|
||||
$routes['/z/files/:id'] = 'zfile';
|
||||
$routes['/z/files/:id/content'] = 'zfileContent';
|
||||
|
||||
$routes['/gitlab/webhook'] = 'gitlabWebhook';
|
||||
|
||||
$config->routes = $routes;
|
||||
|
||||
+52
-39
@@ -142,6 +142,9 @@ $config->openMethods[] = 'my.changepassword';
|
||||
$config->openMethods[] = 'my.profile';
|
||||
$config->openMethods[] = 'my.settutorialconfig';
|
||||
$config->openMethods[] = 'doc.selectlibtype';
|
||||
$config->openMethods[] = 'sso.getfeishusso';
|
||||
$config->openMethods[] = 'sso.feishuauthen';
|
||||
$config->openMethods[] = 'sso.feishulogin';
|
||||
|
||||
/* Define the tables. */
|
||||
define('TABLE_COMPANY', '`' . $config->db->prefix . 'company`');
|
||||
@@ -167,6 +170,7 @@ define('TABLE_USERTPL', '`' . $config->db->prefix . 'usertpl`');
|
||||
define('TABLE_PRODUCT', '`' . $config->db->prefix . 'product`');
|
||||
define('TABLE_BRANCH', '`' . $config->db->prefix . 'branch`');
|
||||
define('TABLE_EXPECT', '`' . $config->db->prefix . 'expect`');
|
||||
define('TABLE_STAGE', '`' . $config->db->prefix . 'stage`');
|
||||
define('TABLE_STAKEHOLDER', '`' . $config->db->prefix . 'stakeholder`');
|
||||
define('TABLE_STORY', '`' . $config->db->prefix . 'story`');
|
||||
define('TABLE_STORYSPEC', '`' . $config->db->prefix . 'storyspec`');
|
||||
@@ -192,6 +196,8 @@ define('TABLE_BURN', '`' . $config->db->prefix . 'burn`');
|
||||
define('TABLE_BUILD', '`' . $config->db->prefix . 'build`');
|
||||
define('TABLE_ACL', '`' . $config->db->prefix . 'acl`');
|
||||
|
||||
define('TABLE_DESIGN', '`' . $config->db->prefix . 'design`');
|
||||
define('TABLE_DESIGNSPEC', '`' . $config->db->prefix . 'designspec`');
|
||||
define('TABLE_DOCLIB', '`' . $config->db->prefix . 'doclib`');
|
||||
define('TABLE_DOC', '`' . $config->db->prefix . 'doc`');
|
||||
define('TABLE_API', '`' . $config->db->prefix . 'api`');
|
||||
@@ -203,6 +209,7 @@ define('TABLE_API_LIB_RELEASE', '`' . $config->db->prefix . 'api_lib_release`');
|
||||
define('TABLE_MODULE', '`' . $config->db->prefix . 'module`');
|
||||
define('TABLE_ACTION', '`' . $config->db->prefix . 'action`');
|
||||
define('TABLE_FILE', '`' . $config->db->prefix . 'file`');
|
||||
define('TABLE_HOLIDAY', '`' . $config->db->prefix . 'holiday`');
|
||||
define('TABLE_HISTORY', '`' . $config->db->prefix . 'history`');
|
||||
define('TABLE_EXTENSION', '`' . $config->db->prefix . 'extension`');
|
||||
define('TABLE_CRON', '`' . $config->db->prefix . 'cron`');
|
||||
@@ -213,6 +220,7 @@ define('TABLE_SUITECASE', '`' . $config->db->prefix . 'suitecase`');
|
||||
define('TABLE_TESTREPORT', '`' . $config->db->prefix . 'testreport`');
|
||||
|
||||
define('TABLE_ENTRY', '`' . $config->db->prefix . 'entry`');
|
||||
define('TABLE_WEEKLYREPORT', '`' . $config->db->prefix . 'weeklyreport`');
|
||||
define('TABLE_WEBHOOK', '`' . $config->db->prefix . 'webhook`');
|
||||
define('TABLE_LOG', '`' . $config->db->prefix . 'log`');
|
||||
define('TABLE_SCORE', '`' . $config->db->prefix . 'score`');
|
||||
@@ -222,54 +230,59 @@ define('TABLE_PIPELINE', '`' . $config->db->prefix . 'pipeline`');
|
||||
define('TABLE_JOB', '`' . $config->db->prefix . 'job`');
|
||||
define('TABLE_COMPILE', '`' . $config->db->prefix . 'compile`');
|
||||
define('TABLE_MR', '`' . $config->db->prefix . 'mr`');
|
||||
define('TABLE_MRAPPROVAL', '`' . $config->db->prefix . 'mrapproval`');
|
||||
|
||||
define('TABLE_REPO', '`' . $config->db->prefix . 'repo`');
|
||||
define('TABLE_RELATION', '`' . $config->db->prefix . 'relation`');
|
||||
define('TABLE_REPOHISTORY', '`' . $config->db->prefix . 'repohistory`');
|
||||
define('TABLE_REPOFILES', '`' . $config->db->prefix . 'repofiles`');
|
||||
define('TABLE_REPOBRANCH', '`' . $config->db->prefix . 'repobranch`');
|
||||
define('TABLE_REPO', '`' . $config->db->prefix . 'repo`');
|
||||
define('TABLE_RELATION', '`' . $config->db->prefix . 'relation`');
|
||||
define('TABLE_REPOHISTORY', '`' . $config->db->prefix . 'repohistory`');
|
||||
define('TABLE_REPOFILES', '`' . $config->db->prefix . 'repofiles`');
|
||||
define('TABLE_REPOBRANCH', '`' . $config->db->prefix . 'repobranch`');
|
||||
define('TABLE_KANBANLANE', '`' . $config->db->prefix . 'kanbanlane`');
|
||||
define('TABLE_KANBANCOLUMN', '`' . $config->db->prefix . 'kanbancolumn`');
|
||||
if(!defined('TABLE_LANG')) define('TABLE_LANG', '`' . $config->db->prefix . 'lang`');
|
||||
if(!defined('TABLE_PROJECTSPEC')) define('TABLE_PROJECTSPEC', '`' . $config->db->prefix . 'projectspec`');
|
||||
|
||||
if(!defined('TABLE_SEARCHINDEX')) define('TABLE_SEARCHINDEX', $config->db->prefix . 'searchindex');
|
||||
if(!defined('TABLE_SEARCHDICT')) define('TABLE_SEARCHDICT', $config->db->prefix . 'searchdict');
|
||||
|
||||
$config->objectTables['product'] = TABLE_PRODUCT;
|
||||
$config->objectTables['productplan'] = TABLE_PRODUCTPLAN;
|
||||
$config->objectTables['story'] = TABLE_STORY;
|
||||
$config->objectTables['requirement'] = TABLE_STORY;
|
||||
$config->objectTables['release'] = TABLE_RELEASE;
|
||||
$config->objectTables['program'] = TABLE_PROJECT;
|
||||
$config->objectTables['project'] = TABLE_PROJECT;
|
||||
$config->objectTables['execution'] = TABLE_PROJECT;
|
||||
$config->objectTables['task'] = TABLE_TASK;
|
||||
$config->objectTables['build'] = TABLE_BUILD;
|
||||
$config->objectTables['bug'] = TABLE_BUG;
|
||||
$config->objectTables['case'] = TABLE_CASE;
|
||||
$config->objectTables['testcase'] = TABLE_CASE;
|
||||
$config->objectTables['testtask'] = TABLE_TESTTASK;
|
||||
$config->objectTables['testsuite'] = TABLE_TESTSUITE;
|
||||
$config->objectTables['testreport'] = TABLE_TESTREPORT;
|
||||
$config->objectTables['user'] = TABLE_USER;
|
||||
$config->objectTables['api'] = TABLE_API;
|
||||
$config->objectTables['doc'] = TABLE_DOC;
|
||||
$config->objectTables['doclib'] = TABLE_DOCLIB;
|
||||
$config->objectTables['todo'] = TABLE_TODO;
|
||||
$config->objectTables['custom'] = TABLE_LANG;
|
||||
$config->objectTables['branch'] = TABLE_BRANCH;
|
||||
$config->objectTables['module'] = TABLE_MODULE;
|
||||
$config->objectTables['caselib'] = TABLE_TESTSUITE;
|
||||
$config->objectTables['entry'] = TABLE_ENTRY;
|
||||
$config->objectTables['webhook'] = TABLE_WEBHOOK;
|
||||
$config->objectTables['stakeholder'] = TABLE_STAKEHOLDER;
|
||||
$config->objectTables['job'] = TABLE_JOB;
|
||||
$config->objectTables['team'] = TABLE_TEAM;
|
||||
$config->objectTables['pipeline'] = TABLE_PIPELINE;
|
||||
$config->objectTables['mr'] = TABLE_MR;
|
||||
$config->objectTables['product'] = TABLE_PRODUCT;
|
||||
$config->objectTables['productplan'] = TABLE_PRODUCTPLAN;
|
||||
$config->objectTables['story'] = TABLE_STORY;
|
||||
$config->objectTables['requirement'] = TABLE_STORY;
|
||||
$config->objectTables['release'] = TABLE_RELEASE;
|
||||
$config->objectTables['program'] = TABLE_PROJECT;
|
||||
$config->objectTables['project'] = TABLE_PROJECT;
|
||||
$config->objectTables['execution'] = TABLE_PROJECT;
|
||||
$config->objectTables['task'] = TABLE_TASK;
|
||||
$config->objectTables['build'] = TABLE_BUILD;
|
||||
$config->objectTables['bug'] = TABLE_BUG;
|
||||
$config->objectTables['case'] = TABLE_CASE;
|
||||
$config->objectTables['testcase'] = TABLE_CASE;
|
||||
$config->objectTables['testtask'] = TABLE_TESTTASK;
|
||||
$config->objectTables['testsuite'] = TABLE_TESTSUITE;
|
||||
$config->objectTables['testreport'] = TABLE_TESTREPORT;
|
||||
$config->objectTables['user'] = TABLE_USER;
|
||||
$config->objectTables['api'] = TABLE_API;
|
||||
$config->objectTables['doc'] = TABLE_DOC;
|
||||
$config->objectTables['doclib'] = TABLE_DOCLIB;
|
||||
$config->objectTables['todo'] = TABLE_TODO;
|
||||
$config->objectTables['custom'] = TABLE_LANG;
|
||||
$config->objectTables['branch'] = TABLE_BRANCH;
|
||||
$config->objectTables['module'] = TABLE_MODULE;
|
||||
$config->objectTables['caselib'] = TABLE_TESTSUITE;
|
||||
$config->objectTables['entry'] = TABLE_ENTRY;
|
||||
$config->objectTables['webhook'] = TABLE_WEBHOOK;
|
||||
$config->objectTables['stakeholder'] = TABLE_STAKEHOLDER;
|
||||
$config->objectTables['job'] = TABLE_JOB;
|
||||
$config->objectTables['team'] = TABLE_TEAM;
|
||||
$config->objectTables['pipeline'] = TABLE_PIPELINE;
|
||||
$config->objectTables['mr'] = TABLE_MR;
|
||||
$config->objectTables['kanbancolumn'] = TABLE_KANBANCOLUMN;
|
||||
$config->objectTables['kanbanlane'] = TABLE_KANBANLANE;
|
||||
|
||||
$config->newFeatures = array('introduction', 'tutorial', 'youngBlueTheme');
|
||||
|
||||
/* Program privs.*/
|
||||
$config->programPriv = new stdclass();
|
||||
$config->programPriv->scrum = array('product', 'story', 'productplan', 'release', 'projectrelease', 'project', 'task', 'build', 'qa', 'bug', 'testcase', 'testsuite', 'testreport', 'caselib', 'doc', 'report', 'repo', 'svn', 'git', 'search', 'tree', 'file', 'jenkins', 'gitlab', 'job', 'ci', 'branch');
|
||||
$config->programPriv->waterfall = $config->programPriv->scrum + array('workestimation', 'durationestimation', 'budget', 'programplan', 'review', 'reviewissue', 'weekly', 'milestone', 'design', 'issue', 'risk', 'auditplan', 'nc', 'cm', 'pssp');
|
||||
$config->programPriv->scrum = array('projectstory', 'projectrelease', 'project', 'build', 'bug', 'testcase', 'testreport', 'caselib', 'doc', 'repo', 'meeting', 'stakeholder');
|
||||
$config->programPriv->waterfall = array_merge($config->programPriv->scrum, array('workestimation', 'durationestimation', 'budget', 'programplan', 'review', 'reviewissue', 'weekly', 'cm', 'milestone', 'design', 'issue', 'risk', 'opportunity', 'measrecord', 'auditplan', 'trainplan', 'gapanalysis', 'pssp', 'researchplan', 'researchreport'));
|
||||
|
||||
+3195
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
a:3:{i:0;O:8:"stdClass":12:{s:2:"id";s:1:"1";s:3:"lib";s:1:"6";s:4:"name";s:4:"user";s:4:"type";s:4:"json";s:4:"desc";s:0:"";s:7:"version";s:1:"2";s:9:"attribute";s:537:"[{"field":"id","paramsType":"int","required":"","desc":"","structType":"json","sub":1,"key":"kwoq04srulxevt93a3h","children":[]},{"field":"account","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0a387on1wpuwntd","children":[]},{"field":"realname","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0i4g80qyu8lqp28","children":[]},{"field":"avatar","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0le57o2p6vxc8ov","children":[]}]";s:7:"addedBy";s:5:"admin";s:9:"addedDate";s:19:"2021-12-02 16:53:45";s:8:"editedBy";s:5:"admin";s:10:"editedDate";s:19:"2021-12-02 16:54:24";s:7:"deleted";s:1:"0";}i:1;O:8:"stdClass":12:{s:2:"id";s:1:"2";s:3:"lib";s:2:"45";s:4:"name";s:4:"user";s:4:"type";s:4:"json";s:4:"desc";s:0:"";s:7:"version";s:1:"2";s:9:"attribute";s:537:"[{"field":"id","paramsType":"int","required":"","desc":"","structType":"json","sub":1,"key":"kwoq04srulxevt93a3h","children":[]},{"field":"account","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0a387on1wpuwntd","children":[]},{"field":"realname","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0i4g80qyu8lqp28","children":[]},{"field":"avatar","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0le57o2p6vxc8ov","children":[]}]";s:7:"addedBy";s:5:"admin";s:9:"addedDate";s:19:"0000-00-00 00:00:00";s:8:"editedBy";s:5:"admin";s:10:"editedDate";s:19:"2021-12-02 16:54:24";s:7:"deleted";s:1:"0";}i:2;O:8:"stdClass":12:{s:2:"id";s:1:"3";s:3:"lib";s:2:"46";s:4:"name";s:4:"user";s:4:"type";s:4:"json";s:4:"desc";s:0:"";s:7:"version";s:1:"2";s:9:"attribute";s:537:"[{"field":"id","paramsType":"int","required":"","desc":"","structType":"json","sub":1,"key":"kwoq04srulxevt93a3h","children":[]},{"field":"account","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0a387on1wpuwntd","children":[]},{"field":"realname","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0i4g80qyu8lqp28","children":[]},{"field":"avatar","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0le57o2p6vxc8ov","children":[]}]";s:7:"addedBy";s:5:"admin";s:9:"addedDate";s:19:"2021-12-07 10:14:42";s:8:"editedBy";s:5:"admin";s:10:"editedDate";s:19:"2021-12-02 16:54:24";s:7:"deleted";s:1:"0";}}
|
||||
@@ -0,0 +1 @@
|
||||
a:4:{i:0;O:8:"stdClass":8:{s:2:"id";s:1:"1";s:4:"name";s:4:"user";s:4:"type";s:4:"json";s:4:"desc";s:0:"";s:9:"attribute";s:537:"[{"field":"id","paramsType":"int","required":"","desc":"","structType":"json","sub":1,"key":"kwoq04srulxevt93a3h","children":[]},{"field":"account","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0a387on1wpuwntd","children":[]},{"field":"realname","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0i4g80qyu8lqp28","children":[]},{"field":"avatar","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0le57o2p6vxc8ov","children":[]}]";s:7:"version";s:1:"1";s:7:"addedBy";s:5:"admin";s:9:"addedDate";s:19:"2021-12-02 16:53:45";}i:1;O:8:"stdClass":8:{s:2:"id";s:1:"2";s:4:"name";s:4:"user";s:4:"type";s:4:"json";s:4:"desc";s:0:"";s:9:"attribute";s:537:"[{"field":"id","paramsType":"int","required":"","desc":"","structType":"json","sub":1,"key":"kwoq04srulxevt93a3h","children":[]},{"field":"account","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0a387on1wpuwntd","children":[]},{"field":"realname","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0i4g80qyu8lqp28","children":[]},{"field":"avatar","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0le57o2p6vxc8ov","children":[]}]";s:7:"version";s:1:"2";s:7:"addedBy";s:5:"admin";s:9:"addedDate";s:19:"2021-12-02 16:54:24";}i:2;O:8:"stdClass":8:{s:2:"id";s:1:"3";s:4:"name";s:4:"user";s:4:"type";s:4:"json";s:4:"desc";s:0:"";s:9:"attribute";s:537:"[{"field":"id","paramsType":"int","required":"","desc":"","structType":"json","sub":1,"key":"kwoq04srulxevt93a3h","children":[]},{"field":"account","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0a387on1wpuwntd","children":[]},{"field":"realname","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0i4g80qyu8lqp28","children":[]},{"field":"avatar","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0le57o2p6vxc8ov","children":[]}]";s:7:"version";s:1:"1";s:7:"addedBy";s:5:"admin";s:9:"addedDate";s:19:"2021-12-07 10:14:42";}i:3;O:8:"stdClass":8:{s:2:"id";s:1:"4";s:4:"name";s:4:"user";s:4:"type";s:4:"json";s:4:"desc";s:0:"";s:9:"attribute";s:537:"[{"field":"id","paramsType":"int","required":"","desc":"","structType":"json","sub":1,"key":"kwoq04srulxevt93a3h","children":[]},{"field":"account","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0a387on1wpuwntd","children":[]},{"field":"realname","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0i4g80qyu8lqp28","children":[]},{"field":"avatar","paramsType":"string","required":"","desc":"","structType":"json","sub":1,"key":"kwoq0le57o2p6vxc8ov","children":[]}]";s:7:"version";s:1:"2";s:7:"addedBy";s:5:"admin";s:9:"addedDate";s:19:"2021-12-07 10:14:42";}}
|
||||
@@ -0,0 +1 @@
|
||||
a:14:{i:0;O:8:"stdClass":13:{s:2:"id";s:2:"16";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:5:"Token";s:6:"parent";s:1:"0";s:4:"path";s:4:",16,";s:5:"grade";s:1:"1";s:5:"order";s:2:"10";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}i:1;O:8:"stdClass":13:{s:2:"id";s:2:"17";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:9:"项目集";s:6:"parent";s:1:"0";s:4:"path";s:4:",17,";s:5:"grade";s:1:"1";s:5:"order";s:2:"30";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}i:2;O:8:"stdClass":13:{s:2:"id";s:2:"18";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:6:"产品";s:6:"parent";s:1:"0";s:4:"path";s:4:",18,";s:5:"grade";s:1:"1";s:5:"order";s:2:"40";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}i:3;O:8:"stdClass":13:{s:2:"id";s:2:"19";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:6:"项目";s:6:"parent";s:1:"0";s:4:"path";s:4:",19,";s:5:"grade";s:1:"1";s:5:"order";s:2:"80";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}i:4;O:8:"stdClass":13:{s:2:"id";s:2:"20";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:6:"执行";s:6:"parent";s:1:"0";s:4:"path";s:4:",20,";s:5:"grade";s:1:"1";s:5:"order";s:3:"100";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}i:5;O:8:"stdClass":13:{s:2:"id";s:2:"33";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:6:"需求";s:6:"parent";s:1:"0";s:4:"path";s:4:",33,";s:5:"grade";s:1:"1";s:5:"order";s:2:"70";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}i:6;O:8:"stdClass":13:{s:2:"id";s:2:"34";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:6:"任务";s:6:"parent";s:1:"0";s:4:"path";s:4:",34,";s:5:"grade";s:1:"1";s:5:"order";s:3:"110";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}i:7;O:8:"stdClass":13:{s:2:"id";s:2:"35";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:3:"Bug";s:6:"parent";s:1:"0";s:4:"path";s:4:",35,";s:5:"grade";s:1:"1";s:5:"order";s:3:"120";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}i:8;O:8:"stdClass":13:{s:2:"id";s:2:"36";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:6:"用例";s:6:"parent";s:1:"0";s:4:"path";s:4:",36,";s:5:"grade";s:1:"1";s:5:"order";s:3:"130";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}i:9;O:8:"stdClass":13:{s:2:"id";s:2:"37";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:12:"产品计划";s:6:"parent";s:1:"0";s:4:"path";s:4:",37,";s:5:"grade";s:1:"1";s:5:"order";s:2:"50";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}i:10;O:8:"stdClass":13:{s:2:"id";s:2:"38";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:6:"发布";s:6:"parent";s:1:"0";s:4:"path";s:4:",38,";s:5:"grade";s:1:"1";s:5:"order";s:2:"60";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}i:11;O:8:"stdClass":13:{s:2:"id";s:2:"39";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:9:"测试单";s:6:"parent";s:1:"0";s:4:"path";s:4:",39,";s:5:"grade";s:1:"1";s:5:"order";s:3:"140";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}i:12;O:8:"stdClass":13:{s:2:"id";s:2:"40";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:6:"版本";s:6:"parent";s:1:"0";s:4:"path";s:4:",40,";s:5:"grade";s:1:"1";s:5:"order";s:2:"90";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}i:13;O:8:"stdClass":13:{s:2:"id";s:2:"41";s:4:"root";s:1:"6";s:6:"branch";s:1:"0";s:4:"name";s:6:"用户";s:6:"parent";s:1:"0";s:4:"path";s:4:",41,";s:5:"grade";s:1:"1";s:5:"order";s:2:"20";s:4:"type";s:3:"api";s:5:"owner";s:0:"";s:9:"collector";s:0:"";s:5:"short";s:0:"";s:7:"deleted";s:1:"0";}}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,166 @@
|
||||
ALTER TABLE `zt_branch` ADD `default` enum ('0', '1') NOT NULL DEFAULT '0' AFTER `name`;
|
||||
ALTER TABLE `zt_branch` ADD `status` enum ('active', 'closed') NOT NULL DEFAULT 'active' AFTER `default`;
|
||||
ALTER TABLE `zt_branch` ADD `desc` varchar(255) NOT NULL AFTER `status`;
|
||||
ALTER TABLE `zt_branch` ADD `createdDate` date NOT NULL AFTER `desc`;
|
||||
ALTER TABLE `zt_branch` ADD `closedDate` date NOT NULL AFTER `createdDate`;
|
||||
ALTER TABLE `zt_projectstory` ADD `branch` mediumint(8) NOT NULL AFTER `product`;
|
||||
ALTER TABLE `zt_projectproduct` ADD PRIMARY KEY `project_product_branch` (`project`, `product`, `branch`), DROP INDEX `PRIMARY`;
|
||||
ALTER TABLE `zt_apistruct` CHANGE COLUMN `editEdBy` `editedBy` varchar(30) NOT NULL DEFAULT 0;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_kanbanlane`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_kanbanlane` (
|
||||
`id` int(8) NOT NULL AUTO_INCREMENT,
|
||||
`execution` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`type` char(30) NOT NULL,
|
||||
`groupby` char(30) NOT NULL,
|
||||
`extra` char(30) NOT NULL,
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`color` char(30) NOT NULL,
|
||||
`order` smallint(6) NOT NULL DEFAULT '0',
|
||||
`lastEditedTime` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_kanbancolumn`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_kanbancolumn` (
|
||||
`id` int(8) NOT NULL AUTO_INCREMENT,
|
||||
`lane` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`parent` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`type` char(30) NOT NULL,
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`color` char(30) NOT NULL,
|
||||
`limit` smallint(6) NOT NULL DEFAULT '-1',
|
||||
`order` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`cards` text NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_stage`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_stage` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`percent` varchar(255) NOT NULL,
|
||||
`type` varchar(255) NOT NULL,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`editedBy` varchar(30) NOT NULL,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_design`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_design` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`project` varchar(255) NOT NULL,
|
||||
`product` varchar(255) NOT NULL,
|
||||
`commit` text NOT NULL,
|
||||
`commitedBy` varchar(30) NOT NULL,
|
||||
`execution` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`name` varchar(255) NOT NULL,
|
||||
`status` varchar(30) NOT NULL,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`editedBy` varchar(30) NOT NULL,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`assignedTo` varchar(30) NOT NULL,
|
||||
`assignedBy` varchar(30) NOT NULL,
|
||||
`assignedDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
`story` char(30) NOT NULL,
|
||||
`desc` text NOT NULL,
|
||||
`version` smallint(6) NOT NULL,
|
||||
`type` char(30) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_designspec`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_designspec` (
|
||||
`design` mediumint(8) NOT NULL,
|
||||
`version` smallint(6) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`desc` text NOT NULL,
|
||||
`files` varchar(255) NOT NULL,
|
||||
UNIQUE KEY `design` (`design`,`version`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_weeklyreport`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_weeklyreport`(
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`project` mediumint(8) unsigned NOT NULL,
|
||||
`weekStart` date NOT NULL,
|
||||
`pv` float(9,2) NOT NULL,
|
||||
`ev` float(9,2) NOT NULL,
|
||||
`ac` float(9,2) NOT NULL,
|
||||
`sv` float(9,2) NOT NULL,
|
||||
`cv` float(9,2) NOT NULL,
|
||||
`staff` smallint(5) unsigned NOT NULL,
|
||||
`progress` varchar(255) NOT NULL,
|
||||
`workload` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `week` (`project`,`weekStart`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_holiday`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_holiday` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(30) NOT NULL DEFAULT '',
|
||||
`type` enum('holiday', 'working') NOT NULL DEFAULT 'holiday',
|
||||
`desc` text NOT NULL,
|
||||
`year` char(4) NOT NULL,
|
||||
`begin` date NOT NULL,
|
||||
`end` date NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `year` (`year`),
|
||||
KEY `name` (`name`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_mrapproval`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_mrapproval` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`mrID` mediumint(8) unsigned NOT NULL,
|
||||
`account` varchar(255) NOT NULL,
|
||||
`date` datetime NOT NULL,
|
||||
`action` char(30) NOT NULL,
|
||||
`comment` text NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
REPLACE INTO `zt_stage` (`name`,`percent`,`type`,`createdBy`,`createdDate`,`editedBy`,`editedDate`,`deleted`) VALUES
|
||||
('需求','10','request','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
|
||||
('设计','10','design','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
|
||||
('开发','50','dev','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
|
||||
('测试','15','qa','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
|
||||
('发布','10','release','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
|
||||
('总结评审','5','review','admin','2020-02-08 21:08:45','admin','2020-02-12 13:50:27','0');
|
||||
|
||||
INSERT INTO `zt_lang` (`lang`, `module`, `section`, `key`, `value`, `system`) VALUES
|
||||
('all','stage','typeList','request','需求', '1'),
|
||||
('all','stage','typeList','design','设计', '1'),
|
||||
('all','stage','typeList','dev','开发', '1'),
|
||||
('all','stage','typeList','qa','测试', '1'),
|
||||
('all','stage','typeList','release','发布', '1'),
|
||||
('all','stage','typeList','review','总结评审','1'),
|
||||
('all','stage','typeList','other','其他','1');
|
||||
|
||||
ALTER TABLE `zt_bug`
|
||||
ADD `feedbackBy` varchar(100) NOT NULL AFTER `activatedDate`,
|
||||
ADD `notifyEmail` varchar(100) NOT NULL AFTER `feedbackBy`;
|
||||
|
||||
ALTER TABLE `zt_story`
|
||||
ADD `feedbackBy` varchar(100) NOT NULL AFTER `version`,
|
||||
ADD `notifyEmail` varchar(100) NOT NULL AFTER `feedbackBy`;
|
||||
|
||||
ALTER TABLE `zt_product` ADD `reviewer` varchar(255) NOT NULL AFTER `whitelist`;
|
||||
UPDATE `zt_testtask` SET `pri`=3 WHERE `pri`=0;
|
||||
|
||||
ALTER table zt_mr ADD `approver` varchar(255) NOT NULL,
|
||||
ADD `approvalStatus` char(30) NOT NULL,
|
||||
ADD `needApproved` enum('0','1') NOT NULL DEFAULT '0',
|
||||
ADD `needCI` enum('0','1') NOT NULL DEFAULT '0',
|
||||
ADD `repoID` mediumint(8) unsigned NOT NULL,
|
||||
ADD `jobID` mediumint(8) unsigned NOT NULL,
|
||||
ADD `compileID` mediumint(8) unsigned NOT NULL,
|
||||
ADD `compileStatus` char(30) NOT NULL;
|
||||
@@ -0,0 +1,9 @@
|
||||
ALTER TABLE `zt_task` ADD `repo` mediumint unsigned NOT NULL AFTER `activatedDate`;
|
||||
ALTER TABLE `zt_task` ADD `entry` varchar(255) NOT NULL AFTER `repo`;
|
||||
ALTER TABLE `zt_task` ADD `lines` varchar(10) NOT NULL AFTER `entry`;
|
||||
ALTER TABLE `zt_task` ADD `v1` varchar(40) NOT NULL AFTER `lines`;
|
||||
ALTER TABLE `zt_task` ADD `v2` varchar(40) NOT NULL AFTER `v1`;
|
||||
ALTER TABLE `zt_task` ADD `mr` mediumint(8) unsigned NOT NULL AFTER `repo`;
|
||||
ALTER TABLE `zt_bug` ADD `mr` mediumint(8) unsigned NOT NULL AFTER `repo`;
|
||||
|
||||
UPDATE `zt_grouppriv` SET `method`='addReview' where `module`='mr' and `method`='addBug';
|
||||
+236
-87
@@ -30,99 +30,94 @@ CREATE TABLE IF NOT EXISTS `zt_action` (
|
||||
KEY `objectID` (`objectID`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_api_lib_release`;
|
||||
CREATE TABLE `zt_api_lib_release`
|
||||
(
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`lib` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`desc` varchar(255) NOT NULL DEFAULT '',
|
||||
`version` varchar(255) NOT NULL DEFAULT '',
|
||||
`snap` mediumtext NOT NULL,
|
||||
`addedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`addedDate` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
CREATE TABLE `zt_api_lib_release` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`lib` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`desc` varchar(255) NOT NULL DEFAULT '',
|
||||
`version` varchar(255) NOT NULL DEFAULT '',
|
||||
`snap` mediumtext NOT NULL,
|
||||
`addedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`addedDate` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_api`;
|
||||
CREATE TABLE `zt_api`
|
||||
(
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`product` varchar(255) NOT NULL DEFAULT '',
|
||||
`lib` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`module` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`title` varchar(100) NOT NULL DEFAULT '',
|
||||
`path` varchar(255) NOT NULL DEFAULT '',
|
||||
`protocol` varchar(10) NOT NULL DEFAULT '',
|
||||
`method` varchar(10) NOT NULL DEFAULT '',
|
||||
`requestType` varchar(100) NOT NULL DEFAULT '',
|
||||
`responseType` varchar(100) NOT NULL DEFAULT '',
|
||||
`status` varchar(20) NOT NULL DEFAULT '',
|
||||
`owner` varchar(30) NOT NULl DEFAULT 0,
|
||||
`desc` text NULL,
|
||||
`version` smallint UNSIGNED NOT NULL DEFAULT 0,
|
||||
`params` text NULL,
|
||||
`paramsExample` text NUll,
|
||||
`responseExample` text NUll,
|
||||
`response` text NULL,
|
||||
`commonParams` text NULL,
|
||||
`addedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`addedDate` datetime NOT NULL,
|
||||
`editedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`deleted` enum ('0', '1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
CREATE TABLE `zt_api` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`product` varchar(255) NOT NULL DEFAULT '',
|
||||
`lib` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`module` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`title` varchar(100) NOT NULL DEFAULT '',
|
||||
`path` varchar(255) NOT NULL DEFAULT '',
|
||||
`protocol` varchar(10) NOT NULL DEFAULT '',
|
||||
`method` varchar(10) NOT NULL DEFAULT '',
|
||||
`requestType` varchar(100) NOT NULL DEFAULT '',
|
||||
`responseType` varchar(100) NOT NULL DEFAULT '',
|
||||
`status` varchar(20) NOT NULL DEFAULT '',
|
||||
`owner` varchar(30) NOT NULl DEFAULT 0,
|
||||
`desc` text NULL,
|
||||
`version` smallint UNSIGNED NOT NULL DEFAULT 0,
|
||||
`params` text NULL,
|
||||
`paramsExample` text NUll,
|
||||
`responseExample` text NUll,
|
||||
`response` text NULL,
|
||||
`commonParams` text NULL,
|
||||
`addedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`addedDate` datetime NOT NULL,
|
||||
`editedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`deleted` enum ('0', '1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_apispec`;
|
||||
CREATE TABLE `zt_apispec`
|
||||
(
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`doc` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`module` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`title` varchar(100) NOT NULL DEFAULT '',
|
||||
`path` varchar(255) NOT NULL DEFAULT '',
|
||||
`protocol` varchar(10) NOT NULL DEFAULT '',
|
||||
`method` varchar(10) NOT NULL DEFAULT '',
|
||||
`requestType` varchar(100) NOT NULL DEFAULT '',
|
||||
`responseType` varchar(100) NOT NULL DEFAULT '',
|
||||
`status` varchar(20) NOT NULL DEFAULT '',
|
||||
`owner` varchar(255) NOT NULl DEFAULT 0,
|
||||
`desc` text NULL,
|
||||
`version` smallint UNSIGNED NOT NULL DEFAULT 0,
|
||||
`params` text NULL,
|
||||
`paramsExample` text NUll,
|
||||
`responseExample` text NUll,
|
||||
`response` text NULL,
|
||||
`addedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`addedDate` datetime NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
CREATE TABLE `zt_apispec` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`doc` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`module` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`title` varchar(100) NOT NULL DEFAULT '',
|
||||
`path` varchar(255) NOT NULL DEFAULT '',
|
||||
`protocol` varchar(10) NOT NULL DEFAULT '',
|
||||
`method` varchar(10) NOT NULL DEFAULT '',
|
||||
`requestType` varchar(100) NOT NULL DEFAULT '',
|
||||
`responseType` varchar(100) NOT NULL DEFAULT '',
|
||||
`status` varchar(20) NOT NULL DEFAULT '',
|
||||
`owner` varchar(255) NOT NULl DEFAULT 0,
|
||||
`desc` text NULL,
|
||||
`version` smallint UNSIGNED NOT NULL DEFAULT 0,
|
||||
`params` text NULL,
|
||||
`paramsExample` text NUll,
|
||||
`responseExample` text NUll,
|
||||
`response` text NULL,
|
||||
`addedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`addedDate` datetime NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_apistruct`;
|
||||
CREATE TABLE `zt_apistruct`
|
||||
(
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
`lib` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`name` varchar(30) NOT NULL DEFAULT '',
|
||||
`type` varchar(50) NOT NULL DEFAULT '',
|
||||
`desc` varchar(255) NOT NULL DEFAULT '',
|
||||
`version` smallint unsigned NOT NULL DEFAULT 0,
|
||||
`attribute` text NULL,
|
||||
`addedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`addedDate` datetime NOT NULL,
|
||||
`editEdBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`deleted` enum ('0', '1') NOT NULL DEFAULT '0',
|
||||
primary key (`id`)
|
||||
CREATE TABLE `zt_apistruct` (
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
`lib` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`name` varchar(30) NOT NULL DEFAULT '',
|
||||
`type` varchar(50) NOT NULL DEFAULT '',
|
||||
`desc` varchar(255) NOT NULL DEFAULT '',
|
||||
`version` smallint unsigned NOT NULL DEFAULT 0,
|
||||
`attribute` text NULL,
|
||||
`addedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`addedDate` datetime NOT NULL,
|
||||
`editedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`deleted` enum ('0', '1') NOT NULL DEFAULT '0',
|
||||
primary key (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_apistruct_spec`;
|
||||
CREATE TABLE `zt_apistruct_spec`
|
||||
(
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`type` varchar(50) NOT NULL DEFAULT '',
|
||||
`desc` varchar(255) NOT NULL DEFAULT '',
|
||||
`attribute` text NULL,
|
||||
`version` smallint unsigned NOT NULL DEFAULT 0,
|
||||
`addedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`addedDate` datetime NOT NULL,
|
||||
primary key (`id`)
|
||||
CREATE TABLE `zt_apistruct_spec` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`type` varchar(50) NOT NULL DEFAULT '',
|
||||
`desc` varchar(255) NOT NULL DEFAULT '',
|
||||
`attribute` text NULL,
|
||||
`version` smallint unsigned NOT NULL DEFAULT 0,
|
||||
`addedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`addedDate` datetime NOT NULL,
|
||||
primary key (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_block`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_block` (
|
||||
@@ -147,6 +142,11 @@ CREATE TABLE IF NOT EXISTS `zt_branch` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`product` mediumint(8) unsigned NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`default` enum ('0', '1') NOT NULL DEFAULT '0',
|
||||
`status` enum ('active', 'closed') NOT NULL DEFAULT 'active',
|
||||
`desc` varchar(255) NOT NULL,
|
||||
`createdDate` date NOT NULL,
|
||||
`closedDate` date NOT NULL,
|
||||
`order` smallint unsigned NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
@@ -182,6 +182,8 @@ CREATE TABLE IF NOT EXISTS `zt_bug` (
|
||||
`confirmed` tinyint(1) NOT NULL default '0',
|
||||
`activatedCount` smallint(6) NOT NULL,
|
||||
`activatedDate` datetime NOT NULL,
|
||||
`feedbackBy` varchar(100) NOT NULL,
|
||||
`notifyEmail` varchar(100) NOT NULL,
|
||||
`mailto` text,
|
||||
`openedBy` varchar(30) NOT NULL default '',
|
||||
`openedDate` datetime NOT NULL,
|
||||
@@ -201,6 +203,7 @@ CREATE TABLE IF NOT EXISTS `zt_bug` (
|
||||
`caseVersion` smallint(6) NOT NULL DEFAULT '1',
|
||||
`result` mediumint(8) unsigned NOT NULL,
|
||||
`repo` mediumint(8) unsigned NOT NULL,
|
||||
`mr` mediumint(8) unsigned NOT NULL,
|
||||
`entry` varchar(255) NOT NULL,
|
||||
`lines` varchar(10) NOT NULL,
|
||||
`v1` varchar(40) NOT NULL,
|
||||
@@ -393,6 +396,39 @@ CREATE TABLE IF NOT EXISTS `zt_dept` (
|
||||
KEY `parent` (`parent`),
|
||||
KEY `path` (`path`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_design`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_design` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`project` varchar(255) NOT NULL,
|
||||
`product` varchar(255) NOT NULL,
|
||||
`commit` text NOT NULL,
|
||||
`commitedBy` varchar(30) NOT NULL,
|
||||
`execution` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`name` varchar(255) NOT NULL,
|
||||
`status` varchar(30) NOT NULL,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`editedBy` varchar(30) NOT NULL,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`assignedTo` varchar(30) NOT NULL,
|
||||
`assignedBy` varchar(30) NOT NULL,
|
||||
`assignedDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
`story` char(30) NOT NULL,
|
||||
`desc` text NOT NULL,
|
||||
`version` smallint(6) NOT NULL,
|
||||
`type` char(30) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_designspec`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_designspec` (
|
||||
`design` mediumint(8) NOT NULL,
|
||||
`version` smallint(6) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`desc` text NOT NULL,
|
||||
`files` varchar(255) NOT NULL,
|
||||
UNIQUE KEY `design` (`design`,`version`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_doc`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_doc` (
|
||||
`id` mediumint(8) unsigned NOT NULL auto_increment,
|
||||
@@ -558,6 +594,19 @@ CREATE TABLE IF NOT EXISTS `zt_grouppriv` (
|
||||
`method` char(30) NOT NULL default '',
|
||||
UNIQUE KEY `group` (`group`,`module`,`method`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_holiday`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_holiday` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(30) NOT NULL DEFAULT '',
|
||||
`type` enum('holiday', 'working') NOT NULL DEFAULT 'holiday',
|
||||
`desc` text NOT NULL,
|
||||
`year` char(4) NOT NULL,
|
||||
`begin` date NOT NULL,
|
||||
`end` date NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `year` (`year`),
|
||||
KEY `name` (`name`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_history`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_history` (
|
||||
`id` mediumint(8) unsigned NOT NULL auto_increment,
|
||||
@@ -595,6 +644,34 @@ CREATE TABLE IF NOT EXISTS `zt_job` (
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_kanbanlane`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_kanbanlane` (
|
||||
`id` int(8) NOT NULL AUTO_INCREMENT,
|
||||
`execution` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`type` char(30) NOT NULL,
|
||||
`groupby` char(30) NOT NULL,
|
||||
`extra` char(30) NOT NULL,
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`color` char(30) NOT NULL,
|
||||
`order` smallint(6) NOT NULL DEFAULT '0',
|
||||
`lastEditedTime` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_kanbancolumn`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_kanbancolumn` (
|
||||
`id` int(8) NOT NULL AUTO_INCREMENT,
|
||||
`lane` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`parent` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`type` char(30) NOT NULL,
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`color` char(30) NOT NULL,
|
||||
`limit` smallint(6) NOT NULL DEFAULT '-1',
|
||||
`order` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`cards` text NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_lang`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_lang` (
|
||||
`id` mediumint(8) unsigned NOT NULL auto_increment,
|
||||
@@ -655,6 +732,7 @@ CREATE TABLE IF NOT EXISTS `zt_mr` (
|
||||
`description` text NOT NULL,
|
||||
`assignee` varchar(255) NOT NULL,
|
||||
`reviewer` varchar(255) NOT NULL,
|
||||
`approver` varchar(255) NOT NULL,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`editedBy` varchar(30) NOT NULL,
|
||||
@@ -662,6 +740,23 @@ CREATE TABLE IF NOT EXISTS `zt_mr` (
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
`status` char(30) NOT NULL,
|
||||
`mergeStatus` char(30) NOT NULL,
|
||||
`approvalStatus` char(30) NOT NULL,
|
||||
`needApproved` enum('0','1') NOT NULL DEFAULT '0',
|
||||
`needCI` enum('0','1') NOT NULL DEFAULT '0',
|
||||
`repoID` mediumint(8) unsigned NOT NULL,
|
||||
`jobID` mediumint(8) unsigned NOT NULL,
|
||||
`compileID` mediumint(8) unsigned NOT NULL,
|
||||
`compileStatus` char(30) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_mrapproval`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_mrapproval` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`mrID` mediumint(8) unsigned NOT NULL,
|
||||
`account` varchar(255) NOT NULL,
|
||||
`date` datetime NOT NULL,
|
||||
`action` char(30) NOT NULL,
|
||||
`comment` text NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_notify`;
|
||||
@@ -733,6 +828,7 @@ CREATE TABLE IF NOT EXISTS `zt_product` (
|
||||
`RD` varchar(30) NOT NULL,
|
||||
`acl` enum('open','private','custom') NOT NULL default 'open',
|
||||
`whitelist` text NOT NULL,
|
||||
`reviewer` varchar(255) NOT NULL,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`createdVersion` varchar(20) NOT NULL,
|
||||
@@ -832,7 +928,7 @@ CREATE TABLE IF NOT EXISTS `zt_projectproduct` (
|
||||
`product` mediumint(8) unsigned NOT NULL,
|
||||
`branch` mediumint(8) unsigned NOT NULL,
|
||||
`plan` mediumint(8) unsigned NOT NULL,
|
||||
PRIMARY KEY (`project`,`product`)
|
||||
PRIMARY KEY (`project`, `product`, `branch`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_projectspec`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_projectspec` (
|
||||
@@ -848,6 +944,7 @@ CREATE TABLE IF NOT EXISTS `zt_projectspec` (
|
||||
CREATE TABLE IF NOT EXISTS `zt_projectstory` (
|
||||
`project` mediumint(8) unsigned NOT NULL default '0',
|
||||
`product` mediumint(8) unsigned NOT NULL,
|
||||
`branch` mediumint(8) unsigned NOT NULL,
|
||||
`story` mediumint(8) unsigned NOT NULL default '0',
|
||||
`version` smallint(6) NOT NULL default '1',
|
||||
`order` smallint(6) unsigned NOT NULL,
|
||||
@@ -989,6 +1086,19 @@ CREATE TABLE IF NOT EXISTS `zt_searchindex` (
|
||||
FULLTEXT KEY `content` (`content`),
|
||||
FULLTEXT KEY `title` (`title`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_stage`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_stage` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`percent` varchar(255) NOT NULL,
|
||||
`type` varchar(255) NOT NULL,
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`editedBy` varchar(30) NOT NULL,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_stakeholder`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_stakeholder` (
|
||||
`id` mediumint(8) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
@@ -1043,6 +1153,8 @@ CREATE TABLE IF NOT EXISTS `zt_story` (
|
||||
`linkStories` varchar(255) NOT NULL,
|
||||
`duplicateStory` mediumint(8) unsigned NOT NULL,
|
||||
`version` smallint(6) NOT NULL default '1',
|
||||
`feedbackBy` varchar(100) NOT NULL,
|
||||
`notifyEmail` varchar(100) NOT NULL,
|
||||
`URChanged` enum('0','1') NOT NULL DEFAULT '0',
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`),
|
||||
@@ -1139,6 +1251,12 @@ CREATE TABLE IF NOT EXISTS `zt_task` (
|
||||
`lastEditedBy` varchar(30) NOT NULL,
|
||||
`lastEditedDate` datetime NOT NULL,
|
||||
`activatedDate` date NOT NULL,
|
||||
`repo` mediumint(8) unsigned NOT NULL,
|
||||
`mr` mediumint(8) unsigned NOT NULL,
|
||||
`entry` varchar(255) NOT NULL,
|
||||
`lines` varchar(10) NOT NULL,
|
||||
`v1` varchar(40) NOT NULL,
|
||||
`v2` varchar(40) NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `execution` (`execution`),
|
||||
@@ -1409,6 +1527,22 @@ CREATE TABLE IF NOT EXISTS `zt_userview` (
|
||||
`sprints` mediumtext NOT NULL,
|
||||
UNIQUE KEY `account` (`account`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_weeklyreport`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_weeklyreport`(
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`project` mediumint(8) unsigned NOT NULL,
|
||||
`weekStart` date NOT NULL,
|
||||
`pv` float(9,2) NOT NULL,
|
||||
`ev` float(9,2) NOT NULL,
|
||||
`ac` float(9,2) NOT NULL,
|
||||
`sv` float(9,2) NOT NULL,
|
||||
`cv` float(9,2) NOT NULL,
|
||||
`staff` smallint(5) unsigned NOT NULL,
|
||||
`progress` varchar(255) NOT NULL,
|
||||
`workload` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `week` (`project`,`weekStart`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_webhook`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_webhook` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
@@ -5695,7 +5829,22 @@ REPLACE INTO `zt_lang` (`lang`, `module`, `section`, `key`, `value`, `system`) V
|
||||
('zh-cn', 'custom', 'URSRList', '3', '{\"SRName\":\"\\u8f6f\\u9700\",\"URName\":\"\\u7528\\u9700\"}', '1'),('zh-cn', 'custom', 'URSRList', '4', '{\"SRName\":\"\\u6545\\u4e8b\",\"URName\":\"\\u53f2\\u8bd7\"}', '1'),
|
||||
('zh-cn', 'custom', 'URSRList', '5', '{\"SRName\":\"\\u9700\\u6c42\",\"URName\":\"\\u7528\\u6237\\u9700\\u6c42\"}', '1'),
|
||||
('en', 'custom', 'URSRList', '1', '{\"SRName\":\"Story\",\"URName\":\"Epic\"}', '0'),
|
||||
('en', 'custom', 'URSRList', '2', '{\"SRName\":\"Software Requirement\",\"URName\":\"User Requirement\"}', '0');
|
||||
('en', 'custom', 'URSRList', '2', '{\"SRName\":\"Software Requirement\",\"URName\":\"User Requirement\"}', '0'),
|
||||
('all','stage','typeList','request','需求', '1'),
|
||||
('all','stage','typeList','design','设计', '1'),
|
||||
('all','stage','typeList','dev','开发', '1'),
|
||||
('all','stage','typeList','qa','测试', '1'),
|
||||
('all','stage','typeList','release','发布', '1'),
|
||||
('all','stage','typeList','review','总结评审','1'),
|
||||
('all','stage','typeList','other','其他','1');
|
||||
|
||||
REPLACE INTO `zt_stage` (`name`,`percent`,`type`,`createdBy`,`createdDate`,`editedBy`,`editedDate`,`deleted`) VALUES
|
||||
('需求','10','request','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
|
||||
('设计','10','design','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
|
||||
('开发','50','dev','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
|
||||
('测试','15','qa','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
|
||||
('发布','10','release','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
|
||||
('总结评审','5','review','admin','2020-02-08 21:08:45','admin','2020-02-12 13:50:27','0');
|
||||
|
||||
INSERT INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES ('system', 'custom', '', 'hourPoint', '0');
|
||||
INSERT INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES ('system', 'common', '', 'CRProduct', '1');
|
||||
|
||||
+230
@@ -1,3 +1,233 @@
|
||||
2021-12-06 16.0.beat1
|
||||
完成的需求
|
||||
14005 能够按照平台分支浏览用户需求
|
||||
14429 父需求支持变更
|
||||
14761 选择某一个分支之后点击其他菜单希望能够保持分支下拉菜单状态
|
||||
14771 启用多分支功能后增加分支字样显示的控制
|
||||
14772 需求修改所属分支时如果有冲突给出提示
|
||||
14778 分支设置默认分支功能
|
||||
14877 根据分支提示上次版本计划名称
|
||||
15134 员工负载表增加备注说明
|
||||
15470 看板可以设置一个单元格里面卡片的排列方式
|
||||
15478 我的地盘bug列表增加确认字段
|
||||
25665 梳理项目和执行关联产品分支的逻辑
|
||||
25666 可以将某一个分支关闭
|
||||
25667 将所有分支概念改为主干并处理历史数据
|
||||
25670 多分支产品浏览需求的时候将所有和主干区分开
|
||||
25673 分支增加排序功能
|
||||
27484 文档库右侧目录增加文件的浮动操作菜单
|
||||
27485 文档库右侧目录增加目录的浮动操作菜单
|
||||
27486 wiki目录中,当鼠标悬浮到文章名称时展示文章快捷操作
|
||||
27487 wiki目录中,鼠标悬浮到具体章节时展示章节的快捷操作
|
||||
27927 执行看板默认只显示一屏滚动时再往下加载
|
||||
28098 需求批量转任务时对已经转换过任务的需求进行提示
|
||||
28131 待处理任务列表中子任务名称前显示父任务
|
||||
28138 员工负载表中增加项目名称信息
|
||||
28147 统计列表中具备横向滚动条的列表可以直接展示出来
|
||||
28153 Bug创建表中优化执行查询条件
|
||||
28235 关闭项目时增加实际完成日期的记录
|
||||
28236 项目工时统计中增加实际开始和实际完成的信息
|
||||
28237 执行启动时增加实际开始日期的记录
|
||||
28238 关闭执行时增加实际完成日期的记录
|
||||
28239 执行工时统计中增加实际开始和实际完成的信息
|
||||
28310 未开始的项目
|
||||
28466 测试Bug列表中增加按所属项目的搜索条件
|
||||
28509 项目概况中增加项目代号的显示
|
||||
28510 项目列表中增加项目代号字段显示
|
||||
28719 项目看板中看板列显示数量汇总
|
||||
28727 计划创建迭代时选择项目点击下一步后自动关闭选择弹窗
|
||||
28809 执行看板中进行中项目排序规则调整
|
||||
28810 执行看板中已关闭的执行只展示最近2期数据
|
||||
28811 执行看板中执行支持拖动调整看板列和状态
|
||||
28811 执行看板中执行支持拖动调整看板列和状态
|
||||
28812 项目看板中调整项目集和项目的排序规则
|
||||
28813 项目看板中已关闭的项目只展示最近2个数据
|
||||
28814 项目看板中项目支持拖动调整看板列和状态
|
||||
28814 项目看板中项目支持拖动调整看板列和状态
|
||||
28815 产品看板中看板列显示数量汇总
|
||||
28816 产品看板中调整项目集和产品的排序规则
|
||||
28817 项目集看板中调整项目集和产品的排序规则
|
||||
28818 项目集看板中看板列显示数量汇总
|
||||
28819 调整项目集/产品/项目/执行重名规则
|
||||
28833 创建执行页面可以直接维护相关负责人信息
|
||||
28834 项目的分组权限中移除无用的模块和方法
|
||||
28835 关联多个产品的项目也可以选择归并方式
|
||||
28904 优化项目列表“我参与的”筛选结果 结
|
||||
28928 可以设置哪些人不需要提醒
|
||||
28929 编辑bug修改状态时如果未修改成功希望有错误提示
|
||||
28931 调整分支管理功能
|
||||
28932 实现分支的批量操作
|
||||
28941 重新登陆系统后产品下拉菜单应当保持上次选中的产品名称
|
||||
28944 在开源版中增加瀑布模型的相关功能
|
||||
28959 老版本升级新版本数据归并的时候,可以修改项目、执行名称。
|
||||
28960 调整产品列表页面的宽度展示比例
|
||||
28965 实现分支的新增/编辑操作
|
||||
28970 需求列表批量选中希望可以通过shift快捷键操作
|
||||
28972 产品列表左侧的模块设置调整为显示设置
|
||||
28973 提交Bug时分支与影响版本要跟着联动
|
||||
28974 产品列表批量调整计划时在计划名称前显示分支信息
|
||||
28993 创建或者编辑用例时调整所属需求的查询逻辑
|
||||
29000 产品列表中调整字段显示宽度
|
||||
29002 动态支持按正序/倒序切换排序
|
||||
29030 已挂起的项目/执行下面的任务不在待办/待处理的任务中展示
|
||||
29059 多分支产品批量创建需求时分支字段设为默认项
|
||||
29069 组织团队成员任务列表增加优先级排序功能
|
||||
29074 用户下拉菜单中增加人员的头像/部门/职位信息
|
||||
29108 提交/编辑软件需求页面中增加反馈者和通知邮箱信息
|
||||
29109 提交/编辑Bug页面中增加反馈者和通知邮箱信息
|
||||
29116 创建/编辑发布信息的通知人员中增加反馈者
|
||||
29127 计划的Bug列表中增加批量编辑和调整计划功能
|
||||
29131 产品概况中增加评审人员的设置
|
||||
29134 看板页面的刷新不要抖动用更加平滑的方式呈现
|
||||
29141 启用多分支功能后要用例增加分支字样显示的控制
|
||||
29142 启用多分支功能后要Bug增加分支字样显示的控制
|
||||
29143 批量创建需求/BUG/用例时所属模块选择同上,需要检测上一行数据的所属分支和当前行的所属分支是否一致
|
||||
29144 所有分支下批量编辑需求/BUG/用例,所属模块数据默认为所有分支的模块时,需要处理分支与模块不一致的问题
|
||||
29145 项目和执行关联了产品的多个分支及计划时调整概况页面显示方式
|
||||
29147 产品下软件需求列表需求名称前显示主干的分支名
|
||||
29156 启用多分支功能后项目需求列表增加是否显示分支名
|
||||
29157 启用多分支功能后执行需求列表增加是否显示分支名
|
||||
29158 启用多分支功能后执行任务列表增加是否显示分支名
|
||||
29166 需求调整分支时,需求所属模块为主干的不用清空所属模块
|
||||
29167 Bug调整分支时所属模块为主干的不用清空所属模块
|
||||
29168 用例调整分支时所属模块为主干的不用清空所属模块
|
||||
29173 项目关联产品计划时不允许关联父计划
|
||||
29174 执行关联产品计划时不允许关联父计划
|
||||
29182 分支下拉菜单中显示已关闭的分支状态
|
||||
29192 归并数据遇到重名数据时可修改重名的数据
|
||||
29193 调整发布中消息通知的触发方式
|
||||
29218 分支的状态全部为关闭时才能调整产品类型为正常
|
||||
29234 梳理分支逻辑
|
||||
29438 在执行1下创建测试用例在执行2用例列表中也能看到
|
||||
修复的BUG
|
||||
6917 用例转bug编号会变化
|
||||
6978 多分支产品bug搜索影响版本不太清晰
|
||||
11290 邮件列表中主题字段内容部分遮挡
|
||||
12023 产品下分支页面建议优化
|
||||
13756 提bug页面没有正常显示所属产品分支的控件
|
||||
14101 青春蓝-引导页国际版配图为中文
|
||||
15665 维护目录和版本管理前的icon图标一样
|
||||
15675 版本下解决又激活的bug,重新解决的时候,应该带有之前版本信息
|
||||
15675 版本下解决又激活的bug,重新解决的时候,应该带有之前版本信息
|
||||
15686 创建项目填充数据后,再选择项目集数据被清空
|
||||
15687 自定义任务优先级展示问题
|
||||
15688 新建用例,模块和需求对应错误
|
||||
15689 测试单的报表百分比换行
|
||||
15690 切换产品后,新建用例未显示在用例列表中
|
||||
15691 套件的用例列表右上角的操作按钮样式不一致
|
||||
15693 卡片展示项目时,项目状态显示不正确
|
||||
15694 执行下创建用例,可以选择产品所有的模块和需求
|
||||
15695 建用例,有默认所属模块可选择所有需求
|
||||
15737 统计视图无法通过权限控制取消
|
||||
15780 更改项目集的父项目集时,下面的产品线不能变更到顶层项目集
|
||||
15781 项目创建版本时选择不到产品分支
|
||||
15798 报告导出之后不展示饼状图
|
||||
15826 后台评审流程开启后产品中批量创建研发需求没有默认需要评审
|
||||
15828 项目集列表中删除顶级项目,跳转错误
|
||||
16000 执行测试用例下用例标题换行显示
|
||||
16018 项目-测试-BUG界面提交BUG不显示多分支/平台
|
||||
16130 项目下创建测试用例时相关需求列出的数据不对
|
||||
16139 设为分支为默认分支icon没有显示完全
|
||||
16257 创建执行的时候已经关闭的项目仍然可以选择
|
||||
16302 项目软件需求下搜索下拉列中所属分支显示为%s
|
||||
16527 批量编辑用例时,列出了所有分支
|
||||
16567 多分支产品的任务名称前主干分支名称显示其他分支名称不显示
|
||||
16570 经典模式多分支产品批量提bug时标题未填写点击保存没做提示
|
||||
16573 经典模式多分支产品批量创建用例未填写用例标题保存直接跳转列表没做提示
|
||||
16574 关联产品页面已关联产品可以下拉选择其他未关联的分支
|
||||
16582 分支1版本可以关联其他分支需求
|
||||
16583 批量编辑测试用例分支显示错误导致无法选择模块
|
||||
16584 执行版本不能按照所属分支搜索
|
||||
16585 主干版本前未显示主干标识
|
||||
16587 需求编辑页面所处阶段处分支展示方式建议优化
|
||||
16588 项目/执行下显示了未关联的分支需求
|
||||
16589 多分支产品测试用例列表用例类型展示有遮挡
|
||||
16591 批量编辑研发需求修改分支后再修改回去计划没有随之联动
|
||||
16592 多分支产品项目的研发需求模块展示不对
|
||||
16593 测试下Bug页面中左侧模块树默认高亮了主干
|
||||
16603 项目列表中项目名称显示不全
|
||||
16605 项目的用例下显示了所有的分支
|
||||
16608 编辑模块页面选择分支后上级模块列出的还是主干模块
|
||||
16609 导出用例的模板显示了所有分支
|
||||
16612 用例模板没显示分支下的模块
|
||||
16616 导入用例分支下拉列表显示了所有分支
|
||||
16620 研发需求变动列表一条用例显示多次
|
||||
16621 搜索用例时,所属分支列出了所有分支
|
||||
16622 产品下研发需求页搜索的所属模块下拉只列出了主干下的模块
|
||||
16623 多分支产品关闭的分支在项目关联产品的时候仍然显示
|
||||
16624 产品详情页中左上角产品下拉菜单中无当前产品选项
|
||||
16626 测试套件中不显示其他分支模块只显示主干模块
|
||||
16631 套件的用例名称前不显示主干
|
||||
16637 测试单关联用例列表,用例列表显示分支标识
|
||||
16639 测试用例详情页指派给用户显示数字
|
||||
16640 测试单的优先级显示为0
|
||||
16641 地盘待处理下用例批量编辑页面相关研发需求未带出
|
||||
16643 地盘下批量编辑任务页面“贡献”菜单位置显示不对
|
||||
16645 创建Gitlab动态没有链接地址
|
||||
16646 文档的产品库中产品显示错误
|
||||
16647 测试单生成报告提示没有关联的非Trunk测试单
|
||||
16648 项目列表中项目名称完全折叠隐藏
|
||||
16650 多分支产品测试套件详情所属模块只展示主干模块
|
||||
16653 发布可以关联所有分支的需求
|
||||
16676 地盘待处理下批量执行用例页面有代码报错
|
||||
16680 产品库创建文档时所属文档库下拉无法选择其他产品库
|
||||
16681 导入用例库测试用例分支和模块不对应
|
||||
16682 地盘贡献下复制用例页面有代码报错
|
||||
16683 测试单关联测试用例不能选择主干
|
||||
16684 套件中用例标题的主干分支不显示
|
||||
16685 测试单关联测试用例分支=空搜索到的数据为主干的测试用例
|
||||
16689 测试单用例列表不显示测试用例相关模块
|
||||
16690 产品下需求批量编辑页面计划显示不对
|
||||
16692 项目下软件需求批量编辑页面分支显示不对
|
||||
16694 提交测试的测试单不应该受左上角选择分支影响
|
||||
16697 测试单关联测试用例选择所属分支应该只能选择版本关联的分支
|
||||
16700 项目创建发布选择版本后产品分支会消失
|
||||
16708 批量编辑多分支产品的研发需求报错
|
||||
16713 产品需求模块中主干模块直接显示不用增加层级
|
||||
|
||||
2021-11-02 15.7.1
|
||||
修复的BUG
|
||||
15835 创建产品选择产品线选中样式不对
|
||||
15793 编辑项目集实际开始日期应置空
|
||||
15792 子计划的开始结束时间没有根据父计划做约束
|
||||
15790 无关联项目时,计划创建迭代跳转页面不正确
|
||||
15784 执行测试下提Bug返回的页面不对
|
||||
15778 产品线取消所属项目集后产品列表页面显示错误
|
||||
15776 添加产品 无法选中 产品线
|
||||
15755 地盘下执行列表中“指派给我”含义不明确
|
||||
15754 批量提Bug时不填写必填项[影响版本]也可以保存成功
|
||||
15753 内网中批量新建质量保证计划三级导航菜单未高亮
|
||||
15746 文档大纲只能显示第一个字影响使用
|
||||
15745 执行-提醒-模块和动作顺序颠倒了
|
||||
15744 后台-通知-设置,权限的英文描述不需要为过去式
|
||||
15743 产品-需求-没有创建权限的用户点击导出时下拉菜单溢出
|
||||
15742 产品-设置页面英文单词换行
|
||||
15741 修改接口文档后历史记录可以优化一下,对于用户来说看不懂修改了哪里
|
||||
15739 接口库中接口的添加时间会随更新时间改动
|
||||
15737 统计视图无法通过权限控制取消
|
||||
15729 项目团队成员维护新增字段行没有搜索功能
|
||||
15728 取消备注权限后,还可以通过编辑添加备注
|
||||
15723 点击左侧导航栏有时跳转页面不正确
|
||||
15719 评审阶段的需求,点击搜索后,不可以评审,但可以变更
|
||||
15718 需求导入excel时如果取消勾选“不需要评审”则导入的需求状态为草稿且无法激活
|
||||
15716 测试报告中项目目标建议给出提示或说明
|
||||
15715 细分子任务弹窗时无任务研发需求
|
||||
15712 项目下研发需求还会显示细分需求按钮
|
||||
15710 在产品A下添加测试用例选择产品B不显示相关联研发需求
|
||||
15708 经典模式下变更需求页标签名称不对
|
||||
15705 组织-动态搜索条件设置 所属产品=全部产品 后,搜索不出数据
|
||||
15702 接口多层级字段,去掉多个L符号
|
||||
15672 点击删除版本按钮后没有弹出访问受限提示弹窗
|
||||
15668 编辑名称为空的接口时显示错误
|
||||
15667 创建接口的时候可以为一个空格
|
||||
15664 不能进行目录维护时,优化一下左侧提示文案
|
||||
15660 接口库名称可以重名
|
||||
15659 接口库中多级目录时创建接口显示不明确
|
||||
15657 数据结构列表操作栏的title显示为接口
|
||||
15467 管理流程字样显示问题
|
||||
15287 批量编辑任务,指派给closed,任务状态未关闭
|
||||
14559 项目下拉中所有产品和产品列表文案需统一
|
||||
|
||||
2021-10-18 15.7
|
||||
修复的BUG
|
||||
14487 无用php记录太多拉低禅道整体性能
|
||||
|
||||
@@ -275,6 +275,7 @@ class baseEntry
|
||||
global $app;
|
||||
$app->setModuleName($moduleName);
|
||||
$app->setMethodName($methodName);
|
||||
$app->viewType = 'json';
|
||||
|
||||
/* Check user permission. */
|
||||
$this->checkPriv();
|
||||
@@ -546,6 +547,23 @@ class baseEntry
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format user.
|
||||
*
|
||||
* @param string $account
|
||||
* @param array $users
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function formatUser($account, $users)
|
||||
{
|
||||
$user = array();
|
||||
$user['account'] = $account;
|
||||
$user['realname'] = zget($users, $account);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 类型转换.
|
||||
* Typecasting.
|
||||
@@ -559,31 +577,62 @@ class baseEntry
|
||||
{
|
||||
switch($type)
|
||||
{
|
||||
case 'time':
|
||||
$timeFormat = $this->param('timeFormat', 'utc');
|
||||
if($timeFormat == 'utc')
|
||||
{
|
||||
if(!$value or $value == '0000-00-00 00:00:00') return null;
|
||||
return gmdate("Y-m-d\TH:i:s\Z", strtotime($value));
|
||||
}
|
||||
return $value;
|
||||
case 'date':
|
||||
if(!$value or $value == '0000-00-00') return null;
|
||||
return $value;
|
||||
case 'bool':
|
||||
return boolval($value) ? true : false;
|
||||
case 'idList':
|
||||
$values = explode(',', $value);
|
||||
if(empty($values)) return array();
|
||||
case 'time':
|
||||
$timeFormat = $this->param('timeFormat', 'utc');
|
||||
if($timeFormat == 'utc')
|
||||
{
|
||||
if(!$value or $value == '0000-00-00 00:00:00') return null;
|
||||
return gmdate("Y-m-d\TH:i:s\Z", strtotime($value));
|
||||
}
|
||||
return $value;
|
||||
case 'date':
|
||||
if(!$value or $value == '0000-00-00') return null;
|
||||
return $value;
|
||||
case 'bool':
|
||||
return !empty($value);
|
||||
case 'int':
|
||||
return (int) $value;
|
||||
case 'idList':
|
||||
$values = explode(',', $value);
|
||||
if(empty($values)) return array();
|
||||
|
||||
$idList = array();
|
||||
foreach($values as $val)
|
||||
{
|
||||
if($val !== '') $idList[] = (int) $val;
|
||||
}
|
||||
return $idList;
|
||||
default:
|
||||
return $value;
|
||||
$idList = array();
|
||||
foreach($values as $val)
|
||||
{
|
||||
if($val !== '') $idList[] = (int) $val;
|
||||
}
|
||||
return $idList;
|
||||
case 'stringList':
|
||||
$values = explode(',', $value);
|
||||
if(empty($values)) return array();
|
||||
|
||||
$stringList = array();
|
||||
foreach($values as $val)
|
||||
{
|
||||
if($val !== '') $stringList[] = $val;
|
||||
}
|
||||
return $stringList;
|
||||
case 'array':
|
||||
$array = array();
|
||||
if(!empty($value)) foreach($value as $v) $array[] = $v;
|
||||
return $array;
|
||||
case 'user':
|
||||
if(empty($value)) return null;
|
||||
if(empty($this->users)) $this->users = $this->dao->select('id,account,avatar,realname')->from(TABLE_USER)->fetchAll('account');
|
||||
return zget($this->users, $value, null);
|
||||
case 'userList':
|
||||
$values = explode(',', $value);
|
||||
if(empty($values)) return array();
|
||||
|
||||
$userList = array();
|
||||
foreach($values as $val)
|
||||
{
|
||||
$val = $this->cast($val, 'user');
|
||||
if($val) $userList[] = $val;
|
||||
}
|
||||
return $userList;
|
||||
default:
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -616,9 +665,23 @@ class baseEntry
|
||||
{
|
||||
$module = $this->app->getModuleName();
|
||||
$method = $this->app->getMethodName();
|
||||
if($module and $method and !commonModel::hasPriv($module, $method))
|
||||
if($module and $method and !$this->loadModel('common')->isOpenMethod($module, $method) and !commonModel::hasPriv($module, $method))
|
||||
{
|
||||
$this->send(403, array('error' => 'Access not allowed'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset open app.
|
||||
*
|
||||
* @param string $tab
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function resetOpenApp($tab)
|
||||
{
|
||||
$_COOKIE['tab'] = $tab;
|
||||
$this->app->tab = $tab;
|
||||
$this->app->session->tab = $tab;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,22 +82,13 @@ class api extends router
|
||||
|
||||
$this->httpMethod = strtolower($_SERVER['REQUEST_METHOD']);
|
||||
|
||||
if(!empty($_SERVER['PATH_INFO']))
|
||||
{
|
||||
$this->path = rtrim($_SERVER['PATH_INFO'], '/');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->path = rtrim((strpos($_SERVER['REQUEST_URI'], '?') > 0 ? strstr($_SERVER['REQUEST_URI'], '?', true) : $_SERVER['REQUEST_URI']), '/');
|
||||
}
|
||||
$fileName = ltrim(substr($_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT'])), '/');
|
||||
$this->path = substr(ltrim($_SERVER['REQUEST_URI'], '/'), strlen($fileName) + 1);
|
||||
if(strpos($this->path, '?') > 0) $this->path = strstr($this->path, '?', true);
|
||||
|
||||
$dir = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/');
|
||||
if($dir != '' and strpos($this->path, $dir) === 0) $this->path = substr($this->path, strlen($dir));
|
||||
|
||||
$subPos = strpos($this->path, '/', 1);
|
||||
|
||||
$this->version = $subPos ? substr($this->path, 1, $subPos - 1) : '';
|
||||
$this->path = $subPos ? substr($this->path, $subPos) : $this->path;
|
||||
$subPos = $this->path ? strpos($this->path, '/') : false;
|
||||
$this->version = $subPos !== false ? substr($this->path, 0, $subPos) : '';
|
||||
$this->path = $subPos !== false ? substr($this->path, $subPos) : '';
|
||||
|
||||
$this->loadApiLang();
|
||||
}
|
||||
@@ -230,7 +221,7 @@ class api extends router
|
||||
public function loadApiLang()
|
||||
{
|
||||
global $lang;
|
||||
include($this->appRoot . "api/$this->version/lang/$this->clientLang.php");
|
||||
if($this->version) include($this->appRoot . "api/$this->version/lang/$this->clientLang.php");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -927,6 +927,14 @@ class baseControl
|
||||
{
|
||||
if(!empty($data['message']))
|
||||
{
|
||||
if(is_string($data['message']))
|
||||
{
|
||||
echo js::alert($data['message']);
|
||||
$locate = isset($data['locate']) ? $data['locate'] : (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '');
|
||||
if (!empty($locate)) die(js::locate($locate));
|
||||
die(isset($data['message']) ? $data['message'] : 'fail');
|
||||
}
|
||||
|
||||
$message = json_decode(json_encode((array)$data['message']));
|
||||
foreach((array)$message as $item => $errors) $message->$item = implode(',', $errors);
|
||||
die(js::alert(strip_tags(implode('\n', (array)$message))));
|
||||
@@ -944,10 +952,7 @@ class baseControl
|
||||
*/
|
||||
public function sendError($error)
|
||||
{
|
||||
$this->send([
|
||||
'result' => 'fail',
|
||||
'message' => $error,
|
||||
]);
|
||||
$this->send(array('result' => 'fail', 'message' => $error));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -504,7 +504,12 @@ class baseHelper
|
||||
*/
|
||||
static public function diffDate($date1, $date2)
|
||||
{
|
||||
return round((strtotime($date1) - strtotime($date2)) / 86400, 0);
|
||||
/* Get the timestamp in the current operating system. */
|
||||
$date1 = new DateTime($date1);
|
||||
$date2 = new DateTime($date2);
|
||||
$date1 = date_format($date1, "U");
|
||||
$date2 = date_format($date2, "U");
|
||||
return round(($date1 - $date2) / 86400, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -512,7 +517,7 @@ class baseHelper
|
||||
* Get now time use the DT_DATETIME1 constant defined in the lang file.
|
||||
*
|
||||
* @access public
|
||||
* @return datetime now
|
||||
* @return string now
|
||||
*/
|
||||
static public function now()
|
||||
{
|
||||
@@ -524,7 +529,7 @@ class baseHelper
|
||||
* Get today according to the DT_DATE1 constant defined in the lang file.
|
||||
*
|
||||
* @access public
|
||||
* @return date today
|
||||
* @return string today
|
||||
*/
|
||||
static public function today()
|
||||
{
|
||||
@@ -536,7 +541,7 @@ class baseHelper
|
||||
* Get now time use the DT_TIME1 constant defined in the lang file.
|
||||
*
|
||||
* @access public
|
||||
* @return date today
|
||||
* @return string today
|
||||
*/
|
||||
static public function time()
|
||||
{
|
||||
@@ -743,10 +748,10 @@ class baseHelper
|
||||
* @param string $viewType
|
||||
* @return string the link string.
|
||||
*/
|
||||
function inLink($methodName = 'index', $vars = '', $viewType = '')
|
||||
function inLink($methodName = 'index', $vars = '', $viewType = '', $onlybody = false)
|
||||
{
|
||||
global $app;
|
||||
return helper::createLink($app->getModuleName(), $methodName, $vars, $viewType);
|
||||
return helper::createLink($app->getModuleName(), $methodName, $vars, $viewType, $onlybody);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -850,7 +855,7 @@ function getWebRoot($full = false)
|
||||
* @param mixed $valueWhenNone value when the key not exits.
|
||||
* @param mixed $valueWhenExists value when the key exits.
|
||||
* @access public
|
||||
* @return string
|
||||
* @return mixed
|
||||
*/
|
||||
function zget($var, $key, $valueWhenNone = false, $valueWhenExists = false)
|
||||
{
|
||||
@@ -882,3 +887,18 @@ function isHttps()
|
||||
if(!empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off') return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatibility for htmlspecialchars.
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $flags
|
||||
* @param string $encoding
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
function htmlSpecialString($string, $flags = '', $encoding = 'UTF-8')
|
||||
{
|
||||
if(!$flags) $flags = defined('ENT_SUBSTITUTE') ? ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 : ENT_QUOTES;
|
||||
return htmlspecialchars($string, $flags, $encoding);
|
||||
}
|
||||
|
||||
@@ -2250,6 +2250,7 @@ class baseRouter
|
||||
$view->methodVar = $this->config->methodVar;
|
||||
$view->viewVar = $this->config->viewVar;
|
||||
$view->sessionVar = $this->config->sessionVar;
|
||||
$view->systemMode = $this->config->systemMode;
|
||||
|
||||
$this->session->set('random', mt_rand(0, 10000));
|
||||
$view->sessionName = session_name();
|
||||
@@ -2420,7 +2421,7 @@ class baseRouter
|
||||
public function triggerError($message, $file, $line, $exit = false)
|
||||
{
|
||||
/* 设置错误信息(Set the error info) */
|
||||
$message = htmlspecialchars($message);
|
||||
$message = htmlSpecialString($message);
|
||||
if(preg_match('/[^\x00-\x80]/', $message)) $message = helper::convertEncoding($message, 'gbk');
|
||||
|
||||
/* Only show error when debug is open. */
|
||||
|
||||
@@ -117,7 +117,12 @@ class router extends baseRouter
|
||||
unset($lang->{$moduleName}->{$section});
|
||||
|
||||
if(isset($nullKey))$lang->{$moduleName}->{$section}[$nullKey] = $nullValue;
|
||||
foreach($fields as $key => $value) $lang->{$moduleName}->{$section}[$key] = $value;
|
||||
foreach($fields as $key => $value)
|
||||
{
|
||||
if(!isset($lang->{$moduleName})) $lang->{$moduleName} = new stdclass();
|
||||
if(!isset($lang->{$moduleName}->{$section})) $lang->{$moduleName}->{$section} = array();
|
||||
$lang->{$moduleName}->{$section}[$key] = $value;
|
||||
}
|
||||
unset($nullKey);
|
||||
unset($nullValue);
|
||||
}
|
||||
|
||||
+194
-177
@@ -17,8 +17,8 @@ class ztclient
|
||||
public $session;
|
||||
|
||||
/**
|
||||
* The construce function.
|
||||
*
|
||||
* The construce function.
|
||||
*
|
||||
* @param string $zentaoRoot the zentao root url
|
||||
* @param string $account the login account
|
||||
* @param string $password the passwod
|
||||
@@ -43,8 +43,8 @@ class ztclient
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings through getconfig api from remote.
|
||||
*
|
||||
* Get the settings through getconfig api from remote.
|
||||
*
|
||||
* @access private
|
||||
* @return object
|
||||
*/
|
||||
@@ -58,7 +58,7 @@ class ztclient
|
||||
|
||||
/**
|
||||
* Set the session api.
|
||||
*
|
||||
*
|
||||
* @access private
|
||||
* @return string the session api url.
|
||||
*/
|
||||
@@ -69,7 +69,7 @@ class ztclient
|
||||
|
||||
/**
|
||||
* Set the login api.
|
||||
*
|
||||
*
|
||||
* @access private
|
||||
* @return string the login api url.
|
||||
*/
|
||||
@@ -80,8 +80,8 @@ class ztclient
|
||||
|
||||
/**
|
||||
* Set the method api.
|
||||
*
|
||||
* @param string $module the module name
|
||||
*
|
||||
* @param string $module the module name
|
||||
* @param string $method the methhod name
|
||||
* @param string $vars the vars to passwd
|
||||
* @access private
|
||||
@@ -110,8 +110,8 @@ class ztclient
|
||||
|
||||
/**
|
||||
* Set the method api.
|
||||
*
|
||||
* @param string $module the module name
|
||||
*
|
||||
* @param string $module the module name
|
||||
* @param string $method the methhod name
|
||||
* @param string $vars the vars to passed
|
||||
* @access private
|
||||
@@ -138,8 +138,8 @@ class ztclient
|
||||
}
|
||||
|
||||
/**
|
||||
* Start session
|
||||
*
|
||||
* Start session
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -151,7 +151,7 @@ class ztclient
|
||||
|
||||
/**
|
||||
* Login.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -164,9 +164,9 @@ class ztclient
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch one method of a module's control.
|
||||
*
|
||||
* @param string $module the module name
|
||||
* Fetch one method of a module's control.
|
||||
*
|
||||
* @param string $module the module name
|
||||
* @param string $method the methhod name
|
||||
* @param string $vars the vars to passwd
|
||||
* @access public
|
||||
@@ -178,9 +178,9 @@ class ztclient
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch one method of a module's model.
|
||||
*
|
||||
* @param string $module the module name
|
||||
* Fetch one method of a module's model.
|
||||
*
|
||||
* @param string $module the module name
|
||||
* @param string $method the methhod name
|
||||
* @param string $vars the vars to passwd
|
||||
* @access public
|
||||
@@ -192,9 +192,9 @@ class ztclient
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a api and check it.
|
||||
*
|
||||
* @param string $url
|
||||
* Get a api and check it.
|
||||
*
|
||||
* @param string $url
|
||||
* @access private
|
||||
* @return bool
|
||||
*/
|
||||
@@ -209,9 +209,9 @@ class ztclient
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch one method of a module's control.
|
||||
*
|
||||
* @param string $module the module name
|
||||
* Fetch one method of a module's control.
|
||||
*
|
||||
* @param string $module the module name
|
||||
* @param string $method the methhod name
|
||||
* @param array $vars the vars to passwd
|
||||
* @access public
|
||||
@@ -224,8 +224,8 @@ class ztclient
|
||||
|
||||
/**
|
||||
* Post.
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @param string $url
|
||||
* @access private
|
||||
* @return bool
|
||||
*/
|
||||
@@ -241,8 +241,8 @@ class ztclient
|
||||
|
||||
/**
|
||||
* Append session param to the url.
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @param string $url
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
@@ -288,7 +288,7 @@ http://snoopy.sourceforge.net/
|
||||
class Snoopy
|
||||
{
|
||||
/**** Public variables ****/
|
||||
|
||||
|
||||
/* user definable vars */
|
||||
|
||||
var $host = "www.php.net"; // host name we are connecting to
|
||||
@@ -297,7 +297,7 @@ class Snoopy
|
||||
var $proxy_port = ""; // proxy port to use
|
||||
var $proxy_user = ""; // proxy user to use
|
||||
var $proxy_pass = ""; // proxy password to use
|
||||
|
||||
|
||||
var $agent = "Snoopy v1.2.4"; // agent we masquerade as
|
||||
var $referer = ""; // referer info to pass
|
||||
var $cookies = array(); // array of cookies to pass
|
||||
@@ -315,15 +315,15 @@ class Snoopy
|
||||
var $passcookies = true; // pass set cookies back through redirects
|
||||
// NOTE: this currently does not respect
|
||||
// dates, domains or paths.
|
||||
|
||||
|
||||
var $user = ""; // user for http authentication
|
||||
var $pass = ""; // password for http authentication
|
||||
|
||||
|
||||
// http accept types
|
||||
var $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
|
||||
|
||||
|
||||
var $results = ""; // where the content is put
|
||||
|
||||
|
||||
var $error = ""; // error messages sent here
|
||||
var $response_code = ""; // response code returned from server
|
||||
var $headers = array(); // headers returned from server sent here
|
||||
@@ -349,11 +349,11 @@ class Snoopy
|
||||
// library functions built into php,
|
||||
// as these functions are not stable
|
||||
// as of this Snoopy release.
|
||||
|
||||
/**** Private variables ****/
|
||||
|
||||
|
||||
/**** Private variables ****/
|
||||
|
||||
var $_maxlinelen = 4096; // max line length (headers)
|
||||
|
||||
|
||||
var $_httpmethod = "GET"; // default http request method
|
||||
var $_httpversion = "HTTP/1.0"; // default http request version
|
||||
var $_submit_method = "POST"; // default submit method
|
||||
@@ -363,7 +363,7 @@ class Snoopy
|
||||
var $_redirectdepth = 0; // increments on an http redirect
|
||||
var $_frameurls = array(); // frame src urls
|
||||
var $_framedepth = 0; // increments on frame depth
|
||||
|
||||
|
||||
var $_isproxy = false; // set if using a proxy server
|
||||
var $_fp_timeout = 30; // timeout for socket connection
|
||||
|
||||
@@ -378,7 +378,7 @@ class Snoopy
|
||||
|
||||
function fetch($URI)
|
||||
{
|
||||
|
||||
|
||||
//preg_match("|^([^:]+)://([^:/]+)(:[\d]+)*(.*)|",$URI,$URI_PARTS);
|
||||
$URI_PARTS = parse_url($URI);
|
||||
if (!empty($URI_PARTS["user"]))
|
||||
@@ -389,7 +389,7 @@ class Snoopy
|
||||
$URI_PARTS["query"] = '';
|
||||
if (empty($URI_PARTS["path"]))
|
||||
$URI_PARTS["path"] = '';
|
||||
|
||||
|
||||
switch(strtolower($URI_PARTS["scheme"]))
|
||||
{
|
||||
case "http":
|
||||
@@ -409,7 +409,7 @@ class Snoopy
|
||||
// no proxy, send only the path
|
||||
$this->_httprequest($path, $fp, $URI, $this->_httpmethod);
|
||||
}
|
||||
|
||||
|
||||
$this->_disconnect($fp);
|
||||
|
||||
if($this->_redirectaddr)
|
||||
@@ -432,8 +432,8 @@ class Snoopy
|
||||
{
|
||||
$frameurls = $this->_frameurls;
|
||||
$this->_frameurls = array();
|
||||
|
||||
while(list(,$frameurl) = each($frameurls))
|
||||
|
||||
foreach($frameurls as $frameurl))
|
||||
{
|
||||
if($this->_framedepth < $this->maxframes)
|
||||
{
|
||||
@@ -441,15 +441,17 @@ class Snoopy
|
||||
$this->_framedepth++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return true;
|
||||
break;
|
||||
case "https":
|
||||
if(!$this->curl_path)
|
||||
@@ -493,7 +495,7 @@ class Snoopy
|
||||
$frameurls = $this->_frameurls;
|
||||
$this->_frameurls = array();
|
||||
|
||||
while(list(,$frameurl) = each($frameurls))
|
||||
foreach($frameurls as $frameurl)
|
||||
{
|
||||
if($this->_framedepth < $this->maxframes)
|
||||
{
|
||||
@@ -501,17 +503,19 @@ class Snoopy
|
||||
$this->_framedepth++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
// not a valid protocol
|
||||
$this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n';
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -529,9 +533,9 @@ class Snoopy
|
||||
function submit($URI, $formvars="", $formfiles="")
|
||||
{
|
||||
unset($postdata);
|
||||
|
||||
|
||||
$postdata = $this->_prepare_post_body($formvars, $formfiles);
|
||||
|
||||
|
||||
$URI_PARTS = parse_url($URI);
|
||||
if (!empty($URI_PARTS["user"]))
|
||||
$this->user = $URI_PARTS["user"];
|
||||
@@ -561,17 +565,17 @@ class Snoopy
|
||||
// no proxy, send only the path
|
||||
$this->_httprequest($path, $fp, $URI, $this->_submit_method, $this->_submit_type, $postdata);
|
||||
}
|
||||
|
||||
|
||||
$this->_disconnect($fp);
|
||||
|
||||
if($this->_redirectaddr)
|
||||
{
|
||||
/* url was redirected, check if we've hit the max depth */
|
||||
if($this->maxredirs > $this->_redirectdepth)
|
||||
{
|
||||
{
|
||||
if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr))
|
||||
$this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]);
|
||||
|
||||
$this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]);
|
||||
|
||||
// only follow redirect if it's on this site, or offsiteok is true
|
||||
if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
|
||||
{
|
||||
@@ -590,9 +594,9 @@ class Snoopy
|
||||
{
|
||||
$frameurls = $this->_frameurls;
|
||||
$this->_frameurls = array();
|
||||
|
||||
while(list(,$frameurl) = each($frameurls))
|
||||
{
|
||||
|
||||
foreach($frameurls as $frameurl)
|
||||
{
|
||||
if($this->_framedepth < $this->maxframes)
|
||||
{
|
||||
$this->fetch($frameurl);
|
||||
@@ -601,14 +605,14 @@ class Snoopy
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return true;
|
||||
break;
|
||||
case "https":
|
||||
if(!$this->curl_path)
|
||||
@@ -635,9 +639,9 @@ class Snoopy
|
||||
{
|
||||
/* url was redirected, check if we've hit the max depth */
|
||||
if($this->maxredirs > $this->_redirectdepth)
|
||||
{
|
||||
{
|
||||
if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr))
|
||||
$this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]);
|
||||
$this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]);
|
||||
|
||||
// only follow redirect if it's on this site, or offsiteok is true
|
||||
if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
|
||||
@@ -658,8 +662,8 @@ class Snoopy
|
||||
$frameurls = $this->_frameurls;
|
||||
$this->_frameurls = array();
|
||||
|
||||
while(list(,$frameurl) = each($frameurls))
|
||||
{
|
||||
foreach($frameurls as $frameurl)
|
||||
{
|
||||
if($this->_framedepth < $this->maxframes)
|
||||
{
|
||||
$this->fetch($frameurl);
|
||||
@@ -668,16 +672,16 @@ class Snoopy
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
// not a valid protocol
|
||||
$this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n';
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -691,7 +695,7 @@ class Snoopy
|
||||
function fetchlinks($URI)
|
||||
{
|
||||
if ($this->fetch($URI))
|
||||
{
|
||||
{
|
||||
if($this->lastredirectaddr)
|
||||
$URI = $this->lastredirectaddr;
|
||||
if(is_array($this->results))
|
||||
@@ -719,9 +723,9 @@ class Snoopy
|
||||
|
||||
function fetchform($URI)
|
||||
{
|
||||
|
||||
|
||||
if ($this->fetch($URI))
|
||||
{
|
||||
{
|
||||
|
||||
if(is_array($this->results))
|
||||
{
|
||||
@@ -730,14 +734,14 @@ class Snoopy
|
||||
}
|
||||
else
|
||||
$this->results = $this->_stripform($this->results);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*======================================================================*\
|
||||
Function: fetchtext
|
||||
Purpose: fetch the text from a web page, stripping the links
|
||||
@@ -748,7 +752,7 @@ class Snoopy
|
||||
function fetchtext($URI)
|
||||
{
|
||||
if($this->fetch($URI))
|
||||
{
|
||||
{
|
||||
if(is_array($this->results))
|
||||
{
|
||||
for($x=0;$x<count($this->results);$x++)
|
||||
@@ -772,7 +776,7 @@ class Snoopy
|
||||
function submitlinks($URI, $formvars="", $formfiles="")
|
||||
{
|
||||
if($this->submit($URI,$formvars, $formfiles))
|
||||
{
|
||||
{
|
||||
if($this->lastredirectaddr)
|
||||
$URI = $this->lastredirectaddr;
|
||||
if(is_array($this->results))
|
||||
@@ -806,7 +810,7 @@ class Snoopy
|
||||
function submittext($URI, $formvars = "", $formfiles = "")
|
||||
{
|
||||
if($this->submit($URI,$formvars, $formfiles))
|
||||
{
|
||||
{
|
||||
if($this->lastredirectaddr)
|
||||
$URI = $this->lastredirectaddr;
|
||||
if(is_array($this->results))
|
||||
@@ -830,7 +834,7 @@ class Snoopy
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*======================================================================*\
|
||||
Function: set_submit_multipart
|
||||
@@ -842,7 +846,7 @@ class Snoopy
|
||||
$this->_submit_type = "multipart/form-data";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*\
|
||||
Function: set_submit_normal
|
||||
Purpose: Set the form submission content type to
|
||||
@@ -853,14 +857,14 @@ class Snoopy
|
||||
$this->_submit_type = "application/x-www-form-urlencoded";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*======================================================================*\
|
||||
Private functions
|
||||
\*======================================================================*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*======================================================================*\
|
||||
Function: _striplinks
|
||||
Purpose: strip the hyperlinks from an html document
|
||||
@@ -869,28 +873,28 @@ class Snoopy
|
||||
\*======================================================================*/
|
||||
|
||||
function _striplinks($document)
|
||||
{
|
||||
{
|
||||
preg_match_all("'<\s*a\s.*?href\s*=\s* # find <a href=
|
||||
([\"\'])? # find single or double quote
|
||||
(?(1) (.*?)\\1 | ([^\s\>]+)) # if quote found, match up to next matching
|
||||
# quote, otherwise match up to next space
|
||||
'isx",$document,$links);
|
||||
|
||||
|
||||
|
||||
// catenate the non-empty matches from the conditional subpattern
|
||||
|
||||
while(list($key,$val) = each($links[2]))
|
||||
foreach($links[2] as $key => $val)
|
||||
{
|
||||
if(!empty($val))
|
||||
$match[] = $val;
|
||||
}
|
||||
|
||||
while(list($key,$val) = each($links[3]))
|
||||
}
|
||||
|
||||
foreach($links[3] as $key => $val)
|
||||
{
|
||||
if(!empty($val))
|
||||
$match[] = $val;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// return the links
|
||||
return $match;
|
||||
}
|
||||
@@ -903,18 +907,18 @@ class Snoopy
|
||||
\*======================================================================*/
|
||||
|
||||
function _stripform($document)
|
||||
{
|
||||
{
|
||||
preg_match_all("'<\/?(FORM|INPUT|SELECT|TEXTAREA|(OPTION))[^<>]*>(?(2)(.*(?=<\/?(option|select)[^<>]*>[\r\n]*)|(?=[\r\n]*))|(?=[\r\n]*))'Usi",$document,$elements);
|
||||
|
||||
|
||||
// catenate the matches
|
||||
$match = implode("\r\n",$elements[0]);
|
||||
|
||||
|
||||
// return the links
|
||||
return $match;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*======================================================================*\
|
||||
Function: _striptext
|
||||
Purpose: strip the text from an html document
|
||||
@@ -924,11 +928,11 @@ class Snoopy
|
||||
|
||||
function _striptext($document)
|
||||
{
|
||||
|
||||
|
||||
// I didn't use preg eval (//e) since that is only available in PHP 4.0.
|
||||
// so, list your entities one by one here. I included some of the
|
||||
// more common ones.
|
||||
|
||||
|
||||
$search = array("'<script[^>]*?>.*?</script>'si", // strip out javascript
|
||||
"'<[\/\!]*?[^<>]*?>'si", // strip out html tags
|
||||
"'([\r\n])[\s]+'", // strip out white space
|
||||
@@ -977,9 +981,9 @@ class Snoopy
|
||||
"?",
|
||||
"?",
|
||||
);
|
||||
|
||||
|
||||
$text = preg_replace($search,$replace,$document);
|
||||
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
@@ -993,7 +997,7 @@ class Snoopy
|
||||
|
||||
function _expandlinks($links,$URI)
|
||||
{
|
||||
|
||||
|
||||
preg_match("/^[^\?]+/",$URI,$match);
|
||||
|
||||
$match = preg_replace("|/[^\/\.]+\.[^\/\.]+$|","",$match[0]);
|
||||
@@ -1001,21 +1005,21 @@ class Snoopy
|
||||
$match_part = parse_url($match);
|
||||
$match_root =
|
||||
$match_part["scheme"]."://".$match_part["host"];
|
||||
|
||||
|
||||
$search = array( "|^http://".preg_quote($this->host)."|i",
|
||||
"|^(\/)|i",
|
||||
"|^(?!http://)(?!mailto:)|i",
|
||||
"|/\./|",
|
||||
"|/[^\/]+/\.\./|"
|
||||
);
|
||||
|
||||
|
||||
$replace = array( "",
|
||||
$match_root."/",
|
||||
$match."/",
|
||||
"/",
|
||||
"/"
|
||||
);
|
||||
|
||||
);
|
||||
|
||||
$expandedLinks = preg_replace($search,$replace,$links);
|
||||
|
||||
return $expandedLinks;
|
||||
@@ -1028,19 +1032,19 @@ class Snoopy
|
||||
$fp the current open file pointer
|
||||
$URI the full URI
|
||||
$body body contents to send if any (POST)
|
||||
Output:
|
||||
Output:
|
||||
\*======================================================================*/
|
||||
|
||||
|
||||
function _httprequest($url,$fp,$URI,$http_method,$content_type="",$body="")
|
||||
{
|
||||
$cookie_headers = '';
|
||||
if($this->passcookies && $this->_redirectaddr)
|
||||
$this->setcookies();
|
||||
|
||||
|
||||
$URI_PARTS = parse_url($URI);
|
||||
if(empty($url))
|
||||
$url = "/";
|
||||
$headers = $http_method." ".$url." ".$this->_httpversion."\r\n";
|
||||
$headers = $http_method." ".$url." ".$this->_httpversion."\r\n";
|
||||
if(!empty($this->agent))
|
||||
$headers .= "User-Agent: ".$this->agent."\r\n";
|
||||
if(!empty($this->host) && !isset($this->rawheaders['Host'])) {
|
||||
@@ -1054,10 +1058,10 @@ class Snoopy
|
||||
if(!empty($this->referer))
|
||||
$headers .= "Referer: ".$this->referer."\r\n";
|
||||
if(!empty($this->cookies))
|
||||
{
|
||||
{
|
||||
if(!is_array($this->cookies))
|
||||
$this->cookies = (array)$this->cookies;
|
||||
|
||||
|
||||
reset($this->cookies);
|
||||
if ( count($this->cookies) > 0 ) {
|
||||
$cookie_headers .= 'Cookie: ';
|
||||
@@ -1065,14 +1069,18 @@ class Snoopy
|
||||
$cookie_headers .= $cookieKey."=".urlencode($cookieVal)."; ";
|
||||
}
|
||||
$headers .= substr($cookie_headers,0,-2) . "\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!empty($this->rawheaders))
|
||||
{
|
||||
if(!is_array($this->rawheaders))
|
||||
{
|
||||
$this->rawheaders = (array)$this->rawheaders;
|
||||
while(list($headerKey,$headerVal) = each($this->rawheaders))
|
||||
}
|
||||
foreach($this->rawheaders as $headerKey => $headerVal)
|
||||
{
|
||||
$headers .= $headerKey.": ".$headerVal."\r\n";
|
||||
}
|
||||
}
|
||||
if(!empty($content_type)) {
|
||||
$headers .= "Content-type: $content_type";
|
||||
@@ -1080,28 +1088,28 @@ class Snoopy
|
||||
$headers .= "; boundary=".$this->_mime_boundary;
|
||||
$headers .= "\r\n";
|
||||
}
|
||||
if(!empty($body))
|
||||
if(!empty($body))
|
||||
$headers .= "Content-length: ".strlen($body)."\r\n";
|
||||
if(!empty($this->user) || !empty($this->pass))
|
||||
if(!empty($this->user) || !empty($this->pass))
|
||||
$headers .= "Authorization: Basic ".base64_encode($this->user.":".$this->pass)."\r\n";
|
||||
|
||||
|
||||
//add proxy auth headers
|
||||
if(!empty($this->proxy_user))
|
||||
if(!empty($this->proxy_user))
|
||||
$headers .= 'Proxy-Authorization: ' . 'Basic ' . base64_encode($this->proxy_user . ':' . $this->proxy_pass)."\r\n";
|
||||
|
||||
|
||||
$headers .= "\r\n";
|
||||
|
||||
|
||||
// set the read timeout if needed
|
||||
if ($this->read_timeout > 0)
|
||||
socket_set_timeout($fp, $this->read_timeout);
|
||||
$this->timed_out = false;
|
||||
|
||||
|
||||
fwrite($fp,$headers.$body,strlen($headers.$body));
|
||||
|
||||
|
||||
$this->_redirectaddr = false;
|
||||
unset($this->headers);
|
||||
|
||||
|
||||
while($currentHeader = fgets($fp,$this->_maxlinelen))
|
||||
{
|
||||
if ($this->read_timeout > 0 && $this->_check_timeout($fp))
|
||||
@@ -1109,10 +1117,10 @@ class Snoopy
|
||||
$this->status=-100;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if($currentHeader == "\r\n")
|
||||
break;
|
||||
|
||||
|
||||
// if a header begins with Location: or URI:, set the redirect
|
||||
if(preg_match("/^(Location:|URI:)/i",$currentHeader))
|
||||
{
|
||||
@@ -1132,16 +1140,16 @@ class Snoopy
|
||||
else
|
||||
$this->_redirectaddr = $matches[2];
|
||||
}
|
||||
|
||||
|
||||
if(preg_match("|^HTTP/|",$currentHeader))
|
||||
{
|
||||
if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$currentHeader, $status))
|
||||
{
|
||||
$this->status= $status[1];
|
||||
}
|
||||
}
|
||||
$this->response_code = $currentHeader;
|
||||
}
|
||||
|
||||
|
||||
$this->headers[] = $currentHeader;
|
||||
}
|
||||
|
||||
@@ -1159,13 +1167,13 @@ class Snoopy
|
||||
$this->status=-100;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// check if there is a a redirect meta tag
|
||||
|
||||
|
||||
if(preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match))
|
||||
|
||||
{
|
||||
$this->_redirectaddr = $this->_expandlinks($match[1],$URI);
|
||||
$this->_redirectaddr = $this->_expandlinks($match[1],$URI);
|
||||
}
|
||||
|
||||
// have we hit our frame depth and is there frame src to fetch?
|
||||
@@ -1181,7 +1189,7 @@ class Snoopy
|
||||
// no framed content
|
||||
else
|
||||
$this->results = $results;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1191,21 +1199,21 @@ class Snoopy
|
||||
Input: $url the url to fetch
|
||||
$URI the full URI
|
||||
$body body contents to send if any (POST)
|
||||
Output:
|
||||
Output:
|
||||
\*======================================================================*/
|
||||
|
||||
|
||||
function _httpsrequest($url,$URI,$http_method,$content_type="",$body="")
|
||||
{
|
||||
{
|
||||
if($this->passcookies && $this->_redirectaddr)
|
||||
$this->setcookies();
|
||||
|
||||
$headers = array();
|
||||
|
||||
$headers = array();
|
||||
|
||||
$URI_PARTS = parse_url($URI);
|
||||
if(empty($url))
|
||||
$url = "/";
|
||||
// GET ... header not needed for curl
|
||||
//$headers[] = $http_method." ".$url." ".$this->_httpversion;
|
||||
//$headers[] = $http_method." ".$url." ".$this->_httpversion;
|
||||
if(!empty($this->agent))
|
||||
$headers[] = "User-Agent: ".$this->agent;
|
||||
if(!empty($this->host))
|
||||
@@ -1218,10 +1226,10 @@ class Snoopy
|
||||
if(!empty($this->referer))
|
||||
$headers[] = "Referer: ".$this->referer;
|
||||
if(!empty($this->cookies))
|
||||
{
|
||||
{
|
||||
if(!is_array($this->cookies))
|
||||
$this->cookies = (array)$this->cookies;
|
||||
|
||||
|
||||
reset($this->cookies);
|
||||
if ( count($this->cookies) > 0 ) {
|
||||
$cookie_str = 'Cookie: ';
|
||||
@@ -1234,9 +1242,13 @@ class Snoopy
|
||||
if(!empty($this->rawheaders))
|
||||
{
|
||||
if(!is_array($this->rawheaders))
|
||||
{
|
||||
$this->rawheaders = (array)$this->rawheaders;
|
||||
while(list($headerKey,$headerVal) = each($this->rawheaders))
|
||||
}
|
||||
foreach($this->rawheaders as $headerKey => $headerVal)
|
||||
{
|
||||
$headers[] = $headerKey.": ".$headerVal;
|
||||
}
|
||||
}
|
||||
if(!empty($content_type)) {
|
||||
if ($content_type == "multipart/form-data")
|
||||
@@ -1244,43 +1256,43 @@ class Snoopy
|
||||
else
|
||||
$headers[] = "Content-type: $content_type";
|
||||
}
|
||||
if(!empty($body))
|
||||
if(!empty($body))
|
||||
$headers[] = "Content-length: ".strlen($body);
|
||||
if(!empty($this->user) || !empty($this->pass))
|
||||
if(!empty($this->user) || !empty($this->pass))
|
||||
$headers[] = "Authorization: BASIC ".base64_encode($this->user.":".$this->pass);
|
||||
|
||||
|
||||
for($curr_header = 0; $curr_header < count($headers); $curr_header++) {
|
||||
$safer_header = strtr( $headers[$curr_header], "\"", " " );
|
||||
$cmdline_params .= " -H \"".$safer_header."\"";
|
||||
}
|
||||
|
||||
|
||||
if(!empty($body))
|
||||
$cmdline_params .= " -d \"$body\"";
|
||||
|
||||
|
||||
if($this->read_timeout > 0)
|
||||
$cmdline_params .= " -m ".$this->read_timeout;
|
||||
|
||||
|
||||
$headerfile = tempnam($temp_dir, "sno");
|
||||
|
||||
exec($this->curl_path." -k -D \"$headerfile\"".$cmdline_params." \"".escapeshellcmd($URI)."\"",$results,$return);
|
||||
|
||||
|
||||
if($return)
|
||||
{
|
||||
$this->error = "Error: cURL could not retrieve the document, error $return.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$results = implode("\r\n",$results);
|
||||
|
||||
|
||||
$result_headers = file("$headerfile");
|
||||
|
||||
|
||||
$this->_redirectaddr = false;
|
||||
unset($this->headers);
|
||||
|
||||
|
||||
for($currentHeader = 0; $currentHeader < count($result_headers); $currentHeader++)
|
||||
{
|
||||
|
||||
|
||||
// if a header begins with Location: or URI:, set the redirect
|
||||
if(preg_match("/^(Location: |URI: )/i",$result_headers[$currentHeader]))
|
||||
{
|
||||
@@ -1300,7 +1312,7 @@ class Snoopy
|
||||
else
|
||||
$this->_redirectaddr = $matches[2];
|
||||
}
|
||||
|
||||
|
||||
if(preg_match("|^HTTP/|",$result_headers[$currentHeader]))
|
||||
$this->response_code = $result_headers[$currentHeader];
|
||||
|
||||
@@ -1308,10 +1320,10 @@ class Snoopy
|
||||
}
|
||||
|
||||
// check if there is a a redirect meta tag
|
||||
|
||||
|
||||
if(preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match))
|
||||
{
|
||||
$this->_redirectaddr = $this->_expandlinks($match[1],$URI);
|
||||
$this->_redirectaddr = $this->_expandlinks($match[1],$URI);
|
||||
}
|
||||
|
||||
// have we hit our frame depth and is there frame src to fetch?
|
||||
@@ -1329,7 +1341,7 @@ class Snoopy
|
||||
$this->results = $results;
|
||||
|
||||
unlink("$headerfile");
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1337,7 +1349,7 @@ class Snoopy
|
||||
Function: setcookies()
|
||||
Purpose: set cookies for a redirection
|
||||
\*======================================================================*/
|
||||
|
||||
|
||||
function setcookies()
|
||||
{
|
||||
for($x=0; $x<count($this->headers); $x++)
|
||||
@@ -1347,7 +1359,7 @@ class Snoopy
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*\
|
||||
Function: _check_timeout
|
||||
Purpose: checks whether timeout has occurred
|
||||
@@ -1371,13 +1383,13 @@ class Snoopy
|
||||
Purpose: make a socket connection
|
||||
Input: $fp file pointer
|
||||
\*======================================================================*/
|
||||
|
||||
|
||||
function _connect(&$fp)
|
||||
{
|
||||
if(!empty($this->proxy_host) && !empty($this->proxy_port))
|
||||
{
|
||||
$this->_isproxy = true;
|
||||
|
||||
|
||||
$host = $this->proxy_host;
|
||||
$port = $this->proxy_port;
|
||||
}
|
||||
@@ -1386,9 +1398,9 @@ class Snoopy
|
||||
$host = $this->host;
|
||||
$port = $this->port;
|
||||
}
|
||||
|
||||
|
||||
$this->status = 0;
|
||||
|
||||
|
||||
if($fp = fsockopen(
|
||||
$host,
|
||||
$port,
|
||||
@@ -1424,13 +1436,13 @@ class Snoopy
|
||||
Purpose: disconnect a socket connection
|
||||
Input: $fp file pointer
|
||||
\*======================================================================*/
|
||||
|
||||
|
||||
function _disconnect($fp)
|
||||
{
|
||||
return(fclose($fp));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*\
|
||||
Function: _prepare_post_body
|
||||
Purpose: Prepare post body according to encoding type
|
||||
@@ -1438,7 +1450,7 @@ class Snoopy
|
||||
$formfiles - form upload files
|
||||
Output: post body
|
||||
\*======================================================================*/
|
||||
|
||||
|
||||
function _prepare_post_body($formvars, $formfiles)
|
||||
{
|
||||
settype($formvars, "array");
|
||||
@@ -1447,27 +1459,32 @@ class Snoopy
|
||||
|
||||
if (count($formvars) == 0 && count($formfiles) == 0)
|
||||
return;
|
||||
|
||||
|
||||
switch ($this->_submit_type) {
|
||||
case "application/x-www-form-urlencoded":
|
||||
reset($formvars);
|
||||
while(list($key,$val) = each($formvars)) {
|
||||
foreach($formvars as $key => $val)
|
||||
{
|
||||
if (is_array($val) || is_object($val)) {
|
||||
while (list($cur_key, $cur_val) = each($val)) {
|
||||
foreach($val as $cur_key => $cur_val)
|
||||
{
|
||||
$postdata .= urlencode($key)."[]=".urlencode($cur_val)."&";
|
||||
}
|
||||
} else
|
||||
{
|
||||
$postdata .= urlencode($key)."=".urlencode($val)."&";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "multipart/form-data":
|
||||
$this->_mime_boundary = "Snoopy".md5(uniqid(microtime()));
|
||||
|
||||
|
||||
reset($formvars);
|
||||
while(list($key,$val) = each($formvars)) {
|
||||
foreach($formvars as $key => $val)
|
||||
{
|
||||
if (is_array($val) || is_object($val)) {
|
||||
while (list($cur_key, $cur_val) = each($val)) {
|
||||
foreach($val as $cur_key => $cur_val) {
|
||||
$postdata .= "--".$this->_mime_boundary."\r\n";
|
||||
$postdata .= "Content-Disposition: form-data; name=\"$key\[\]\"\r\n\r\n";
|
||||
$postdata .= "$cur_val\r\n";
|
||||
@@ -1478,11 +1495,11 @@ class Snoopy
|
||||
$postdata .= "$val\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
reset($formfiles);
|
||||
while (list($field_name, $file_names) = each($formfiles)) {
|
||||
foreach($formfiles as $field_name => $file_names) {
|
||||
settype($file_names, "array");
|
||||
while (list(, $file_name) = each($file_names)) {
|
||||
foreach($file_names as $file_name) {
|
||||
if (!is_readable($file_name)) continue;
|
||||
|
||||
$fp = fopen($file_name, "r");
|
||||
|
||||
@@ -108,8 +108,6 @@ class baseHTML
|
||||
*/
|
||||
static public function a($href = '', $title = '', $misc = '', $newline = true)
|
||||
{
|
||||
global $config;
|
||||
|
||||
if(strlen(trim($title)) == 0) $title = $href;
|
||||
$newline = $newline ? "\n" : '';
|
||||
|
||||
@@ -491,7 +489,7 @@ class baseHTML
|
||||
|
||||
$gobackLink = "<a href='javascript:history.go(-1)' class='btn btn-back $class' $misc>{$label}</a>";
|
||||
$tab = $_COOKIE['tab'];
|
||||
$referer = isset($_SERVER['HTTP_REFERER']) ? strtolower($_SERVER['HTTP_REFERER']) : '';
|
||||
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
|
||||
$refererParts = parse_url($referer);
|
||||
|
||||
if($config->requestType == 'PATH_INFO' and empty($refererParts)) return $gobackLink;
|
||||
@@ -504,7 +502,7 @@ class baseHTML
|
||||
$gobackLink = isset($gobackList[$tab]) ? $gobackList[$tab] : '';
|
||||
|
||||
/* If the link of the referer is not the link of the current page or the link of the index, the cookie and gobackLink will be updated. */
|
||||
if(!preg_match("/(m=|\/)(index|search|$currentModule)(&f=|-)(index|buildquery|$currentMethod)(&|-|\.)?/", $refererLink))
|
||||
if(!preg_match("/(m=|\/)(index|search|$currentModule)(&f=|-)(index|buildquery|$currentMethod)(&|-|\.)?/", strtolower($refererLink)))
|
||||
{
|
||||
$gobackList[$tab] = $referer;
|
||||
$gobackLink = $referer;
|
||||
|
||||
@@ -136,7 +136,7 @@ class dingapi
|
||||
$node['id'] = $deptID;
|
||||
$node['pId'] = $parentID;
|
||||
$node['name'] = $deptName;
|
||||
if($parentID == 0) $node['open'] = true;
|
||||
$node['open'] = true;
|
||||
|
||||
$tree[] = $node;
|
||||
}
|
||||
|
||||
@@ -52,17 +52,23 @@ class feishuapi
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getAllUsers()
|
||||
public function getAllUsers($selectedDepts = '')
|
||||
{
|
||||
$selectedDepts = trim($selectedDepts);
|
||||
if(empty($selectedDepts)) return array('result' => 'fail', 'message' => 'nodept');
|
||||
|
||||
set_time_limit(0);
|
||||
|
||||
$users = array();
|
||||
$depts = $this->getDepts();
|
||||
$depts = explode(',', $selectedDepts);
|
||||
$depts = array_flip($depts);
|
||||
unset($depts[1]);
|
||||
if(empty($depts)) return array('result' => 'fail', 'message' => 'nodept');
|
||||
|
||||
/* Get users by dept. */
|
||||
foreach($depts as $deptID => $count)
|
||||
{
|
||||
if($deptID and empty($count)) continue;
|
||||
if(empty($deptID)) continue;
|
||||
|
||||
$pageToken = '';
|
||||
while(true)
|
||||
@@ -138,6 +144,46 @@ class feishuapi
|
||||
return $depts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get department tree structure.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getDeptTree()
|
||||
{
|
||||
$depts = array('result' => 'success', 'data' => array());
|
||||
|
||||
/* Gets the enterprise name. */
|
||||
$response = $this->queryAPI($this->apiUrl . "tenant/v2/tenant/query", '', array(CURLOPT_CUSTOMREQUEST => "GET"));
|
||||
$company = array('id' => '1', 'pId' => '0', 'name' => $response->data->tenant->name, 'open' => 1);
|
||||
$data = array($company);
|
||||
|
||||
/* Get depts by parent dept. */
|
||||
$pageToken = '';
|
||||
while(true)
|
||||
{
|
||||
$response = $this->queryAPI($this->apiUrl . "contact/v3/departments?parent_department_id=0" . ($pageToken ? "&page_token={$pageToken}" : '') . "&fetch_child=true", '', array(CURLOPT_CUSTOMREQUEST => "GET"));
|
||||
if(isset($response->data->items))
|
||||
{
|
||||
foreach($response->data->items as $key => $dept)
|
||||
{
|
||||
$key ++;
|
||||
$data[$key]['id'] = $dept->open_department_id;
|
||||
$data[$key]['pId'] = empty($dept->parent_department_id) ? 1 : $dept->parent_department_id;
|
||||
$data[$key]['name'] = $dept->name;
|
||||
$data[$key]['open'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!isset($response->data->page_token)) break;
|
||||
$pageToken = $response->data->page_token;
|
||||
}
|
||||
|
||||
$depts['data'] = $data;
|
||||
return $depts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message
|
||||
*
|
||||
@@ -179,6 +225,11 @@ class feishuapi
|
||||
|
||||
if(empty($response)) $this->errors = $errors;
|
||||
if(isset($response->code)) $this->errors[$response->code] = "Errcode:{$response->code}, Errmsg:{$response->msg}";
|
||||
if(!empty($this->errors))
|
||||
{
|
||||
echo js::error(array_shift($this->errors));
|
||||
die(js::locate(helper::createLink('webhook', 'browse')));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ class html extends baseHTML
|
||||
/**
|
||||
* Create user avatar.
|
||||
*
|
||||
* @param string|object|array $user User object or user avatar url or user account
|
||||
* @param string|object|array $user User object or user account
|
||||
* @param string|int $size Avatar size, can be a number or preset sizes: "xs", "sm", "", "lg", "xl", default is ""
|
||||
* @param string $className Avatar element class name, default is "avatar-circle"
|
||||
* @param string $attrib Extra attributes on avatar element
|
||||
@@ -248,7 +248,6 @@ class html extends baseHTML
|
||||
if(is_string($user))
|
||||
{
|
||||
$userObj->account = $user;
|
||||
if(strlen($user) > 1) $userObj->avatar = $user;
|
||||
$user = $userObj;
|
||||
}
|
||||
elseif(is_array($user))
|
||||
@@ -316,6 +315,21 @@ class html extends baseHTML
|
||||
{
|
||||
return html::avatar($user, 'lg', $className, $attrib, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a progress ring.
|
||||
*
|
||||
* @param int progress Progress value, 0 ~ 100
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
static public function ring($progress)
|
||||
{
|
||||
$progressVal = max(0, min(100, round($progress)));
|
||||
$ringPosition = ceil($progressVal / 2) * 24;
|
||||
return "<div class='ring' style='background-position-x: -{$ringPosition}px'><span>{$progressVal}</span></div>";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,566 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of the HTMLUP package.
|
||||
*
|
||||
* (c) Jitendra Adhikari <jiten.adhikary@gmail.com>
|
||||
* <https://github.com/adhocore>
|
||||
*
|
||||
* Licensed under MIT license.
|
||||
*/
|
||||
|
||||
trait HtmlHelper
|
||||
{
|
||||
public function escape($input)
|
||||
{
|
||||
return \htmlspecialchars($input);
|
||||
}
|
||||
|
||||
public function h($level, $line)
|
||||
{
|
||||
if (\is_string($level)) {
|
||||
$level = \trim($level, '- ') === '' ? 2 : 1;
|
||||
}
|
||||
|
||||
if ($level < 7) {
|
||||
return "\n<h{$level}>" . \ltrim(\ltrim($line, '# ')) . "</h{$level}>";
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function hr($prevLine, $line)
|
||||
{
|
||||
if ($prevLine === '' && \preg_match(BlockElementParser::RE_MD_RULE, $line)) {
|
||||
return "\n<hr />";
|
||||
}
|
||||
}
|
||||
|
||||
public function codeStart($lang)
|
||||
{
|
||||
$lang = isset($lang[1])
|
||||
? ' class="language-' . $lang[1] . '"'
|
||||
: '';
|
||||
|
||||
return "\n<pre><code{$lang}>";
|
||||
}
|
||||
|
||||
public function codeLine($line, $isBlock, $indentLen = 4)
|
||||
{
|
||||
$code = "\n"; // @todo: donot use \n for first line
|
||||
$code .= $isBlock ? $line : \substr($line, $indentLen);
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
public function tableStart($line, $delim = '|')
|
||||
{
|
||||
$table = "<table>\n<thead>\n<tr>\n";
|
||||
|
||||
foreach (\explode($delim, \trim($line, $delim)) as $hdr) {
|
||||
$table .= '<th>' . \trim($hdr) . "</th>\n";
|
||||
}
|
||||
|
||||
$table .= "</tr>\n</thead>\n<tbody>\n";
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
public function tableRow($line, $colCount, $delim = '|')
|
||||
{
|
||||
$row = "<tr>\n";
|
||||
|
||||
foreach (\explode($delim, \trim($line, $delim)) as $i => $col) {
|
||||
if ($i > $colCount) {
|
||||
break;
|
||||
}
|
||||
|
||||
$col = \trim($col);
|
||||
$row .= "<td>{$col}</td>\n";
|
||||
}
|
||||
|
||||
$row .= "</tr>\n";
|
||||
|
||||
return $row;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class BlockElementParser
|
||||
{
|
||||
use HtmlHelper;
|
||||
|
||||
const RE_MD_QUOTE = '~^\s*(>+)\s+~';
|
||||
const RE_RAW = '/^<\/?\w.*?\/?>/';
|
||||
const RE_MD_SETEXT = '~^\s*(={3,}|-{3,})\s*$~';
|
||||
const RE_MD_CODE = '/^```\s*([\w-]+)?/';
|
||||
const RE_MD_RULE = '~^(_{3,}|\*{3,}|\-{3,})$~';
|
||||
const RE_MD_TCOL = '~(\|\s*\:)?\s*\-{3,}\s*(\:\s*\|)?~';
|
||||
const RE_MD_OL = '/^\d+\. /';
|
||||
|
||||
protected $lines = [];
|
||||
protected $stackList = [];
|
||||
protected $stackBlock = [];
|
||||
protected $stackTable = [];
|
||||
|
||||
protected $pointer = -1;
|
||||
protected $listLevel = 0;
|
||||
protected $quoteLevel = 0;
|
||||
protected $indent = 0;
|
||||
protected $nextIndent = 0;
|
||||
protected $indentLen = 4;
|
||||
|
||||
protected $indentStr = ' ';
|
||||
protected $line = '';
|
||||
protected $trimmedLine = '';
|
||||
protected $prevLine = '';
|
||||
protected $trimmedPrevLine = '';
|
||||
protected $nextLine = '';
|
||||
protected $trimmedNextLine = '';
|
||||
protected $markup = '';
|
||||
|
||||
protected $inList = \false;
|
||||
protected $inQuote = \false;
|
||||
protected $inPara = \false;
|
||||
protected $inHtml = \false;
|
||||
protected $inTable = \false;
|
||||
|
||||
protected function parseBlockElements()
|
||||
{
|
||||
while (isset($this->lines[++$this->pointer])) {
|
||||
$this->init();
|
||||
|
||||
if ($this->flush() || $this->raw()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->quote();
|
||||
|
||||
if (($block = $this->isBlock()) || $this->inList) {
|
||||
$this->markup .= $block ? '' : $this->trimmedLine;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->table() || $this->paragraph();
|
||||
}
|
||||
}
|
||||
|
||||
protected function isBlock()
|
||||
{
|
||||
return $this->atx() || $this->setext() || $this->code() || $this->rule() || $this->listt();
|
||||
}
|
||||
|
||||
protected function atx()
|
||||
{
|
||||
if (\substr($this->trimmedLine, 0, 1) === '#') {
|
||||
$level = \strlen($this->trimmedLine) - \strlen(\ltrim($this->trimmedLine, '#'));
|
||||
$head = $this->h($level, $this->trimmedLine);
|
||||
|
||||
$this->markup .= $head;
|
||||
|
||||
return (bool) $head;
|
||||
}
|
||||
}
|
||||
|
||||
protected function setext()
|
||||
{
|
||||
if (\preg_match(static::RE_MD_SETEXT, $this->nextLine)) {
|
||||
$this->markup .= $this->h($this->nextLine, $this->trimmedLine);
|
||||
|
||||
$this->pointer++;
|
||||
|
||||
return \true;
|
||||
}
|
||||
}
|
||||
|
||||
protected function code()
|
||||
{
|
||||
$isShifted = ($this->indent - $this->nextIndent) >= $this->indentLen;
|
||||
$codeBlock = \preg_match(static::RE_MD_CODE, $this->line, $codeMatch);
|
||||
|
||||
if ($codeBlock || (!$this->inList && !$this->inQuote && $isShifted)) {
|
||||
$this->markup .= $this->codeStart($codeMatch);
|
||||
|
||||
if (!$codeBlock) {
|
||||
$this->markup .= $this->escape(\substr($this->line, $this->indentLen));
|
||||
}
|
||||
|
||||
$this->codeInternal($codeBlock);
|
||||
|
||||
$this->pointer++;
|
||||
|
||||
$this->markup .= '</code></pre>';
|
||||
|
||||
return \true;
|
||||
}
|
||||
}
|
||||
|
||||
private function codeInternal($codeBlock)
|
||||
{
|
||||
while (isset($this->lines[$this->pointer + 1])) {
|
||||
$this->line = $this->escape($this->lines[$this->pointer + 1]);
|
||||
|
||||
if (($codeBlock && \substr(\ltrim($this->line), 0, 3) !== '```')
|
||||
|| \strpos($this->line, $this->indentStr) === 0
|
||||
) {
|
||||
$this->markup .= $this->codeLine($this->line, $codeBlock, $this->indentLen);
|
||||
|
||||
$this->pointer++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected function rule()
|
||||
{
|
||||
$this->markup .= $hr = $this->hr($this->trimmedPrevLine, $this->trimmedLine);
|
||||
|
||||
return (bool) $hr;
|
||||
}
|
||||
|
||||
protected function listt()
|
||||
{
|
||||
$isUl = \in_array(\substr($this->trimmedLine, 0, 2), ['- ', '* ', '+ ']);
|
||||
|
||||
if ($isUl || \preg_match(static::RE_MD_OL, $this->trimmedLine)) {
|
||||
$wrapper = $isUl ? 'ul' : 'ol';
|
||||
|
||||
if (!$this->inList) {
|
||||
$this->stackList[] = "</$wrapper>";
|
||||
|
||||
$this->markup .= "\n<$wrapper>\n";
|
||||
$this->inList = \true;
|
||||
|
||||
$this->listLevel++;
|
||||
}
|
||||
|
||||
$this->markup .= '<li>' . \ltrim($this->trimmedLine, '+-*0123456789. ');
|
||||
|
||||
$this->listInternal();
|
||||
|
||||
return \true;
|
||||
}
|
||||
}
|
||||
|
||||
private function listInternal()
|
||||
{
|
||||
$isUl = \in_array(\substr($this->trimmedNextLine, 0, 2), ['- ', '* ', '+ ']);
|
||||
|
||||
if ($isUl || \preg_match(static::RE_MD_OL, $this->trimmedNextLine)) {
|
||||
$wrapper = $isUl ? 'ul' : 'ol';
|
||||
if ($this->nextIndent > $this->indent) {
|
||||
$this->stackList[] = "</li>\n";
|
||||
$this->stackList[] = "</$wrapper>";
|
||||
$this->markup .= "\n<$wrapper>\n";
|
||||
|
||||
$this->listLevel++;
|
||||
} else {
|
||||
$this->markup .= "</li>\n";
|
||||
}
|
||||
|
||||
if ($this->nextIndent < $this->indent) {
|
||||
$shift = \intval(($this->indent - $this->nextIndent) / $this->indentLen);
|
||||
|
||||
while ($shift--) {
|
||||
$this->markup .= \array_pop($this->stackList);
|
||||
|
||||
if ($this->listLevel > 2) {
|
||||
$this->markup .= \array_pop($this->stackList);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->markup .= "</li>\n";
|
||||
}
|
||||
}
|
||||
|
||||
protected function table()
|
||||
{
|
||||
static $headerCount = 0;
|
||||
|
||||
if (!$this->inTable) {
|
||||
$headerCount = \substr_count(\trim($this->trimmedLine, '|'), '|');
|
||||
|
||||
return $this->tableInternal($headerCount);
|
||||
}
|
||||
|
||||
$this->markup .= $this->tableRow($this->trimmedLine, $headerCount);
|
||||
|
||||
if (empty($this->trimmedNextLine)
|
||||
|| !\substr_count(\trim($this->trimmedNextLine, '|'), '|')
|
||||
) {
|
||||
$headerCount = 0;
|
||||
$this->inTable = \false;
|
||||
$this->stackTable[] = "</tbody>\n</table>";
|
||||
}
|
||||
|
||||
return \true;
|
||||
}
|
||||
|
||||
private function tableInternal($headerCount)
|
||||
{
|
||||
$columnCount = \preg_match_all(static::RE_MD_TCOL, \trim($this->trimmedNextLine, '|'));
|
||||
|
||||
if ($headerCount > 0 && $headerCount <= $columnCount) {
|
||||
$this->pointer++;
|
||||
|
||||
$this->inTable = \true;
|
||||
$this->markup .= $this->tableStart($this->trimmedLine);
|
||||
|
||||
return \true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SpanElementParser
|
||||
{
|
||||
use HtmlHelper;
|
||||
|
||||
const RE_URL = '~<(https?:[\/]{2}[^\s]+?)>~';
|
||||
const RE_EMAIL = '~<(\S+?@\S+?)>~';
|
||||
const RE_MD_IMG = '~!\[(.+?)\]\s*\((.+?)\s*(".+?")?\)~';
|
||||
const RE_MD_URL = '~\[(.+?)\]\s*\((.+?)\s*(".+?")?\)~';
|
||||
const RE_MD_FONT = '!(\*{1,2}|_{1,2}|`|~~)(.+?)\\1!';
|
||||
|
||||
public function parse($markup)
|
||||
{
|
||||
return $this->spans(
|
||||
$this->anchors(
|
||||
$this->links($markup)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected function links($markup)
|
||||
{
|
||||
$markup = $this->emails($markup);
|
||||
|
||||
return \preg_replace(
|
||||
static::RE_URL,
|
||||
'<a href="$1">$1</a>',
|
||||
$markup
|
||||
);
|
||||
}
|
||||
|
||||
protected function emails($markup)
|
||||
{
|
||||
return \preg_replace(
|
||||
static::RE_EMAIL,
|
||||
'<a href="mailto:$1">$1</a>',
|
||||
$markup
|
||||
);
|
||||
}
|
||||
|
||||
protected function anchors($markup)
|
||||
{
|
||||
$markup = $this->images($markup);
|
||||
|
||||
return \preg_replace_callback(static::RE_MD_URL, function ($a) {
|
||||
$title = isset($a[3]) ? " title={$a[3]} " : '';
|
||||
|
||||
return "<a href=\"{$a[2]}\"{$title}>{$a[1]}</a>";
|
||||
}, $markup);
|
||||
}
|
||||
|
||||
protected function images($markup)
|
||||
{
|
||||
return \preg_replace_callback(static::RE_MD_IMG, function ($img) {
|
||||
$title = isset($img[3]) ? " title={$img[3]} " : '';
|
||||
$alt = $img[1] ? " alt=\"{$img[1]}\" " : '';
|
||||
|
||||
return "<img src=\"{$img[2]}\"{$title}{$alt}/>";
|
||||
}, $markup);
|
||||
}
|
||||
|
||||
protected function spans($markup)
|
||||
{
|
||||
// em/code/strong/del
|
||||
return \preg_replace_callback(static::RE_MD_FONT, function ($em) {
|
||||
switch (\substr($em[1], 0, 2)) {
|
||||
case '**':
|
||||
case '__':
|
||||
$tag = 'strong';
|
||||
break;
|
||||
|
||||
case '~~':
|
||||
$tag = 'del';
|
||||
break;
|
||||
|
||||
case $em[1] === '*':
|
||||
case $em[1] === '_':
|
||||
$tag = 'em';
|
||||
break;
|
||||
|
||||
default:
|
||||
$tag = 'code';
|
||||
$em[2] = $this->escape($em[2]);
|
||||
}
|
||||
|
||||
return "<$tag>{$em[2]}</$tag>";
|
||||
}, $markup);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HtmlUp - A **lightweight** && **fast** `markdown` to HTML Parser.
|
||||
*
|
||||
* Supports most of the markdown specs except deep nested elements.
|
||||
* Check readme.md for the details of its features && limitations.
|
||||
*
|
||||
* @author adhocore | Jitendra Adhikari <jiten.adhikary@gmail.com>
|
||||
* @copyright (c) 2014 Jitendra Adhikari
|
||||
*/
|
||||
class htmlup extends BlockElementParser
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $markdown
|
||||
* @param int $indentWidth
|
||||
*/
|
||||
public function __construct($markdown = \null, $indentWidth = 4)
|
||||
{
|
||||
$this->scan($markdown, $indentWidth);
|
||||
}
|
||||
|
||||
protected function scan($markdown, $indentWidth = 4)
|
||||
{
|
||||
if ('' === \trim($markdown)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->indentLen = $indentWidth == 2 ? 2 : 4;
|
||||
$this->indentStr = $indentWidth == 2 ? ' ' : ' ';
|
||||
|
||||
// Normalize whitespaces
|
||||
$markdown = \str_replace("\t", $this->indentStr, $markdown);
|
||||
$markdown = \str_replace(["\r\n", "\r"], "\n", $markdown);
|
||||
|
||||
$this->lines = \array_merge([''], \explode("\n", $markdown), ['']);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->parse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse markdown.
|
||||
*
|
||||
* @param string $markdown
|
||||
* @param int $indentWidth
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parse($markdown = \null, $indentWidth = 4)
|
||||
{
|
||||
if (\null !== $markdown) {
|
||||
$this->reset(\true);
|
||||
|
||||
$this->scan($markdown, $indentWidth);
|
||||
}
|
||||
|
||||
if (empty($this->lines)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$this->parseBlockElements();
|
||||
|
||||
return (new SpanElementParser)->parse($this->markup);
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
list($this->prevLine, $this->trimmedPrevLine) = [$this->line, $this->trimmedLine];
|
||||
|
||||
$this->line = $this->lines[$this->pointer];
|
||||
$this->trimmedLine = \trim($this->line);
|
||||
|
||||
$this->indent = \strlen($this->line) - \strlen(\ltrim($this->line));
|
||||
$this->nextLine = isset($this->lines[$this->pointer + 1])
|
||||
? $this->lines[$this->pointer + 1]
|
||||
: '';
|
||||
$this->trimmedNextLine = \trim($this->nextLine);
|
||||
$this->nextIndent = \strlen($this->nextLine) - \strlen(\ltrim($this->nextLine));
|
||||
}
|
||||
|
||||
protected function reset($all = \false)
|
||||
{
|
||||
$except = $all ? [] : \array_flip(['lines', 'pointer', 'markup', 'indentStr', 'indentLen']);
|
||||
|
||||
// Reset all current values.
|
||||
foreach (\get_class_vars(__CLASS__) as $prop => $value) {
|
||||
isset($except[$prop]) || $this->{$prop} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
protected function flush()
|
||||
{
|
||||
if ('' !== $this->trimmedLine) {
|
||||
return \false;
|
||||
}
|
||||
|
||||
while (!empty($this->stackList)) {
|
||||
$this->markup .= \array_pop($this->stackList);
|
||||
}
|
||||
|
||||
while (!empty($this->stackBlock)) {
|
||||
$this->markup .= \array_pop($this->stackBlock);
|
||||
}
|
||||
|
||||
while (!empty($this->stackTable)) {
|
||||
$this->markup .= \array_pop($this->stackTable);
|
||||
}
|
||||
|
||||
$this->markup .= "\n";
|
||||
|
||||
$this->reset(\false);
|
||||
|
||||
return \true;
|
||||
}
|
||||
|
||||
protected function raw()
|
||||
{
|
||||
if ($this->inHtml || \preg_match(static::RE_RAW, $this->trimmedLine)) {
|
||||
$this->markup .= "\n$this->line";
|
||||
if (!$this->inHtml && empty($this->lines[$this->pointer - 1])) {
|
||||
$this->inHtml = \true;
|
||||
}
|
||||
|
||||
return \true;
|
||||
}
|
||||
}
|
||||
|
||||
protected function quote()
|
||||
{
|
||||
if (\preg_match(static::RE_MD_QUOTE, $this->line, $quoteMatch)) {
|
||||
$this->line = \substr($this->line, \strlen($quoteMatch[0]));
|
||||
$this->trimmedLine = \trim($this->line);
|
||||
|
||||
if (!$this->inQuote || $this->quoteLevel < \strlen($quoteMatch[1])) {
|
||||
$this->markup .= "\n<blockquote>";
|
||||
|
||||
$this->stackBlock[] = "\n</blockquote>";
|
||||
|
||||
$this->quoteLevel++;
|
||||
}
|
||||
|
||||
return $this->inQuote = \true;
|
||||
}
|
||||
}
|
||||
|
||||
protected function paragraph()
|
||||
{
|
||||
$this->markup .= $this->inPara ? "\n<br />" : "\n<p>";
|
||||
$this->markup .= $this->trimmedLine;
|
||||
|
||||
if (empty($this->trimmedNextLine)) {
|
||||
$this->markup .= '</p>';
|
||||
$this->inPara = \false;
|
||||
} else {
|
||||
$this->inPara = \true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2015, SegmentFault
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
* Neither the name of schillmania.com nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission from schillmania.com.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2018 Emanuil Rusev, erusev.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This is a stub include that automatically configures the include path.
|
||||
*/
|
||||
|
||||
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
|
||||
require_once 'HTMLPurifier/Bootstrap.php';
|
||||
require_once 'HTMLPurifier.autoload.php';
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user