* merge current 18.x into ai.
This commit is contained in:
@@ -33,3 +33,4 @@ CodeSniffer.conf
|
||||
test/runtime/*
|
||||
test/www
|
||||
!/**/.gitkeep
|
||||
build/*.gz
|
||||
|
||||
+886
-148
File diff suppressed because it is too large
Load Diff
Executable
+168
@@ -0,0 +1,168 @@
|
||||
pipeline {
|
||||
agent {
|
||||
kubernetes {
|
||||
inheritFrom "build-docker code-scan xuanim mysql-server"
|
||||
}
|
||||
}
|
||||
|
||||
environment {
|
||||
ZENTAO_VERSION = """${sh(
|
||||
returnStdout: true,
|
||||
script: 'cat VERSION'
|
||||
).trim()}"""
|
||||
MYSQL_SERVER_HOST = """${sh(
|
||||
returnStdout: true,
|
||||
script: 'hostname -I'
|
||||
).trim()}"""
|
||||
MYSQL_ROOT_PASSWORD = 'pass4ci'
|
||||
|
||||
MIDDLE_IMAGE_REPO = "hub.qc.oop.cc/zentao-ztf"
|
||||
MIDDLE_IMAGE_TAG = """${sh(
|
||||
returnStdout: true,
|
||||
script: 'echo $BUILD_ID-${GIT_COMMIT}'
|
||||
).trim()}"""
|
||||
}
|
||||
|
||||
stages {
|
||||
stage("checkout code") {
|
||||
steps {
|
||||
echo "checkout code success"
|
||||
}
|
||||
}
|
||||
|
||||
stage('Sonar Scanner') {
|
||||
parallel {
|
||||
stage('SonarQube') {
|
||||
steps {
|
||||
container('sonar') {
|
||||
withSonarQubeEnv('sonarqube') {
|
||||
sh 'git config --global --add safe.directory $(pwd)'
|
||||
sh 'sonar-scanner -Dsonar.inclusions=$(git diff --name-only HEAD~1|tr "\\n" ",") -Dsonar.analysis.user=$(git show -s --format=%an)'
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
container('xuanimbot') {
|
||||
sh 'git config --global --add safe.directory $(pwd)'
|
||||
sh '/usr/local/bin/xuanimbot --users "$(git show -s --format=%an)" --title "sonar scanner" --url "https://sonar.qc.oop.cc/dashboard?id=zentaopms&branch=${GIT_BRANCH}" --content "sonar scanner success" --debug --custom'
|
||||
}
|
||||
}
|
||||
failure {
|
||||
container('xuanimbot') {
|
||||
sh 'git config --global --add safe.directory $(pwd)'
|
||||
sh '/usr/local/bin/xuanimbot --users "$(git show -s --format=%an)" --title "sonar scanner" --url "https://sonar.qc.oop.cc/dashboard?id=zentaopms&branch=${GIT_BRANCH}" --content "sonar scanner failure" --debug --custom'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build Image') {
|
||||
steps {
|
||||
container('docker') {
|
||||
sh 'docker build --pull . -f Dockerfile.test --build-arg VERSION=${ZENTAO_VERSION} --build-arg MIRROR=true --build-arg MYSQL_HOST=${MYSQL_SERVER_HOST} --build-arg MYSQL_PASSWORD=${MYSQL_ROOT_PASSWORD} -t ${MIDDLE_IMAGE_REPO}:${MIDDLE_IMAGE_TAG}'
|
||||
sh 'docker push ${MIDDLE_IMAGE_REPO}:${MIDDLE_IMAGE_TAG}'
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
echo 'build image success'
|
||||
}
|
||||
failure {
|
||||
container('xuanimbot') {
|
||||
sh 'git config --global --add safe.directory $(pwd)'
|
||||
sh '/usr/local/bin/xuanimbot --users "$(git show -s --format=%an)" --title "build image" --url "${RUN_DISPLAY_URL}" --content "Build unit test image failure" --debug --custom'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Unit Test'){
|
||||
stages{
|
||||
stage('Init') {
|
||||
agent {
|
||||
kubernetes {
|
||||
inheritFrom "xuanim"
|
||||
containerTemplate {
|
||||
name "zentao"
|
||||
image "${MIDDLE_IMAGE_REPO}:${MIDDLE_IMAGE_TAG}"
|
||||
command "sleep"
|
||||
args "99d"
|
||||
}
|
||||
}
|
||||
}
|
||||
options { skipDefaultCheckout() }
|
||||
|
||||
steps {
|
||||
container('zentao') {
|
||||
sh 'initdb.php ; /apps/zentao/test/ztest init'
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
sh 'echo "stage unit init success"'
|
||||
}
|
||||
failure {
|
||||
container('xuanimbot') {
|
||||
sh 'git config --global --add safe.directory $(pwd)'
|
||||
sh '/usr/local/bin/xuanimbot --users "$(git show -s --format=%an)" --title "unittest init" --url "${RUN_DISPLAY_URL}" --content "Unit test database initialization failed" --debug --custom'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Run') {
|
||||
matrix {
|
||||
agent {
|
||||
kubernetes {
|
||||
inheritFrom "xuanim"
|
||||
containerTemplate {
|
||||
name "zentao"
|
||||
image "${MIDDLE_IMAGE_REPO}:${MIDDLE_IMAGE_TAG}"
|
||||
command "sleep"
|
||||
args "99d"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
options { skipDefaultCheckout() }
|
||||
|
||||
axes {
|
||||
axis {
|
||||
name "SEQUENCE"
|
||||
values "P1", "P2", "P3", "P4", "P5", "P6", "P7"
|
||||
}
|
||||
}
|
||||
stages {
|
||||
stage("Run") {
|
||||
steps {
|
||||
container('zentao') {
|
||||
sh 'initdb.php config'
|
||||
sh '/apps/zentao/test/ztest extract ; /apps/zentao/test/ztest ${SEQUENCE} | tee /apps/zentao/test/${SEQUENCE}.log'
|
||||
sh 'pipeline-unittest.sh /apps/zentao/test/${SEQUENCE}.log'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post{
|
||||
success{
|
||||
container('xuanimbot') {
|
||||
sh 'git config --global --add safe.directory /home/jenkins/agent/workspace/pangu_pangu_xuanimbot_master'
|
||||
sh '/usr/local/bin/xuanimbot --users "$(git show -s --format=%an)" --title "unittest" --url "${RUN_DISPLAY_URL}" --content "Unit test passed" --debug --custom'
|
||||
}
|
||||
}
|
||||
failure{
|
||||
container('xuanimbot') {
|
||||
sh 'git config --global --add safe.directory $(pwd)'
|
||||
sh '/usr/local/bin/xuanimbot --users "$(git show -s --format=%an)" --title "unittest" --url "${RUN_DISPLAY_URL}" --content "Unit test failed" --debug --custom'
|
||||
}
|
||||
}
|
||||
}
|
||||
}//End unittest
|
||||
}
|
||||
}
|
||||
} // End Root Stages
|
||||
} // End pipeline
|
||||
@@ -1,6 +1,6 @@
|
||||
VERSION = $(shell head -n 1 VERSION)
|
||||
XUANVERSION = $(shell head -n 1 xuanxuan/XUANVERSION)
|
||||
XVERSION = $(shell head -n 1 xuanxuan/XVERSION)
|
||||
XUANVERSION = $(shell jq -r .pkg.xuanxuan.gitVersion < ci.json)
|
||||
XVERSION = $(shell jq -r .pkg.xuanxuan.version < ci.json)
|
||||
XHPROF_VERSION = 2.3.9
|
||||
|
||||
XUANPATH := $(XUANXUAN_SRC_PATH)
|
||||
@@ -8,6 +8,9 @@ BUILD_PATH := $(if $(ZENTAO_BUILD_PATH),$(ZENTAO_BUILD_PATH),$(shell pwd))
|
||||
RELEASE_PATH := $(if $(ZENTAO_RELEASE_PATH),$(ZENTAO_RELEASE_PATH),$(shell pwd))
|
||||
XUAN_WEB_PATH := $(ZENTAO_BUILD_PATH)/web
|
||||
|
||||
DOWNGRADE_ENABLED := $(or $(DOWNGRADE_ENABLED),$(shell jq -r .downgrade.enabled < ci.json))
|
||||
DOWNGRADE_VERSIONS := $(or $(DOWNGRADE_VERSIONS),$(shell jq -r .downgrade.versions < ci.json))
|
||||
|
||||
all:
|
||||
make clean
|
||||
make ci
|
||||
@@ -68,9 +71,9 @@ zentaoxx:
|
||||
mkdir -p zentaoxx/db
|
||||
mkdir -p zentaoxx/www
|
||||
mkdir -p zentaoxx/extension/xuan/common/ext/model/
|
||||
cd $(XUANPATH); git pull; git archive --format=zip --prefix=xuan/ $(XUANVERSION) > xuan.zip
|
||||
cd $(XUANPATH); git archive --format=zip --prefix=xuan/ $(XUANVERSION) > xuan.zip
|
||||
mv $(XUANPATH)/xuan.zip .
|
||||
unzip xuan.zip
|
||||
unzip -q xuan.zip
|
||||
cp xuan/xxb/config/ext/_0_xuanxuan.php zentaoxx/config/ext/
|
||||
cp -r xuan/xxb/lib/phpaes zentaoxx/lib/
|
||||
cp -r xuan/xxb/framework/xuanxuan.class.php zentaoxx/framework/
|
||||
@@ -98,6 +101,8 @@ zentaoxx:
|
||||
cp -r $(XUAN_WEB_PATH) zentaoxx/www/data/xuanxuan/
|
||||
mv zentaoxx/db/ zentaoxx/db_bak
|
||||
mkdir zentaoxx/db/
|
||||
sed -i "s/datetime NOT NULL DEFAULT '0000-00-00 00:00:00'/datetime NULL/" zentaoxx/db_bak/*.sql
|
||||
sed -i "/`xxb_user` ADD `clientStatus`/d; /`xxb_user` ADD `clientLang`/d; /`xxb_file` CHANGE `pathname`/d" zentaoxx/db_bak/xuanxuan.sql
|
||||
cp zentaoxx/db_bak/upgradexuanxuan*.sql zentaoxx/db_bak/xuanxuan.sql zentaoxx/db/
|
||||
rm -rf zentaoxx/db_bak/
|
||||
sed -i "s/\$$accountAdmin = \$$this->dao->select('account, admin')->from(TABLE_USER)->where('id')->eq(\$$userID)->fetch();/\$$accountAdmin = \$$this->dao->select('account')->from(TABLE_USER)->where('id')->eq(\$$userID)->fetch();\n\$$sysAdmins = \$$this->dao->select('admins')->from(TABLE_COMPANY)->where('id')->eq(\$$this->app->company->id)->fetch('admins');\n\$$sysAdminArray = explode(',', \$$sysAdmins);\n\$$accountAdmin->admin = in_array(\$$accountAdmin->account, \$$sysAdminArray) ? 'super' : '';\n/" zentaoxx/extension/xuan/im/model/chat.php
|
||||
@@ -132,6 +137,7 @@ zentaoxx:
|
||||
sed -i '/xxb_entry/d' zentaoxx/db/*.sql
|
||||
sed -i '/deviceToken/d' zentaoxx/db/*.sql
|
||||
sed -i '/deviceType/d' zentaoxx/db/*.sql
|
||||
sed -i 's/xxb_/zt_/g' zentaoxx/db/*.sql
|
||||
sed -i "/fetch('push', 'pushMessage');/d" zentaoxx/extension/xuan/im/control.php
|
||||
#sed -i "s/marked\.html\.php';?>/marked\.html\.php';?>\n<div id='mainMenu' class='clearfix'><div class='btn-toolbar pull-left'><?php common::printAdminSubMenu('xuanxuan');?><\/div><\/div>/g" zentaoxx/extension/xuan/client/view/checkupgrade.html.php
|
||||
sed -i '/var serverVersions/d' zentaoxx/extension/xuan/client/js/checkupgrade.js
|
||||
@@ -146,7 +152,7 @@ zentaoxx:
|
||||
sed -i 's/v\.//g' zentaoxx/extension/xuan/client/js/checkupgrade.js
|
||||
sed -i 's/commonModel::getLicensePropertyValue/extCommonModel::getLicensePropertyValue/g' zentaoxx/extension/xuan/im/control.php
|
||||
sed -i 's/commonModel::getLicensePropertyValue/extCommonModel::getLicensePropertyValue/g' zentaoxx/extension/xuan/im/model/conference.php
|
||||
sed -i 's/xxb_/zt_/g' zentaoxx/db/*.sql
|
||||
sed -i 's/commonModel::isLicensedMethod([^\)]*)/false/g' zentaoxx/extension/xuan/conference/model.php
|
||||
sed -i "s#\$this->app->getModuleRoot() . 'im/apischeme.json'#\$this->app->getExtensionRoot() . 'xuan/im/apischeme.json'#g" zentaoxx/extension/xuan/im/model.php
|
||||
sed -i "s/'..\/..\/common\/view\/header.html.php'/\$$app->getModuleRoot() . 'common\/view\/header.html.php'/g" zentaoxx/extension/xuan/conference/view/admin.html.php
|
||||
sed -i "s/'..\/..\/common\/view\/footer.html.php'/\$$app->getModuleRoot() . 'common\/view\/footer.html.php'/g" zentaoxx/extension/xuan/conference/view/admin.html.php
|
||||
@@ -154,7 +160,7 @@ zentaoxx:
|
||||
sed -i "/.*->getAllDepts();/d" zentaoxx/extension/xuan/im/ext/bot/default.bot.php
|
||||
sed -i "s/lang->user->status/lang->user->clientStatus/" zentaoxx/extension/xuan/im/ext/bot/default.bot.php
|
||||
sed -i "s/.*->getRoleList();/\$$depts = \$$this->im->loadModel('dept')->getDeptPairs();\n\$$deptList = array_map(function(\$$k, \$$v) {return (object)array('id' => \$$k, 'name' => \$$v);}, array_keys(\$$depts), \$$depts);\n\$$roleList = \$$this->im->lang->user->roleList;/" zentaoxx/extension/xuan/im/ext/bot/default.bot.php
|
||||
echo "ALTER TABLE \`zt_user\` ADD \`pinyin\` varchar(255) NOT NULL DEFAULT '' AFTER \`realname\`;" >> zentaoxx/db/xuanxuan.sql
|
||||
find zentaoxx/extension/xuan/ -name '*.php' -exec sed -i -r 's|->ne(["'\'']0000-00-00 00:00:00["'\''])|->notZeroDatetime()|g; s|["'\'']\)->eq\(["'\'']0000-00-00( 00:00:00)?| is null|g; s|([=!]=) ?["'\'']0000-00-00( 00:00:00)?["'\'']|\1 null|g; s|([^!=]=) ?["'\'']0000-00-00( 00:00:00)?["'\'']|\1 null|g; s|(["'\''])(,.*)\)->eq\(["'\'']0000-00-00( 00:00:00)?["'\'']| is null\1\2|g; s|["'\'']0000-00-00 00:00:00["'\'']|null|g' {} +
|
||||
mkdir zentaoxx/tools; cp tools/cn2tw.php zentaoxx/tools; cd zentaoxx/tools; php cn2tw.php
|
||||
cp tools/en2other.php zentaoxx/tools; cd zentaoxx/tools; php en2other.php ../
|
||||
rm -rf zentaoxx/tools
|
||||
@@ -254,9 +260,9 @@ enrpm:
|
||||
rpmbuild -ba ~/rpmbuild/SPECS/zentaopms.spec
|
||||
cp ~/rpmbuild/RPMS/noarch/zentaoalm-${VERSION}-1.noarch.rpm ./
|
||||
rm -rf ~/rpmbuild
|
||||
cleanAssets:
|
||||
find zentaopms/ -type f \( -name "*.js.map" -o -name "*.gz" \) -delete
|
||||
ciCommon:
|
||||
make clean
|
||||
git pull
|
||||
make common
|
||||
|
||||
ifneq ($(XUANPATH), )
|
||||
@@ -266,14 +272,20 @@ ciCommon:
|
||||
endif
|
||||
|
||||
make package
|
||||
make cleanAssets
|
||||
zip -rq -9 ZenTaoPMS.$(VERSION).zip zentaopms
|
||||
# en
|
||||
cd zentaopms/; grep -rl 'zentao.net'|xargs sed -i 's/zentao.net/zentao.pm/g';
|
||||
cd zentaopms/; grep -rl 'http://www.zentao.pm'|xargs sed -i 's/http:\/\/www.zentao.pm/https:\/\/www.zentao.pm/g';
|
||||
cd zentaopms/config/; echo >> config.php; echo '$$config->isINT = true;' >> config.php
|
||||
mv zentaopms zentaoalm
|
||||
zip -r -9 ZenTaoALM.$(VERSION).int.zip zentaoalm
|
||||
rm -fr zentaoalm
|
||||
cp -a zentaopms zentaoalm
|
||||
cd zentaoalm/; grep -rl 'zentao.net'|xargs sed -i 's/zentao.net/zentao.pm/g';
|
||||
cd zentaoalm/; grep -rl 'http://www.zentao.pm'|xargs sed -i 's/http:\/\/www.zentao.pm/https:\/\/www.zentao.pm/g';
|
||||
cd zentaoalm/config/; echo >> config.php; echo '$$config->isINT = true;' >> config.php
|
||||
zip -rq -9 ZenTaoALM.$(VERSION).int.zip zentaoalm
|
||||
|
||||
# downgrade
|
||||
@test "$(DOWNGRADE_ENABLED)" != "true" && echo "skip downgrade" || ./misc/downgrade.sh -p "$(DOWNGRADE_VERSIONS)" -i -r zentaopms -o "$(RELEASE_PATH)" framework/ module/*
|
||||
|
||||
rm -fr zentaopms zentaoalm
|
||||
|
||||
# move pms zip to build and release path.
|
||||
rm -f $(BUILD_PATH)/ZenTao*.zip $(RELEASE_PATH)/ZenTaoPMS.$(VERSION).zip $(RELEASE_PATH)/ZenTaoALM.$(VERSION).int.zip
|
||||
cp ZenTaoPMS.$(VERSION).zip $(BUILD_PATH)
|
||||
|
||||
@@ -92,6 +92,6 @@ class bugsEntry extends entry
|
||||
|
||||
$bug = $this->loadModel('bug')->getByID($data->id);
|
||||
|
||||
return $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'));
|
||||
return $this->send(201, $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'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ class buildsEntry extends entry
|
||||
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), $this->param('order', 't1.date_desc,t1.id_desc'));
|
||||
$control = $this->loadController('projectbuild', 'browse');
|
||||
$control->browse($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');
|
||||
@@ -51,7 +51,9 @@ class buildsEntry extends entry
|
||||
if(!$projectID) $projectID = $this->param('project', 0);
|
||||
|
||||
$project = $this->loadModel('project')->getByID($projectID);
|
||||
if(!$project) return $this->send404();
|
||||
if(!$project) return $this->sendError(404, 'Error project id');
|
||||
|
||||
$this->setPost('project', $projectID);
|
||||
|
||||
$fields = 'execution,product,name,builder,date,scmPath,filePath,desc,branch';
|
||||
$this->batchSetPost($fields);
|
||||
@@ -59,7 +61,8 @@ class buildsEntry extends entry
|
||||
$control = $this->loadController('build', 'create');
|
||||
$this->requireFields('execution,product,name,builder,date');
|
||||
|
||||
$control->create(0, 0, $projectID);
|
||||
$executionID = isset($_POST['execution']) ? $_POST['execution'] : 0;
|
||||
$control->create($executionID, 0, $projectID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
@@ -119,8 +119,10 @@ class executionEntry extends entry
|
||||
{
|
||||
$oldExecution = $this->loadModel('execution')->getByID($executionID);
|
||||
|
||||
$useCode = $this->checkCodeUsed();
|
||||
/* Set $_POST variables. */
|
||||
$fields = 'project,code,name,begin,end,lifetime,desc,days,acl,status,PO,PM,QD,RD';
|
||||
$fields = 'project,name,begin,end,lifetime,desc,days,acl,status,PO,PM,QD,RD';
|
||||
if($useCode) $fields .= 'code';
|
||||
$this->batchSetPost($fields, $oldExecution);
|
||||
|
||||
$this->setPost('whitelist', $this->request('whitelist', explode(',', $oldExecution->whitelist)));
|
||||
|
||||
@@ -55,8 +55,6 @@ class executionsEntry extends entry
|
||||
$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,children,' . $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');
|
||||
}
|
||||
@@ -80,7 +78,10 @@ class executionsEntry extends entry
|
||||
*/
|
||||
public function post($projectID = 0)
|
||||
{
|
||||
$fields = 'project,code,name,begin,end,lifetime,desc,days,percent,parent';
|
||||
$useCode = $this->checkCodeUsed();
|
||||
|
||||
$fields = 'project,name,begin,end,lifetime,desc,days,percent,parent';
|
||||
if($useCode) $fields .= 'code';
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
$projectID = $this->param('project', $projectID);
|
||||
@@ -94,7 +95,12 @@ class executionsEntry extends entry
|
||||
$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 = $this->loadController('execution', 'create');
|
||||
|
||||
$requireFields = 'name,begin,end';
|
||||
if($useCode) $requireFields .= ',code';
|
||||
$this->requireFields($requireFields);
|
||||
|
||||
$control->create($projectID);
|
||||
|
||||
$data = $this->getData();
|
||||
@@ -122,7 +128,7 @@ class executionsEntry extends entry
|
||||
$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($data->data->projectExecutions as $projectID => $projectExecutions)
|
||||
{
|
||||
foreach($projectExecutions as $execution)
|
||||
{
|
||||
|
||||
@@ -28,10 +28,8 @@ class feedbackEntry extends entry
|
||||
$feedback = $data->data->feedback;
|
||||
|
||||
$feedback->publicStatus = $feedback->public;
|
||||
$feedback->productName = $data->data->product;
|
||||
$feedback->productName = is_object($data->data->product) ? $data->data->product->name : $data->data->product;
|
||||
$feedback->moduleName = isset($data->data->modulePath[0]->name) ? $data->data->modulePath[0]->name : '/';
|
||||
$feedback->resultType = $data->data->type;
|
||||
if(isset($feedback->resultInfo) and $feedback->resultInfo->deleted == 0) $feedback->resultStatus = $this->loadModel('feedback')->processStatus($feedback->resultType, $feedback->resultInfo);
|
||||
|
||||
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);
|
||||
|
||||
@@ -21,6 +21,7 @@ class feedbacksEntry extends entry
|
||||
{
|
||||
if(strpos(strtolower($this->param('fields')), 'moduleandproduct') !== false) return $this->getModuleAndProduct();
|
||||
|
||||
$this->app->session->set('feedbackProduct', 'all');
|
||||
$control = $this->loadController('feedback', 'admin');
|
||||
$control->admin($this->param('status', 'unclosed'), 0, $this->param('orderBy', 'id_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
|
||||
@@ -30,6 +30,8 @@ class langsEntry extends entry
|
||||
|
||||
global $filter;
|
||||
$rule = $filter->default->moduleName;
|
||||
|
||||
if($modules == 'all') $modules = 'upgrade,task,block,testtask,execution,story,project,cron,todo,productplan,release,product,doc,file,customer,action,design,bug,mr,webhook,error,effort,report,programplan,my,search,feedback,score,user,api,program,stakeholder,branch,testcase,meeting,searchObjects,index,dev,personnel,workfloweditor,devops,oa';
|
||||
$modules = explode(',', $modules);
|
||||
foreach($modules as $module)
|
||||
{
|
||||
|
||||
@@ -107,10 +107,12 @@ class productEntry extends entry
|
||||
*/
|
||||
public function put($productID)
|
||||
{
|
||||
$useCode = $this->checkCodeUsed();
|
||||
$oldProduct = $this->loadModel('product')->getByID($productID);
|
||||
|
||||
/* Set $_POST variables. */
|
||||
$fields = 'program,line,name,PO,QD,RD,type,desc,whitelist,status,acl';
|
||||
if($useCode) $fields .= ',code';
|
||||
$this->batchSetPost($fields, $oldProduct);
|
||||
|
||||
$control = $this->loadController('product', 'edit');
|
||||
|
||||
@@ -85,7 +85,7 @@ class productplansEntry extends entry
|
||||
$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'));
|
||||
return $this->send(201, $this->format($plan, 'begin:date,end:date,deleted:bool,project:int'));
|
||||
}
|
||||
|
||||
$this->sendError(400, array('message' => isset($data->message) ? $data->message : 'error'));
|
||||
|
||||
@@ -112,14 +112,20 @@ class productsEntry extends entry
|
||||
*/
|
||||
public function post()
|
||||
{
|
||||
$fields = 'program,code,line,name,PO,QD,RD,type,desc,whitelist';
|
||||
$useCode = $this->checkCodeUsed();
|
||||
|
||||
$fields = 'program,line,name,PO,QD,RD,type,desc,whitelist';
|
||||
if($useCode) $fields .= ',code';
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
$this->setPost('acl', $this->request('acl', 'private'));
|
||||
$this->setPost('whitelist', $this->request('whitelist', array()));
|
||||
|
||||
$control = $this->loadController('product', 'create');
|
||||
$this->requireFields('name,code');
|
||||
|
||||
$requireFields = 'name';
|
||||
if($useCode) $requireFields .= ',code';
|
||||
$this->requireFields($requireFields);
|
||||
|
||||
$control->create($this->request('program', 0));
|
||||
|
||||
@@ -130,7 +136,7 @@ class productsEntry extends entry
|
||||
$product = $this->loadModel('product')->getByID($data->id);
|
||||
$product = $this->format($product, 'createdDate:time,whitelist:userList,createdBy:user,PO:user,RD:user,QD:user');
|
||||
|
||||
return $this->send(200, $product);
|
||||
return $this->send(201, $product);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,7 +45,9 @@ class programEntry extends entry
|
||||
$control = $this->loadController('program', 'edit');
|
||||
$control->edit($programID);
|
||||
|
||||
$this->getData();
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$program = $this->program->getByID($programID);
|
||||
return $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'));
|
||||
}
|
||||
|
||||
@@ -28,19 +28,16 @@ class programsEntry extends entry
|
||||
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'));
|
||||
$program->browse($this->param('status', 'all'), $this->param('order', 'order_asc'), 0, 10000, 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(zget($data, 'code', 400), $data->message);
|
||||
|
||||
$programs = $data->data->programs;
|
||||
$progressList = $data->data->progressList;
|
||||
$users = $data->data->users;
|
||||
$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)
|
||||
|
||||
@@ -101,8 +101,10 @@ class projectEntry extends entry
|
||||
$oldProject = $this->loadModel('project')->getByID($projectID);
|
||||
$linkedProducts = $this->loadModel('product')->getProducts($projectID);
|
||||
|
||||
$useCode = $this->checkCodeUsed();
|
||||
/* Set $_POST variables. */
|
||||
$fields = 'name,code,begin,end,acl,parent,desc,PM,whitelist,model';
|
||||
$fields = 'name,begin,end,acl,parent,desc,PM,whitelist,model';
|
||||
if($useCode) $fields .= ',code';
|
||||
$this->batchSetPost($fields, $oldProject);
|
||||
|
||||
$products = array();
|
||||
@@ -119,7 +121,7 @@ class projectEntry extends entry
|
||||
$control->edit($projectID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
if(!isset($data->result)) return $this->sendError(400, 'error');
|
||||
|
||||
$project = $this->project->getByID($projectID);
|
||||
|
||||
@@ -35,9 +35,10 @@ class projectReleasesEntry extends entry
|
||||
{
|
||||
$result = array();
|
||||
$releases = $data->data->releases;
|
||||
$pager = $data->data->pager;
|
||||
foreach($releases as $release) $result[] = $this->format($release, 'deleted:bool,date:date,mailto:userList');
|
||||
|
||||
return $this->send(200, array('total' => count($result), 'releases' => $result));
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'releases' => $result));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
@@ -48,8 +48,6 @@ class projectsEntry extends entry
|
||||
$result = array();
|
||||
foreach($data->data->projectStats as $project)
|
||||
{
|
||||
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');
|
||||
}
|
||||
|
||||
@@ -79,8 +77,11 @@ class projectsEntry extends entry
|
||||
{
|
||||
$fields = 'name,begin,end,products';
|
||||
$this->batchSetPost($fields);
|
||||
if(isset($_POST['products'])) $_POST['hasProduct'] = true;
|
||||
|
||||
$this->setPost('code', $this->request('code', ''));
|
||||
$useCode = $this->checkCodeUsed();
|
||||
|
||||
if($useCode) $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()));
|
||||
@@ -89,7 +90,10 @@ class projectsEntry extends entry
|
||||
$this->setPost('parent', $this->request('parent', 0));
|
||||
|
||||
$control = $this->loadController('project', 'create');
|
||||
$this->requireFields('name,code,begin,end,products');
|
||||
|
||||
$requireFields = 'name,begin,end,products';
|
||||
if($useCode) $requireFields .= ',code';
|
||||
$this->requireFields($requireFields);
|
||||
|
||||
$control->create($this->request('model', 'scrum'));
|
||||
|
||||
|
||||
@@ -32,9 +32,10 @@ class releasesEntry extends entry
|
||||
{
|
||||
$result = array();
|
||||
$releases = $data->data->releases;
|
||||
$pager = $data->data->pager;
|
||||
foreach($releases as $release) $result[] = $this->format($release, 'deleted:bool,date:date,mailto:userList');
|
||||
|
||||
return $this->send(200, array('total' => count($result), 'releases' => $result));
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'releases' => $result));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
|
||||
@@ -162,7 +162,7 @@ class reportsEntry extends entry
|
||||
$newProject->id = $project->id;
|
||||
$newProject->name = $project->name;
|
||||
$newProject->status = $project->status;
|
||||
$newProject->progress = round($project->hours->progress, 1);
|
||||
$newProject->progress = isset($project->progress) ? $project->progress : round($project->hours->progress, 1);
|
||||
$newProject->totalConsumed = round($project->hours->totalConsumed, 1);
|
||||
$newProject->totalLeft = round($project->hours->totalLeft, 1);
|
||||
if(isset($project->delay)) $newProject->delay = $project->delay;
|
||||
@@ -206,7 +206,7 @@ class reportsEntry extends entry
|
||||
$newExecution->id = $execution->id;
|
||||
$newExecution->name = $execution->name;
|
||||
$newExecution->status = $execution->status;
|
||||
$newExecution->progress = round($execution->hours->progress, 1);
|
||||
$newExecution->progress = isset($execution->progress) ? $execution->progress : round($execution->hours->progress, 1);
|
||||
$newExecution->totalConsumed = round($execution->hours->totalConsumed, 1);
|
||||
$newExecution->totalLeft = round($execution->hours->totalLeft, 1);
|
||||
if(isset($execution->delay)) $newExecution->delay = $execution->delay;
|
||||
|
||||
@@ -92,6 +92,6 @@ class storiesEntry extends entry
|
||||
if(isset($data->result) and !isset($data->id)) return $this->sendError(400, $data->message);
|
||||
|
||||
$story = $this->loadModel('story')->getByID($data->id);
|
||||
return $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'));
|
||||
return $this->send(201, $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'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,8 +104,8 @@ class storyEntry extends entry
|
||||
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
if(!isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
if(!isset($data->result)) return $this->sendError(400, 'error');
|
||||
|
||||
$story = $this->story->getByID($storyID);
|
||||
return $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'));
|
||||
|
||||
@@ -28,17 +28,18 @@ class taskFinishEntry extends entry
|
||||
$fields = 'finishedDate,comment';
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
$realStarted = $this->request('realStarted', (isset($task->realStarted) and !helper::isZeroDate($task->realStarted)) ? $task->realStarted : '');
|
||||
if($realStarted) $this->setPost('realStarted', $realStarted);
|
||||
$this->setPost('currentConsumed', $this->request('currentConsumed', 0));
|
||||
$this->setPost('consumed', $this->request('currentConsumed', 0) + $task->consumed);
|
||||
|
||||
$control = $this->loadController('task', 'finish');
|
||||
$this->requireFields('assignedTo,currentConsumed,realStarted,finishedDate');
|
||||
$this->requireFields('currentConsumed,realStarted,finishedDate');
|
||||
$control->finish($taskID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$task = $this->loadModel('task')->getByID($taskID);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class taskPauseEntry extends entry
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$task = $this->loadModel('task')->getByID($taskID);
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class taskRecordEstimateEntry extends entry
|
||||
{
|
||||
if($this->loadModel('effort'))
|
||||
{
|
||||
$fields = 'id,dates,consumed,left,objectType,objectID,work';
|
||||
$fields = 'id,dates,consumed,left,objectType,objectID,work,date';
|
||||
$this->batchSetPost($fields);
|
||||
$control = $this->loadController('effort', 'createForObject');
|
||||
$control->createForObject('task', $taskID);
|
||||
|
||||
@@ -34,7 +34,7 @@ class taskRestartEntry extends entry
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data) return $this->send400('error');
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$task = $this->loadModel('task')->getByID($taskID);
|
||||
|
||||
|
||||
@@ -104,8 +104,9 @@ class tasksEntry extends entry
|
||||
$fields = 'name,type,assignedTo,estimate,story,execution,project,module,pri,desc,estStarted,deadline,mailto,team,teamEstimate,multiple,uid';
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
$assignedTo = $this->request('assignedTo');
|
||||
if($assignedTo and !is_array($assignedTo)) $this->setPost('assignedTo', array($assignedTo));
|
||||
$assignedTo = $this->request('assignedTo', array(0 => ''));
|
||||
if($assignedTo and !is_array($assignedTo)) $assignedTo = array($assignedTo);
|
||||
$this->setPost('assignedTo', $assignedTo);
|
||||
if($this->request('multiple'))
|
||||
{
|
||||
if(count($this->request('team')) != count($this->request('teamEstimate'))) return $this->sendError(400, 'Arrays team and teamEstimate should be the same length');
|
||||
|
||||
@@ -22,17 +22,17 @@ class taskStartEntry extends entry
|
||||
{
|
||||
$task = $this->loadModel('task')->getByID($taskID);
|
||||
|
||||
$fields = 'assignedTo,realStarted,consumed,left,comment';
|
||||
$fields = 'assignedTo,consumed,left,comment';
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
$this->setPost('realStarted', $this->request('realStarted', helper::now()));
|
||||
|
||||
$control = $this->loadController('task', 'start');
|
||||
$this->requireFields('left');
|
||||
$control->start($taskID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data) return $this->send400('error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$task = $this->loadModel('task')->getByID($taskID);
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ class userEntry extends entry
|
||||
{
|
||||
$myExecutions['owner'] = array();
|
||||
$myExecutions['other'] = array();
|
||||
foreach($data->data->executions as $projectID => $projectExecutions)
|
||||
foreach($data->data->projectExecutions as $projectID => $projectExecutions)
|
||||
{
|
||||
foreach($projectExecutions as $execution)
|
||||
{
|
||||
@@ -298,7 +298,7 @@ class userEntry extends entry
|
||||
$info->issue = array('total' => 0, 'issues' => array());
|
||||
if(!common::hasPriv('my', 'work')) break;
|
||||
|
||||
if($this->config->edition == 'max')
|
||||
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
|
||||
{
|
||||
global $app;
|
||||
$app->rawMethod = 'work';
|
||||
@@ -318,7 +318,7 @@ class userEntry extends entry
|
||||
$info->risk = array('total' => 0, 'risks' => array());
|
||||
if(!common::hasPriv('my', 'work')) break;
|
||||
|
||||
if($this->config->edition == 'max')
|
||||
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
|
||||
{
|
||||
global $app;
|
||||
$app->rawMethod = 'work';
|
||||
@@ -338,7 +338,7 @@ class userEntry extends entry
|
||||
$info->meeting = array('total' => 0, 'meetings' => array());
|
||||
if(!common::hasPriv('my', 'work')) break;
|
||||
|
||||
if($this->config->edition == 'max')
|
||||
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
|
||||
{
|
||||
global $app;
|
||||
$app->rawMethod = 'work';
|
||||
|
||||
@@ -64,6 +64,24 @@ class ztfSubmitEntry extends baseEntry
|
||||
->set('ZTFResult')->eq(json_encode($post))
|
||||
->where('id')->eq($post->task)
|
||||
->exec();
|
||||
|
||||
$result = $this->dao->select('*')->from(TABLE_TESTRESULT)
|
||||
->where('id')->eq($post->task)
|
||||
->fetch();
|
||||
|
||||
if($result->run)
|
||||
{
|
||||
$runStatus = $result->caseResult == 'blocked' ? 'blocked' : 'normal';
|
||||
$this->dao->update(TABLE_TESTRUN)
|
||||
->set('lastRunResult')->eq($result->caseResult)
|
||||
->set('status')->eq($runStatus)
|
||||
->set('lastRunner')->eq($result->lastRunner)
|
||||
->set('lastRunDate')->eq($result->date)
|
||||
->where('id')->eq($result->run)
|
||||
->exec();
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_CASE)->set('lastRunner')->eq($result->lastRunner)->set('lastRunDate')->eq($result->date)->set('lastRunResult')->eq($result->caseResult)->where('id')->eq($result->case)->exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
<?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';
|
||||
|
||||
$app = router::createApp('pms', dirname(dirname(dirname(__FILE__))), 'router');
|
||||
$cacheConfig = $app->config->cache;
|
||||
if(!$cacheConfig->enable && !$cacheConfig->enableFullPage)
|
||||
{
|
||||
echo 'Cache is disabled.', PHP_EOL;
|
||||
exit;
|
||||
}
|
||||
|
||||
function traverseDirectory($directory, &$cleanNum)
|
||||
{
|
||||
$files = glob($directory . DS . '*.cache');
|
||||
|
||||
foreach($files as $file)
|
||||
{
|
||||
$result = viewFileContent($file);
|
||||
if(!$result) $cleanNum ++;
|
||||
}
|
||||
|
||||
$subdirectories = glob($directory . DS . '*', GLOB_ONLYDIR);
|
||||
|
||||
foreach($subdirectories as $subdirectory) traverseDirectory($subdirectory, $cleanNum);
|
||||
}
|
||||
|
||||
function isExpired($payload)
|
||||
{
|
||||
if(is_null($payload['time'])) return false;
|
||||
|
||||
return time() > $payload['time'];
|
||||
}
|
||||
|
||||
function viewFileContent($file)
|
||||
{
|
||||
$content = file_get_contents($file);
|
||||
$content = unserialize($content);
|
||||
if(isExpired($content))
|
||||
{
|
||||
unlink($file);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
$cleanNum = 0;
|
||||
traverseDirectory(rtrim($app->getCacheRoot(), DS), $cleanNum);
|
||||
|
||||
echo "Cleaned {$cleanNum} cache files.", PHP_EOL;
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"pkg": {
|
||||
"xuanxuan": {
|
||||
"gitVersion": "e08cd0387cbfcf4cbc28b3b3e829683066ee3bc7",
|
||||
"version": "7.2.1"
|
||||
},
|
||||
"zentaoext": {
|
||||
"gitVersion": "18.x",
|
||||
"gitRepo": "https://git.zcorp.cc/easycorp/zentaoext.git"
|
||||
},
|
||||
"zdoo": {
|
||||
"gitVersion": "master"
|
||||
},
|
||||
"zdooext": {
|
||||
"gitVersion": "master"
|
||||
}
|
||||
},
|
||||
"downgrade": {
|
||||
"enabled": false,
|
||||
"versions": "7.2,7.1,7.0,5.4"
|
||||
},
|
||||
"upload": {
|
||||
"bucket": "download"
|
||||
},
|
||||
"notice": {
|
||||
"users": "qishiyao,hufangzhou",
|
||||
"groups": "84be4c6e-02e3-4fdc-b081-318c0c1eca02,31a0008b-6e3e-4b7f-9b7b-396a46b1f8f4"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/* 缓存设置。Cache settings. */
|
||||
$config->cache = new stdclass();
|
||||
$config->cache->enable = false; // 是否开启缓存。Enable cache or not.
|
||||
$config->cache->lifetime = 5 * 60; // 缓存生存时间。The lifetime of cache.
|
||||
$config->cache->driver = 'File'; // 缓存驱动。 The driver of cache. can be File|Yac|Apcu.
|
||||
|
||||
$config->cache->enableFullPage = false; // 是否开启整页缓存。Enable full page cache or not.
|
||||
$config->cache->fullPageLifetime = 5 * 60;
|
||||
$config->cache->fullPageDriver = 'File';
|
||||
|
||||
$config->cache->fullPages = array(); // 需要整页缓存的页面,格式为:模块名|方法名。模块和方法名都是小写。The pages need to be cached, format: module|method. Both module and method are lowercase.
|
||||
$config->cache->fullPages[] = 'program|browse';
|
||||
$config->cache->fullPages[] = 'product|all';
|
||||
$config->cache->fullPages[] = 'project|browse';
|
||||
$config->cache->fullPages[] = 'block|printblock';
|
||||
$config->cache->fullPages[] = 'screen|view';
|
||||
|
||||
$config->cacheKeys = new stdclass();
|
||||
|
||||
$config->cacheKeys->block = new stdclass();
|
||||
$config->cacheKeys->block->welcome = 'welcome';
|
||||
$config->cacheKeys->block->contribute = 'contribute';
|
||||
$config->cacheKeys->block->projectStatistic = 'projectStatistic%s%s%s';
|
||||
$config->cacheKeys->block->recentProject = 'recentProject';
|
||||
|
||||
$config->cacheKeys->execution = new stdclass();
|
||||
$config->cacheKeys->execution->ajaxGetDropMenuProjects = 'ajaxDropMenuProjects';
|
||||
$config->cacheKeys->execution->ajaxGetDropMenuExecutions = 'ajaxDropMenuExecutions';
|
||||
|
||||
$config->cacheKeys->bug = new stdclass();
|
||||
$config->cacheKeys->bug->browse = 'bugBrowse%s';
|
||||
+9
-8
@@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}}
|
||||
if(!function_exists('getWebRoot')){function getWebRoot(){}}
|
||||
|
||||
/* 基本设置。Basic settings. */
|
||||
$config->version = '18.4.beta1'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
|
||||
$config->version = '18.6'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
|
||||
$config->liteVersion = '1.2'; // 迅捷版版本。 The version of Lite.
|
||||
$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP.
|
||||
$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time.
|
||||
@@ -34,7 +34,7 @@ $config->methodVar = 'f'; // 请求类型为GET:模块
|
||||
$config->viewVar = 't'; // 请求类型为GET:视图变量名。 requestType=GET: the view var name.
|
||||
$config->sessionVar = 'zentaosid'; // 请求类型为GET:session变量名。 requestType=GET: the session var name.
|
||||
$config->views = ',html,json,mhtml,xhtml,'; // 支持的视图类型。 Supported view formats.
|
||||
$config->visions = ',rnd,lite,'; // 支持的界面类型。 Supported vision formats.
|
||||
$config->visions = ',or,rnd,lite,'; // 支持的界面类型。 Supported vision formats.
|
||||
|
||||
/* 支持的主题和语言。Supported thems and languages. */
|
||||
$config->themes['default'] = 'default';
|
||||
@@ -71,12 +71,6 @@ $config->slaveDB->driver = 'mysql';
|
||||
$config->slaveDB->encoding = 'UTF8';
|
||||
$config->slaveDB->strictMode = false;
|
||||
|
||||
/* 缓存设置。Cache settings. */
|
||||
$config->cache = new stdclass();
|
||||
$config->cache->enable = false; // 是否开启缓存。Enable cache or not.
|
||||
$config->cache->lifetime = 5 * 60; // 缓存生存时间。The lifetime of cache.
|
||||
$config->cache->driver = 'File'; // 缓存驱动。 The driver of cache. can be File|Yac|Apcu.
|
||||
|
||||
/* 可用域名后缀列表。Domain postfix lists. */
|
||||
$config->domainPostfix = "|com|com.cn|com.hk|com.tw|com.vc|edu.cn|es|";
|
||||
$config->domainPostfix .= "|eu|fm|gov.cn|gs|hk|im|in|info|jp|kr|la|me|";
|
||||
@@ -167,6 +161,7 @@ $config->wideSize = 1400;
|
||||
$config->timeout = 30000;
|
||||
$config->duplicateTime = 30;
|
||||
$config->maxCount = 500;
|
||||
$config->batchMaxCount = 20;
|
||||
$config->moreLinks = array();
|
||||
|
||||
/* 配置参数过滤。Filter param settings. */
|
||||
@@ -177,6 +172,10 @@ if(file_exists($filterConfig)) include $filterConfig;
|
||||
$dbConfig = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'db.php';
|
||||
if(file_exists($dbConfig)) include $dbConfig;
|
||||
|
||||
/* 引用缓存的配置。 Include the cache config file. */
|
||||
$cacheConfig = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'cache.php';
|
||||
if(file_exists($cacheConfig)) include $cacheConfig;
|
||||
|
||||
/* 引用自定义的配置。 Include the custom config file. */
|
||||
$myConfig = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'my.php';
|
||||
if(file_exists($myConfig)) include $myConfig;
|
||||
@@ -198,9 +197,11 @@ if($config->edition != 'open')
|
||||
{
|
||||
$config->version = $config->edition . $config->{$config->edition . 'Version'};
|
||||
if($config->edition != 'max') unset($config->maxVersion);
|
||||
if($config->edition != 'ipd') unset($config->ipdVersion);
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($config->bizVersion);
|
||||
unset($config->maxVersion);
|
||||
unset($config->ipdVersion);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ $filter->default->paramValue = 'reg::paramValue';
|
||||
|
||||
$filter->default->get['onlybody'] = 'equal::yes';
|
||||
$filter->default->get['_single'] = 'equal::1';
|
||||
$filter->default->get['_nocache'] = 'equal::1';
|
||||
$filter->default->get['tid'] = 'reg::word';
|
||||
$filter->default->get['HTTP_X_REQUESTED_WITH'] = 'equal::XMLHttpRequest';
|
||||
|
||||
@@ -85,6 +86,8 @@ $filter->bug->browse = new stdclass();
|
||||
$filter->bug->default = new stdclass();
|
||||
$filter->bug->create = new stdclass();
|
||||
$filter->bug->export = new stdclass();
|
||||
$filter->bug->ajaxgetproductcases = new stdclass();
|
||||
$filter->bug->ajaxgetproductbugs = new stdclass();
|
||||
$filter->caselib->create = new stdclass();
|
||||
$filter->doc->create = new stdclass();
|
||||
$filter->doc->browse = new stdclass();
|
||||
@@ -300,6 +303,7 @@ $filter->project->task->cookie['windowWidth'] = 'int';
|
||||
$filter->project->export->cookie['checkedItem'] = 'reg::checked';
|
||||
$filter->project->execution->cookie['pagerExecutionAll'] = 'int';
|
||||
$filter->project->execution->cookie['showTask'] = 'code';
|
||||
$filter->project->execution->cookie['showStage'] = 'code';
|
||||
$filter->project->testcase->cookie['showAutoCase'] = 'int';
|
||||
$filter->project->testcase->cookie['onlyScene'] = 'code';
|
||||
|
||||
@@ -466,3 +470,9 @@ $filter->tree->browse->cookie['preBranch'] = 'reg::word';
|
||||
$filter->kanban->space->cookie['showClosed'] = 'code';
|
||||
|
||||
$filter->group->editmanagepriv->cookie['managePrivEditType'] = 'string';
|
||||
|
||||
$filter->bug->ajaxgetproductcases->get['search'] = 'reg::any';
|
||||
$filter->bug->ajaxgetproductcases->get['limit'] = 'int';
|
||||
|
||||
$filter->bug->ajaxgetproductbugs->get['search'] = 'reg::any';
|
||||
$filter->bug->ajaxgetproductbugs->get['limit'] = 'int';
|
||||
|
||||
@@ -34,6 +34,7 @@ $routes['/configurations/:name'] = 'config';
|
||||
$routes['/programs/:id/products'] = 'products';
|
||||
$routes['/products'] = 'products';
|
||||
$routes['/products/:id'] = 'product';
|
||||
$routes['/product/:id'] = 'product';
|
||||
|
||||
$routes['/productlines'] = 'productLines';
|
||||
$routes['/productlines/:id'] = 'productLine';
|
||||
|
||||
@@ -197,6 +197,7 @@ $config->openMethods[] = 'misc.checkupdate';
|
||||
$config->openMethods[] = 'misc.ping';
|
||||
$config->openMethods[] = 'misc.captcha';
|
||||
$config->openMethods[] = 'misc.features';
|
||||
$config->openMethods[] = 'misc.getremind';
|
||||
$config->openMethods[] = 'sso.login';
|
||||
$config->openMethods[] = 'sso.logout';
|
||||
$config->openMethods[] = 'sso.bind';
|
||||
@@ -316,6 +317,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_ACTIONRECENT', '`' . $config->db->prefix . 'actionrecent`');
|
||||
define('TABLE_FILE', '`' . $config->db->prefix . 'file`');
|
||||
define('TABLE_HOLIDAY', '`' . $config->db->prefix . 'holiday`');
|
||||
define('TABLE_HISTORY', '`' . $config->db->prefix . 'history`');
|
||||
@@ -369,9 +371,6 @@ define('TABLE_DATASET', '`' . $config->db->prefix . 'dataset`');
|
||||
define('TABLE_DATAVIEW', '`' . $config->db->prefix . 'dataview`');
|
||||
define('TABLE_DIMENSION', '`' . $config->db->prefix . 'dimension`');
|
||||
define('TABLE_SCENE', '`' . $config->db->prefix . 'scene`');
|
||||
define('VIEW_SCENECASE', '`ztv_scenecase`');
|
||||
|
||||
define('CHANGEVALUE', 100000000);
|
||||
|
||||
define('TABLE_PRIV', '`' . $config->db->prefix . 'priv`');
|
||||
define('TABLE_PRIVLANG', '`' . $config->db->prefix . 'privlang`');
|
||||
@@ -455,6 +454,7 @@ $config->programPriv->scrum = array('story', 'requirement', 'productplan
|
||||
$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'));
|
||||
$config->programPriv->agileplus = $config->programPriv->scrum;
|
||||
$config->programPriv->waterfallplus = $config->programPriv->waterfall;
|
||||
$config->programPriv->ipd = $config->programPriv->waterfall;
|
||||
|
||||
$config->safeFileTimeout = 3600;
|
||||
$config->waterfallModules = array('workestimation', 'durationestimation', 'budget', 'programplan', 'review', 'reviewissue', 'weekly', 'cm', 'milestone', 'design', 'opportunity', 'auditplan', 'trainplan', 'gapanalysis', 'pssp', 'researchplan', 'researchreport');
|
||||
|
||||
+2
-2
@@ -383,8 +383,8 @@ INSERT INTO `zt_product` (`id`, `program`, `name`, `code`, `bind`, `line`, `type
|
||||
INSERT INTO `zt_productplan` (`id`, `product`, `branch`, `parent`, `title`, `desc`, `begin`, `end`, `order`, `deleted`, `createdBy`, `createdDate`) VALUES
|
||||
(1, 1, 0, 0, '1.0版本', '开发出企业网站1.0版本。<br />', '2020-06-05', '2021-06-04', '', '0', 'tester1', '2021-04-01 11:08:09');
|
||||
INSERT INTO `zt_project` (`id`, `project`, `model`, `type`, `lifetime`, `budget`, `budgetUnit`, `attribute`, `percent`, `milestone`, `output`, `auth`, `parent`, `path`, `grade`, `name`, `code`, `begin`, `end`, `realBegan`, `realEnd`, `days`, `status`, `subStatus`, `pri`, `desc`, `version`, `parentVersion`, `planDuration`, `realDuration`, `openedBy`, `openedDate`, `openedVersion`, `lastEditedBy`, `lastEditedDate`, `closedBy`, `closedDate`, `canceledBy`, `canceledDate`, `PO`, `PM`, `QD`, `RD`, `team`, `acl`, `whitelist`, `order`, `deleted`) VALUES
|
||||
(1, 7, '', 'sprint', 'long', '0', 'CNY', '', 0, '0', '', '', 7, ',7,1,', 1, '企业网站第一期', 'coWeb1', '2020-06-05', '2021-12-04', '0000-00-00', '0000-00-00', 391, 'doing', '', '1', '开发企业网站的基本雏形。<br />', 0, 0, 0, 0, '', '0000-00-00 00:00:00', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 'productManager', 'projectManager', 'testManager', 'productManager', '公司开发团队', 'open', '', 5, '0'),
|
||||
(2, 7, '', 'sprint', 'long', '0', 'CNY', '', 0, '0', '', '', 7, ',7,2,', 1, '企业网站第二期', 'coWebsite2', '2021-06-05', '2022-06-04', '0000-00-00', '0000-00-00', 260, 'wait', '', '1', '', 0, 0, 0, 0, '', '0000-00-00 00:00:00', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 'productManager', 'projectManager', 'testManager', 'productManager', '公司开发团队', 'open', '', 10, '0'),
|
||||
(1, 7, '', 'sprint', 'long', '0', 'CNY', '', 0, '0', '', '', 7, ',7,1,', 1, '企业网站第一期', 'coWeb1', '2020-06-05', '2021-12-04', '0000-00-00', '0000-00-00', 391, 'doing', '', '1', '开发企业网站的基本雏形。<br />', 0, 0, 0, 0, '', '0000-00-00 00:00:00', '15.0.rc3', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 'productManager', 'projectManager', 'testManager', 'productManager', '公司开发团队', 'open', '', 5, '0'),
|
||||
(2, 7, '', 'sprint', 'long', '0', 'CNY', '', 0, '0', '', '', 7, ',7,2,', 1, '企业网站第二期', 'coWebsite2', '2021-06-05', '2022-06-04', '0000-00-00', '0000-00-00', 260, 'wait', '', '1', '', 0, 0, 0, 0, '', '0000-00-00 00:00:00', '15.0.rc3', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 'productManager', 'projectManager', 'testManager', 'productManager', '公司开发团队', 'open', '', 10, '0'),
|
||||
(7, 0, 'scrum', 'project', '', '0', 'CNY', '', 0, '0', '', 'extend', 6, ',6,7,', 2, '企业管理系统', '', '2021-06-05', '2022-06-04', '0000-00-00', '0000-00-00', 0, 'doing', '', '1', '', 0, 0, 0, 0, 'admin', '2021-04-28 11:22:04', '15.0.rc3', 'admin', '2021-04-28 11:22:04', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 'projectManager', '', '', '', 'open', ',tester3,admin', 35, '0'),
|
||||
(6, 0, '', 'program', '', '0', 'CNY', '', 0, '0', '', '', 0, ',6,', 1, '企业管理', '', '2021-06-05', '2022-06-04', '0000-00-00', '0000-00-00', 0, 'doing', '', '1', '', 0, 0, 0, 0, 'admin', '2021-04-28 11:22:04', '15.0.rc3', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '', '', '', '', 'open', '', 30, '0');
|
||||
INSERT INTO `zt_projectcase` (`project`, `product`, `case`, `count`, `version`, `order`) VALUES
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
TRUNCATE TABLE `zt_pivot`;
|
||||
TRUNCATE TABLE `zt_chart`;
|
||||
TRUNCATE TABLE `zt_basicmeas`;
|
||||
DELETE FROM `zt_screen` WHERE id IN (1,2,4,6,7,8);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -727,7 +727,7 @@ CREATE TABLE `zt_cron` (
|
||||
`lastTime` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `lastTime` (`lastTime`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;
|
||||
CREATE TABLE `zt_dashboard` (
|
||||
`id` mediumint(8) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
@@ -2148,6 +2148,19 @@ CREATE TABLE `zt_product` (
|
||||
`acl` enum('open','private','custom') NOT NULL DEFAULT 'open',
|
||||
`whitelist` text NOT NULL,
|
||||
`reviewer` text NOT NULL,
|
||||
`draftStories` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`activeStories` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`changingStories` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`reviewingStories` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`closedStories` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`totalStories` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`unresolvedBugs` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`closedBugs` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`fixedBugs` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`totalBugs` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`plans` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`releases` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`finishedStories` mediumint(9) NOT NULL DEFAULT '0',
|
||||
`createdBy` varchar(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`createdVersion` varchar(20) NOT NULL,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+5
-2
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,42 @@
|
||||
INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`) VALUES ('0','*','*','*','*','moduleName=misc&methodName=cleanCache', '清理缓存文件','zentao', 1, 'normal');
|
||||
|
||||
ALTER TABLE `zt_product`
|
||||
ADD `draftStories` mediumint(8) NOT NULL DEFAULT '0' AFTER `reviewer`,
|
||||
ADD `activeStories` mediumint(8) NOT NULL DEFAULT '0' AFTER `draftStories`,
|
||||
ADD `changingStories` mediumint(8) NOT NULL DEFAULT '0' AFTER `activeStories`,
|
||||
ADD `reviewingStories` mediumint(8) NOT NULL DEFAULT '0' AFTER `changingStories`,
|
||||
ADD `finishedStories` mediumint NOT NULL DEFAULT '0' AFTER `reviewingStories`,
|
||||
ADD `closedStories` mediumint(8) NOT NULL DEFAULT '0' AFTER `finishedStories`,
|
||||
ADD `totalStories` mediumint(8) NOT NULL DEFAULT '0' AFTER `closedStories`,
|
||||
ADD `unresolvedBugs` mediumint(8) NOT NULL DEFAULT '0' AFTER `totalStories`,
|
||||
ADD `closedBugs` mediumint(8) NOT NULL DEFAULT '0' AFTER `unresolvedBugs`,
|
||||
ADD `fixedBugs` mediumint(8) NOT NULL DEFAULT '0' AFTER `closedBugs`,
|
||||
ADD `totalBugs` mediumint(8) NOT NULL DEFAULT '0' AFTER `fixedBugs`,
|
||||
ADD `plans` mediumint(8) NOT NULL DEFAULT '0' AFTER `totalBugs`,
|
||||
ADD `releases` mediumint(8) NOT NULL DEFAULT '0' AFTER `plans`;
|
||||
|
||||
UPDATE `zt_pivot` SET `sql` = 'SELECT \n t1.name AS \'产品\', \n IFNULL(t2.name, \'/\') AS \'一级项目集\', \n IFNULL(t3.name, \'/\') AS \'产品线\', \n IFNULL(t6.exfixedstorys, 0) AS \'研发完成需求数\', \n round(IFNULL(t6.exfixedstorysmate, 0),3) AS \'研发完成需求规模数\',\n IFNULL(t8.storycases, 0) AS \'需求用例数\',\n round(storycases/exfixedstorysmate,3) AS \'用例密度\',\n round(IFNULL(t10.casestorys/t6.exfixedstorys,0),3) AS \'用例覆盖率\',\n IFNULL(t7.bug, 0) AS \'Bug数\',\n IFNULL(t7.effbugs, 0) AS \'有效Bug数\',\n IFNULL(t7.pri12bugs, 0) AS \'优先级为1,2的Bug数\',\n round(bug/exfixedstorysmate,3) AS \'Bug密度\',\n IFNULL(t7.fixedbugs, 0) AS \'修复Bug数\',\n round(t7.fixedbugs/bug,3) \'Bug修复率\'\nFROM \n zt_product AS t1 \n LEFT JOIN zt_project AS t2 ON t1.program = t2.id AND t2.type = \'program\' AND t2.grade = 1 \n LEFT JOIN zt_module AS t3 ON t1.line = t3.id AND t3.type = \'line\' \n LEFT JOIN (\n SELECT\n product, \n count(id) exfixedstorys, \n sum(estimate) exfixedstorysmate\n FROM zt_story \n WHERE deleted = \'0\' and (stage in (\'developed\',\'testing\',\'verfied\',\'released\') or (status=\'closed\' and closedReason=\'done\'))\n GROUP BY product) AS t6 ON t1.id = t6.product \n LEFT JOIN (SELECT product, COUNT(id) AS bug,\n SUM(case when resolution in (\'fixed\',\'postponed\') or status=\'active\' then 1 else 0 end) effbugs, \n SUM(CASE WHEN resolution=\'fixed\' then 1 else 0 end) fixedbugs,\n SUM(CASE WHEN severity in (1,2) then 1 else 0 end) pri12bugs\n FROM zt_bug WHERE deleted = \'0\' GROUP BY product) AS t7 ON t1.id = t7.product \n LEFT JOIN (SELECT product, COUNT(id) AS storycases FROM zt_case WHERE deleted=\'0\' GROUP BY product) AS t8 ON t1.id=t8.product\n LEFT JOIN (\n select \n t9.product, \n count(t9.story) casestorys\n from(\n SELECT \n zt_case.product,zt_case.story \n FROM zt_case \n left join zt_story\n on zt_case.story=zt_story.id\n WHERE zt_case.deleted=\'0\' and zt_case.story !=\'0\' and zt_story.deleted=\'0\' and (zt_story.stage in (\'developed\',\'testing\',\'verfied\',\'released\') or (zt_story.status=\'closed\' and zt_story.closedReason=\'done\'))\n GROUP BY product, story) t9\n group by product) t10\n on t1.id=t10.product\nWHERE t1.deleted = \'0\' AND t1.status != \'closed\' AND t1.shadow = \'0\'AND t1.vision = \'rnd\'\nORDER BY t1.order'
|
||||
WHERE id = 1002;
|
||||
UPDATE `zt_chart` SET `settings` = '{\"value\": {\"type\": \"agg\", \"field\": \"taskleft\", \"agg\": \"sum\"}, \"title\": {\"type\": \"text\", \"name\": \"\"}, \"type\": \"value\"}'
|
||||
WHERE id = 10112;
|
||||
|
||||
UPDATE `zt_priv` SET `edition`=',biz,max,ipd,' where `module`='feedback' and `method`='toUserStory';
|
||||
|
||||
UPDATE `zt_pivot` SET `stage` = 'published', `sql` = 'select t1.id,t3.name as project,IF(t3.multiple=\"1\",t1.name,\"\") as execution,t2.id as bugID,t2.type from zt_project as t1 \r\nleft join zt_bug as t2 on t1.id=t2.execution\r\nleft join zt_project as t3 on t3.id=t1.project\r\nwhere t1.deleted=\'0\' and t2.deleted=\'0\' and if($project=\'\',1,t3.id=$project) and if($execution=\'\',1,t1.id=$execution)'
|
||||
WHERE `sql` = 'select t1.id,t3.name as project,t3.id,IF(t3.multiple=\"1\",t1.name,\"\") as execution,t2.id as bugID,t2.type from zt_project as t1 \r\nleft join zt_bug as t2 on t1.id=t2.execution\r\nleft join zt_project as t3 on t3.id=t1.project\r\nwhere t1.deleted=\'0\' and t2.deleted=\'0\' and if($project=\'\',1,t3.id=$project) and if($execution=\'\',1,t1.id=$execution)';
|
||||
UPDATE `zt_pivot` SET `stage` = 'published', `sql` = 'select t1.id,t4.name as project,IF(t4.multiple=\"1\",t1.name,\"\") as execution,t1.status,t2.number as tasks,round(t2.consumed,2) as consumed,round(t2.`left`,2) as `left`,t3.stories,t2.undone as undoneTask,t3.undone as undoneStory,t2.totalReal from zt_project as t1 \r\nleft join ztv_executionsummary as t2 on t1.id=t2.execution\r\nleft join ztv_projectstories as t3 on t1.id=t3.execution\r\nleft join zt_project as t4 on t4.id=t1.project\r\nwhere t1.deleted=\'0\' and t1.type in (\'sprint\',\'stage\') and if($project=\'\',1,t4.id=$project) and if($execution=\'\',1,t1.id=$execution) and if($status=\'\',1,t1.status=$status)'
|
||||
WHERE `sql` = 'select t1.id,t4.name as project,t4.id,IF(t4.multiple=\"1\",t1.name,\"\") as execution,t1.status,t2.number as tasks,round(t2.consumed,2) as consumed,round(t2.`left`,2) as `left`,t3.stories,t2.undone as undoneTask,t3.undone as undoneStory,t2.totalReal from zt_project as t1 \r\nleft join ztv_executionsummary as t2 on t1.id=t2.execution\r\nleft join ztv_projectstories as t3 on t1.id=t3.execution\r\nleft join zt_project as t4 on t4.id=t1.project\r\nwhere t1.deleted=\'0\' and t1.type in (\'sprint\',\'stage\') and if($project=\'\',1,t4.id=$project) and if($execution=\'\',1,t1.id=$execution) and if($status=\'\',1,t1.status=$status)';
|
||||
UPDATE `zt_pivot` SET `stage` = 'published', `sql` = 'select t1.id, t5.name as project,IF(t5.multiple=\"1\",t1.name,\"\") as execution,t2.stories,(t2.stories-t2.undone) as doneStory,t3.number,(t3.number-t3.undone) as doneTask,t4.bugs,t4.resolutions, round(t4.bugs/(t2.stories-t2.undone),2) as bugthanstory,round(t4.bugs/(t3.number-t3.undone),2) as bugthantask,t4.seriousBugs from zt_project as t1 \r\nleft join ztv_projectstories as t2 on t1.id=t2.execution\r\nleft join ztv_executionsummary as t3 on t1.id=t3.execution\r\nleft join ztv_projectbugs as t4 on t1.id=t4.execution\r\nleft join zt_project as t5 on t5.id=t1.project\r\nwhere t1.deleted=\'0\' and t1.type in (\'sprint\',\'stage\') and t1.grade=\'1\' and if($project=\'\',1,t5.id=$project) and if($execution=\'\',1,t1.id=$execution)'
|
||||
WHERE `sql` = 'select t1.id, t5.name as project,t5.id,IF(t5.multiple=\"1\",t1.name,\"\") as execution,t2.stories,(t2.stories-t2.undone) as doneStory,t3.number,(t3.number-t3.undone) as doneTask,t4.bugs,t4.resolutions, round(t4.bugs/(t2.stories-t2.undone),2) as bugthanstory,round(t4.bugs/(t3.number-t3.undone),2) as bugthantask,t4.seriousBugs from zt_project as t1 \r\nleft join ztv_projectstories as t2 on t1.id=t2.execution\r\nleft join ztv_executionsummary as t3 on t1.id=t3.execution\r\nleft join ztv_projectbugs as t4 on t1.id=t4.execution\r\nleft join zt_project as t5 on t5.id=t1.project\r\nwhere t1.deleted=\'0\' and t1.type in (\'sprint\',\'stage\') and t1.grade=\'1\' and if($project=\'\',1,t5.id=$project) and if($execution=\'\',1,t1.id=$execution)';
|
||||
UPDATE `zt_pivot` SET `stage` = 'published', `sql` = 'select t1.id,t3.name as project,t3.id as projectID,IF(t3.multiple=\"1\",t1.name,\"\") as execution,t1.id as bugID,t2.assignedTo from zt_project as t1 \r\nleft join zt_bug as t2 on t1.id=t2.execution \r\nleft join zt_project as t3 on t3.id=t1.project\r\nwhere t1.deleted=\'0\' and t2.deleted=\'0\' having bugID!=\'\' and if($project=\'\',1,t3.id=$project) and if($execution=\'\',1,t1.id=$execution)'
|
||||
WHERE `sql` = 'select t1.id,t3.name as project,t3.id,IF(t3.multiple=\"1\",t1.name,\"\") as execution,t1.id as bugID,t2.assignedTo from zt_project as t1 \r\nleft join zt_bug as t2 on t1.id=t2.execution \r\nleft join zt_project as t3 on t3.id=t1.project\r\nwhere t1.deleted=\'0\' and t2.deleted=\'0\' having bugID!=\'\' and if($project=\'\',1,t3.id=$project) and if($execution=\'\',1,t1.id=$execution)';
|
||||
UPDATE `zt_pivot` SET `stage` = 'published', `sql` = 'select t1.id,t3.name as project,t3.id as projectID,IF(t3.multiple=\"1\",t1.name,\"\") as execution,t1.id as bugID,t2.resolvedBy from zt_project as t1 \r\nleft join zt_bug as t2 on t1.id=t2.execution\r\nleft join zt_project as t3 on t3.id=t1.project\r\nwhere t1.deleted=\'0\' and t2.deleted=\'0\' and t2.status!=\'active\' and t2.resolvedBy!=\'\' having bugID!=\'\' and if($project=\'\',1,t3.id=$project) and if($execution=\'\',1,t1.id=$execution)'
|
||||
WHERE `sql` = 'select t1.id,t3.name as project,t3.id,IF(t3.multiple=\"1\",t1.name,\"\") as execution,t1.id as bugID,t2.resolvedBy from zt_project as t1 \r\nleft join zt_bug as t2 on t1.id=t2.execution\r\nleft join zt_project as t3 on t3.id=t1.project\r\nwhere t1.deleted=\'0\' and t2.deleted=\'0\' and t2.status!=\'active\' and t2.resolvedBy!=\'\' having bugID!=\'\' and if($project=\'\',1,t3.id=$project) and if($execution=\'\',1,t1.id=$execution)';
|
||||
UPDATE `zt_pivot` SET `stage` = 'published', `sql` = 'select t1.id,t3.name as project,t3.id as projectID,IF(t3.multiple=\"1\",t1.name,\"\") as execution,t1.id as bugID,t2.openedBy from zt_project as t1 \r\nleft join zt_bug as t2 on t1.id=t2.execution\r\nleft join zt_project as t3 on t3.id=t1.project\r\nwhere t1.deleted=\'0\' and t2.deleted=\'0\' having bugID!=\'\' and if($project=\'\',1,t3.id=$project) and if($execution=\'\',1,t1.id=$execution)'
|
||||
WHERE `sql` = 'select t1.id,t3.name as project,t3.id,IF(t3.multiple=\"1\",t1.name,\"\") as execution,t1.id as bugID,t2.openedBy from zt_project as t1 \r\nleft join zt_bug as t2 on t1.id=t2.execution\r\nleft join zt_project as t3 on t3.id=t1.project\r\nwhere t1.deleted=\'0\' and t2.deleted=\'0\' having bugID!=\'\' and if($project=\'\',1,t3.id=$project) and if($execution=\'\',1,t1.id=$execution)';
|
||||
UPDATE `zt_pivot` SET `stage` = 'published', `sql` = 'select t1.id,t3.name as project,t3.id as projectID,IF(t3.multiple=\"1\",t1.name,\"\") as execution,t1.id as bugID,t2.status from zt_project as t1 \r\nleft join zt_bug as t2 on t1.id=t2.execution\r\nleft join zt_project as t3 on t3.id=t1.project\r\nwhere t1.deleted=\'0\' and t2.deleted=\'0\' having bugID!=\' \' and if($project=\'\',1,t3.id=$project) and if($execution=\'\',1,t1.id=$execution)'
|
||||
WHERE `sql` = 'select t1.id,t3.name as project,t3.id,IF(t3.multiple=\"1\",t1.name,\"\") as execution,t1.id as bugID,t2.status from zt_project as t1 \r\nleft join zt_bug as t2 on t1.id=t2.execution\r\nleft join zt_project as t3 on t3.id=t1.project\r\nwhere t1.deleted=\'0\' and t2.deleted=\'0\' having bugID!=\' \' and if($project=\'\',1,t3.id=$project) and if($execution=\'\',1,t1.id=$execution)';
|
||||
UPDATE `zt_pivot` SET `stage` = 'published', `sql` = 'select t1.id,t3.name as project,t3.id as projectID,IF(t3.multiple=\"1\",t1.name,\"\") as execution,t1.id as bugID,t2.resolution from zt_project as t1 \r\nleft join zt_bug as t2 on t1.id=t2.execution\r\nleft join zt_project as t3 on t3.id=t1.project\r\n where t1.deleted=\'0\' and t2.deleted=\'0\' and t2.resolution!=\'\' having bugID!=\'\' and if($project=\'\',1,t3.id=$project) and if($execution=\'\',1,t1.id=$execution)'
|
||||
WHERE `sql` = 'select t1.id,t3.name as project,t3.id,IF(t3.multiple=\"1\",t1.name,\"\") as execution,t1.id as bugID,t2.resolution from zt_project as t1 \r\nleft join zt_bug as t2 on t1.id=t2.execution\r\nleft join zt_project as t3 on t3.id=t1.project\r\n where t1.deleted=\'0\' and t2.deleted=\'0\' and t2.resolution!=\'\' having bugID!=\'\' and if($project=\'\',1,t3.id=$project) and if($execution=\'\',1,t1.id=$execution)';
|
||||
|
||||
UPDATE `zt_chart` SET `createdBy` = 'admin' WHERE `id` <= 1110;
|
||||
@@ -0,0 +1,56 @@
|
||||
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('traincourse', 'cloudImport', '125', ',biz,max,ipd,', ',rnd,', '1', '10');
|
||||
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('dataview', 'export', '650', ',biz,max,ipd,', ',rnd,', '1', '30');
|
||||
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2107, 'priv', 'de', 'traincourse-cloudImport', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2107, 'priv', 'en', 'traincourse-cloudImport', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2107, 'priv', 'fr', 'traincourse-cloudImport', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2107, 'priv', 'zh-cn', 'traincourse-cloudImport', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2107, 'priv', 'zh-tw', 'traincourse-cloudImport', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2108, 'priv', 'de', 'dataview-export', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2108, 'priv', 'en', 'dataview-export', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2108, 'priv', 'fr', 'dataview-export', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2108, 'priv', 'zh-cn', 'dataview-export', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2108, 'priv', 'zh-tw', 'dataview-export', '', '');
|
||||
|
||||
REPLACE INTO zt_privmanager (id, parent, code, `type`, edition, vision, `order`) VALUES (650, 445, '', 'package', ',biz,max,ipd,', ',rnd,', 20);
|
||||
REPLACE INTO zt_privlang (objectID, objectType, lang, `key`, value, `desc`) VALUES(650, 'manager', 'zh-cn', '', '导出数据表', '');
|
||||
|
||||
REPLACE INTO zt_privrelation (priv, `type`, relationPriv) VALUES(2108, 'depend', 1648);
|
||||
REPLACE INTO zt_privrelation (priv, `type`, relationPriv) VALUES(2108, 'depend', 1651);
|
||||
|
||||
ALTER TABLE `zt_traincourse` ADD `importedStatus` enum('','wait','doing','done') NOT NULL DEFAULT '';
|
||||
ALTER TABLE `zt_traincourse` ADD `lastUpdatedTime` int UNSIGNED NOT NULL DEFAULT 0;
|
||||
ALTER TABLE `zt_traincourse` MODIFY `code` varchar(255) NOT NULL DEFAULT '';
|
||||
|
||||
UPDATE `zt_im_chat` SET `createdDate` = NULL WHERE `createdDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_chat` SET `editedDate` = NULL WHERE `editedDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_chat` SET `mergedDate` = NULL WHERE `mergedDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_chat` SET `lastActiveTime` = NULL WHERE `lastActiveTime` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_chat` SET `dismissDate` = NULL WHERE `dismissDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_chat` SET `archiveDate` = NULL WHERE `archiveDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_chatuser` SET `join` = NULL WHERE `join` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_chatuser` SET `quit` = NULL WHERE `quit` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_client` SET `createdDate` = NULL WHERE `createdDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_client` SET `editedDate` = NULL WHERE `editedDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_message` SET `date` = NULL WHERE `date` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_message_backup` SET `date` = NULL WHERE `date` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_message_index` SET `startDate` = NULL WHERE `startDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_message_index` SET `endDate` = NULL WHERE `endDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_chat_message_index` SET `startDate` = NULL WHERE `startDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_chat_message_index` SET `endDate` = NULL WHERE `endDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_queue` SET `addDate` = NULL WHERE `addDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_queue` SET `processDate` = NULL WHERE `processDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_conference` SET `openedDate` = NULL WHERE `openedDate` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_conferenceaction` SET `date` = NULL WHERE `date` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_userdevice` SET `validUntil` = NULL WHERE `validUntil` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_userdevice` SET `lastLogin` = NULL WHERE `lastLogin` = '0000-00-00 00:00:00';
|
||||
UPDATE `zt_im_userdevice` SET `lastLogout` = NULL WHERE `lastLogout` = '0000-00-00 00:00:00';
|
||||
|
||||
CREATE INDEX `project` ON `zt_project` (`project`);
|
||||
|
||||
UPDATE `zt_privlang` SET `value`='删除风险' WHERE `objectID`=197 AND `objectType`='manager';
|
||||
UPDATE `zt_auditcl` SET `deleted` = '0' WHERE `deleted` = '';
|
||||
|
||||
UPDATE `zt_workflowdatasource` SET `vision` = 'rnd' WHERE `code` IN ('products','projects','productLines','stories','tasks','bugs','groups','users','branches','builds','modules','plans','productType','productStatus','productAcl','projectType','projectStatus','projectAcl','releaseStatus','storySource','storyPri','storyStatus','storyStage','bugSeverity','bugPri','bugType','bugOs','bugBrowser','bugStatus','taskType','taskPri','taskStatus','testcasePri','testcaseType','testcaseStage','testcaseStatus','testtaskPri','testtaskStatus','feedbackStatus','bugResolution','cases','feedbackModules','storyType','executions','projectModel','feedbackType','feedbackSolution','feedbackclosedReason','taskReason','testsuiteAuth','programs','storyClosedReason');
|
||||
|
||||
UPDATE `zt_product` SET `shadow` = 1 WHERE `vision` = 'lite';
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,255 @@
|
||||
CREATE TABLE `zt_demandpool` (
|
||||
`id` int(8) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`desc` mediumtext NOT NULL,
|
||||
`status` char(30) NOT NULL,
|
||||
`createdBy` char(30) NOT NULL,
|
||||
`createdDate` date NOT NULL,
|
||||
`owner` text NOT NULL,
|
||||
`reviewer` text NOT NULL,
|
||||
`acl` char(30) NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `zt_demand` (
|
||||
`id` int(8) NOT NULL AUTO_INCREMENT,
|
||||
`pool` int(8) NOT NULL,
|
||||
`module` int(8) NOT NULL,
|
||||
`product` mediumint(8) NOT NULL,
|
||||
`parent` mediumint(8) NOT NULL,
|
||||
`pri` char(30) NOT NULL,
|
||||
`category` char(30) NOT NULL,
|
||||
`source` char(30) NOT NULL,
|
||||
`sourceNote` varchar(255) NOT NULL,
|
||||
`title` varchar(255) NOT NULL,
|
||||
`feedbackedBy` varchar(255) NOT NULL,
|
||||
`email` varchar(255) NOT NULL,
|
||||
`assignedTo` char(30) NOT NULL,
|
||||
`assignedDate` datetime NOT NULL,
|
||||
`reviewedBy` text NOT NULL,
|
||||
`reviewedDate` datetime NOT NULL,
|
||||
`status` char(30) NOT NULL,
|
||||
`duration` char(30) NOT NULL,
|
||||
`BSA` char(30) NOT NULL,
|
||||
`story` mediumint(8) NOT NULL,
|
||||
`roadmap` mediumint(8) NOT NULL,
|
||||
`createdBy` char(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`mailto` text NOT NULL,
|
||||
`duplicateDemand` mediumint(8) NOT NULL,
|
||||
`childDemands` varchar(255) NOT NULL,
|
||||
`version` varchar(255) NOT NULL,
|
||||
`vision` varchar(255) NOT NULL DEFAULT 'or',
|
||||
`color` varchar(255) NOT NULL,
|
||||
`changedBy` char(30) NOT NULL,
|
||||
`changedDate` datetime NOT NULL,
|
||||
`closedBy` char(30) NOT NULL,
|
||||
`closedDate` datetime NOT NULL,
|
||||
`closedReason` varchar(30) NOT NULL,
|
||||
`submitedBy` varchar(30) NOT NULL,
|
||||
`lastEditedBy` varchar(30) NOT NULL DEFAULT '',
|
||||
`lastEditedDate` datetime NOT NULL,
|
||||
`activatedDate` datetime NOT NULL,
|
||||
`distributedBy` varchar(30) NOT NULL DEFAULT '',
|
||||
`distributedDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `zt_demandspec` (
|
||||
`demand` mediumint(9) NOT NULL,
|
||||
`version` smallint(6) NOT NULL,
|
||||
`title` varchar(255) NOT NULL,
|
||||
`spec` mediumtext NOT NULL,
|
||||
`verify` mediumtext NOT NULL,
|
||||
`files` text NOT NULL,
|
||||
UNIQUE KEY `demand` (`demand`,`version`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `zt_demandreview` (
|
||||
`demand` mediumint(9) NOT NULL,
|
||||
`version` smallint(6) NOT NULL,
|
||||
`reviewer` varchar(30) NOT NULL,
|
||||
`result` varchar(30) NOT NULL,
|
||||
`reviewDate` datetime NOT NULL,
|
||||
UNIQUE KEY `demand` (`demand`,`version`,`reviewer`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `zt_charter` (
|
||||
`id` int(8) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`level` int(8) NOT NULL,
|
||||
`category` char(30) NOT NULL,
|
||||
`market` varchar(30) NOT NULL,
|
||||
`appliedBy` char(30) NOT NULL,
|
||||
`appliedDate` datetime NOT NULL,
|
||||
`budget` char(30) NOT NULL,
|
||||
`budgetUnit` char(30) NOT NULL,
|
||||
`product` mediumint(8) NOT NULL,
|
||||
`roadmap` mediumint(8) NOT NULL,
|
||||
`spec` mediumtext NOT NULL,
|
||||
`status` char(30) NOT NULL,
|
||||
`createdBy` char(30) NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`charterFiles` text NOT NULL,
|
||||
`reviewedBy` char(30) NOT NULL,
|
||||
`reviewedResult` char(30) NOT NULL,
|
||||
`reviewedDate` datetime NOT NULL,
|
||||
`meetingDate` date NOT NULL,
|
||||
`meetingLocation` varchar(255) NOT NULL,
|
||||
`meetingMinutes` mediumtext NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
REPLACE INTO `zt_config` (`vision`, `owner`, `module`, `section`, `key`, `value`) VALUES ('or', 'system', 'demand', '', 'reviewRules', 'allpass');
|
||||
REPLACE INTO `zt_config` (`vision`, `owner`, `module`, `section`, `key`, `value`) VALUES ('or', 'system', 'demand', '', 'needReview', 1);
|
||||
|
||||
ALTER TABLE `zt_story` ADD `BSA` char(30) NOT NULL AFTER `notifyEmail`;
|
||||
ALTER TABLE `zt_story` ADD `duration` char(30) NOT NULL AFTER `notifyEmail`;
|
||||
ALTER TABLE `zt_story` ADD `demand` mediumint(8) NOT NULL AFTER `notifyEmail`;
|
||||
ALTER TABLE `zt_product` ADD `PMT` text COLLATE 'utf8_general_ci' NOT NULL AFTER `reviewer`;
|
||||
ALTER TABLE `zt_story` ADD `submitedBy` varchar(30) NOT NULL AFTER `changedDate`;
|
||||
ALTER TABLE `zt_story` ADD `roadmap` VARCHAR(255) NOT NULL DEFAULT '' AFTER `plan`;
|
||||
ALTER TABLE `zt_charter` ADD `check` enum('0','1') NOT NULL DEFAULT '0';
|
||||
ALTER TABLE `zt_charter` modify column reviewedBy varchar(255);
|
||||
|
||||
CREATE TABLE `zt_roadmap` (
|
||||
`id` mediumint(8) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`product` mediumint(8) NOT NULL,
|
||||
`branch` mediumint(8) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`status` char(30) NOT NULL,
|
||||
`begin` date NOT NULL,
|
||||
`end` date NOT NULL,
|
||||
`desc` longtext NOT NULL,
|
||||
`createdBy` char(30) NOT NULL,
|
||||
`createdDate` date NOT NULL,
|
||||
`closedBy` char(30) NOT NULL,
|
||||
`closedDate` datetime NOT NULL,
|
||||
`closedReason` enum('done','canceled') DEFAULT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `zt_roadmapstory` (
|
||||
`roadmap` mediumint(8) unsigned NOT NULL,
|
||||
`story` mediumint(8) unsigned NOT NULL,
|
||||
`order` MEDIUMINT UNSIGNED NOT NULL,
|
||||
UNIQUE KEY `roadmap_story` (`roadmap`,`story`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
ALTER TABLE `zt_story` MODIFY `status` enum('','changing','active','draft','closed','reviewing','launched','developing') NOT NULL DEFAULT '' AFTER `estimate`;
|
||||
|
||||
ALTER TABLE `zt_project`
|
||||
ADD `charter` mediumint(8) NOT NULL DEFAULT 0 AFTER `project`,
|
||||
ADD `category` char(30) COLLATE 'utf8_general_ci' NOT NULL AFTER `type`;
|
||||
|
||||
REPLACE INTO `zt_stage` (`name`, `percent`, `type`, `projectType`, `createdBy`, `createdDate`, `editedBy`, `editedDate`, `deleted`) VALUES
|
||||
('概念', '10', 'concept', 'ipd', 'admin', '2020-02-08 21:08:30', 'admin', '2020-02-12 13:50:27', '0'),
|
||||
('计划', '10', 'plan', 'ipd', 'admin', '2020-02-08 21:08:30', 'admin', '2020-02-12 13:50:27', '0'),
|
||||
('开发', '50', 'develop', 'ipd', 'admin', '2020-02-08 21:08:30', 'admin', '2020-02-12 13:50:27', '0'),
|
||||
('验证', '15', 'qualify', 'ipd', 'admin', '2020-02-08 21:08:30', 'admin', '2020-02-12 13:50:27', '0'),
|
||||
('发布', '10', 'launch', 'ipd', 'admin', '2020-02-08 21:08:30', 'admin', '2020-02-12 13:50:27', '0'),
|
||||
('全生命周期', '5', 'lifecycle', 'ipd', 'admin', '2020-02-08 21:08:45', 'admin', '2020-02-12 13:50:27', '0');
|
||||
|
||||
ALTER TABLE `zt_review` ADD `begin` date NULL AFTER `createdDate`;
|
||||
ALTER TABLE `zt_review` MODIFY `doc` varchar(255);
|
||||
ALTER TABLE `zt_review` MODIFY `docVersion` varchar(255);
|
||||
|
||||
ALTER TABLE `zt_object` ADD `end` date NULL AFTER `designEst`;
|
||||
|
||||
ALTER TABLE `zt_charter` ADD `closedBy` char(30) NULL;
|
||||
ALTER TABLE `zt_charter` ADD `closedDate` datetime NULL;
|
||||
ALTER TABLE `zt_charter` ADD `closedReason` varchar(255) NULL;
|
||||
ALTER TABLE `zt_charter` ADD `activatedBy` char(30) NULL;
|
||||
ALTER TABLE `zt_charter` ADD `activatedDate` datetime NULL;
|
||||
|
||||
UPDATE `zt_priv` SET `vision` = ',rnd,or,' WHERE `module` = 'requirement' AND `method` = 'import';
|
||||
UPDATE `zt_priv` SET `vision` = ',rnd,or,' WHERE `module` = 'requirement' AND `method` = 'exportTemplate';
|
||||
|
||||
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('demand', 'export', '643', ',ipd,', ',or,', '1', '210');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2109, 'priv', 'de', 'demand-export', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2109, 'priv', 'en', 'demand-export', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2109, 'priv', 'fr', 'demand-export', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2109, 'priv', 'zh-cn', 'demand-export', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2109, 'priv', 'zh-tw', 'demand-export', '', '');
|
||||
|
||||
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('demand', 'exportTemplate', '643', ',ipd,', ',or,', '1', '220');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2110, 'priv', 'de', 'demand-exportTemplate', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2110, 'priv', 'en', 'demand-exportTemplate', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2110, 'priv', 'fr', 'demand-exportTemplate', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2110, 'priv', 'zh-cn', 'demand-exportTemplate', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2110, 'priv', 'zh-tw', 'demand-exportTemplate', '', '');
|
||||
|
||||
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('demand', 'import', '643', ',ipd,', ',or,', '1', '230');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2111, 'priv', 'de', 'demand-import', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2111, 'priv', 'en', 'demand-import', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2111, 'priv', 'fr', 'demand-import', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2111, 'priv', 'zh-cn', 'demand-import', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2111, 'priv', 'zh-tw', 'demand-import', '', '');
|
||||
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2109, 'depend', 2075);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2109, 'recommend', 2110);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2109, 'recommend', 2111);
|
||||
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2110, 'depend', 2075);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2110, 'recommend', 2109);
|
||||
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2111, 'depend', 2075);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2111, 'depend', 2110);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2111, 'recommend', 2109);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2111, 'recommend', 2076);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2111, 'recommend', 2077);
|
||||
|
||||
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('requirement', 'batchChangeRoadmap', '32', ',ipd,', ',or,', '1', '125');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2112, 'priv', 'de', 'requirement-batchChangeRoadmap', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2112, 'priv', 'en', 'requirement-batchChangeRoadmap', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2112, 'priv', 'fr', 'requirement-batchChangeRoadmap', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2112, 'priv', 'zh-cn', 'requirement-batchChangeRoadmap', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2112, 'priv', 'zh-tw', 'requirement-batchChangeRoadmap', '', '');
|
||||
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2112, 'depend', 65);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2112, 'recommend', 121);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2112, 'recommend', 122);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2112, 'recommend', 123);
|
||||
|
||||
UPDATE `zt_privlang` SET `value` = '创建维护立项' WHERE `objectID` = 638 and `objectType` = 'manager';
|
||||
|
||||
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('charter', 'close', '638', ',ipd,', ',or,', '1', '80');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2113, 'priv', 'de', 'charter-close', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2113, 'priv', 'en', 'charter-close', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2113, 'priv', 'fr', 'charter-close', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2113, 'priv', 'zh-cn', 'charter-close', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2113, 'priv', 'zh-tw', 'charter-close', '', '');
|
||||
|
||||
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('charter', 'activate', '638', ',ipd,', ',or,', '1', '90');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2114, 'priv', 'de', 'charter-activate', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2114, 'priv', 'en', 'charter-activate', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2114, 'priv', 'fr', 'charter-activate', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2114, 'priv', 'zh-cn', 'charter-activate', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2114, 'priv', 'zh-tw', 'charter-activate', '', '');
|
||||
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2113, 'depend', 2061);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2113, 'depend', 2064);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2113, 'recommend', 2062);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2113, 'recommend', 2063);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2113, 'recommend', 2114);
|
||||
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2114, 'depend', 2061);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2114, 'depend', 2064);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2114, 'recommend', 2062);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2114, 'recommend', 2063);
|
||||
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2114, 'recommend', 2113);
|
||||
|
||||
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('requirement', 'relation', '32', ',max,ipd,', ',rnd,', '1', '130');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2115, 'priv', 'de', 'requirement-relation', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2115, 'priv', 'en', 'requirement-relation', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2115, 'priv', 'fr', 'requirement-relation', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2115, 'priv', 'zh-cn', 'requirement-relation', '', '');
|
||||
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2115, 'priv', 'zh-tw', 'requirement-relation', '', '');
|
||||
|
||||
UPDATE `zt_priv` SET `vision` = ',rnd,or,' WHERE `module` = 'user' AND `method` = 'export';
|
||||
UPDATE `zt_priv` SET `vision` = ',rnd,or,' WHERE `module` = 'user' AND `method` = 'exportTemplate';
|
||||
UPDATE `zt_priv` SET `vision` = ',rnd,or,' WHERE `module` = 'user' AND `method` = 'import';
|
||||
UPDATE `zt_priv` SET `vision` = ',rnd,or,' WHERE `module` = 'user' AND `method` = 'importldap';
|
||||
Executable → Regular
+1637
-587
File diff suppressed because one or more lines are too long
+360
-34
@@ -1,3 +1,329 @@
|
||||
2023-08-15 18.6
|
||||
完成的需求
|
||||
开源版:
|
||||
39958 文档按版本记录每个版本下的附件内容
|
||||
46723 新增区域页面中调整复制区域样式的名称
|
||||
31901 产品中设置的评审人默认具备产品访问权限
|
||||
39958 文档按版本记录每个版本下的附件内容
|
||||
44084 文档详情对比后内容区域优化删除和新增的样式
|
||||
46723 新增区域页面中调整复制区域样式的名称
|
||||
42686 版本关联需求时搜索列表中过滤掉草稿、评审中、变更中的需求
|
||||
44726 文档详情中文章内容大纲支持显示所有层级
|
||||
39958 文档按版本记录每个版本下的附件内容
|
||||
42686 版本关联需求时搜索列表中过滤掉草稿、评审中、变更中的需求
|
||||
45887 优化树状图中任务的显示规则
|
||||
46723 新增区域页面中调整复制区域样式的名称
|
||||
30539 数据备份前自动检查空间大小空间不足时给出提示
|
||||
43731 附件增加单独的预览权限
|
||||
45316 创建文档时调整选择模板的方式
|
||||
47076 测试下面的测试单中创建测试报告与执行下面测试单创建测试报告逻辑保持一致
|
||||
47293 升级流程中在执行SQL环节增加进度展示
|
||||
企业版:
|
||||
47188 汇总设置增加提示文案
|
||||
47126 透视表设计器实现汇总设置参数的开关
|
||||
47127 在未勾选汇总设置时实现下一步按钮和流程标签的校验逻辑
|
||||
47130 前台支持切换查看透视表和原始数据
|
||||
47137 前台支持查看未勾选汇总设置的透视表
|
||||
47138 前台支持查看透视表的原始数据
|
||||
47132 老用户未设置报表设计参数的水晶报表时也可以正常升级
|
||||
47137 前台支持查看未勾选汇总设置的透视表
|
||||
47138 前台支持查看透视表的原始数据
|
||||
46528 浏览数据表时可以分页查看数据表
|
||||
旗舰版:
|
||||
47077 调整瀑布项目甘特图中任务计划起止日期的显示规则
|
||||
46637 检查清单中的不符合项不直接影响评审结果
|
||||
46631 地盘待处理区块中标签下无数据时隐藏该标签
|
||||
46630 地盘待处理区块中将审批标签调整到日程后面
|
||||
46629 工时明细表中列表数据超过一屏时底部滚动条置顶显示
|
||||
44213 融合瀑布模型中看板和迭代工时数据参与挣值计算
|
||||
46639 批量创建质量保证计划时可以按过程内容默认填充所有活动、文档
|
||||
46636 评审问题列表中增加搜索功能
|
||||
46626 不符合项列表增加搜索功能
|
||||
46625 质量保证计划列表增加搜索功能
|
||||
修复的Bug
|
||||
开源版:
|
||||
36686 产品下创建非激活状态需求没有记录动态和历史记录
|
||||
36654 升级后产品需求的数据不正确
|
||||
36958 修改需求的所属产品异常
|
||||
36954 任务起止时间设置必填不生效
|
||||
36722 升级18.5系列版本,出现一致性检查需要手动执行SQL
|
||||
36910 更新燃尽图计算有误
|
||||
36959 禅道项目空间提研发需求提示【所属计划】不能为空
|
||||
35520 无产品无迭代项目用户需求列表点击SR处数字提示无权限
|
||||
35526 无产品无迭代项目研发需求列表切换为看板视图后无法再切换到用户需求
|
||||
36945 全局搜索无迭代项目下任务,点击没有跳转项目标签
|
||||
36055 通用看板模块的“泳道高度”设置“自定义”后卡片展示没有按照高度变化来呈现
|
||||
36102 mysql8下文档仪表盘下的产品文档区块sql报错
|
||||
36961 评审用例时选了了多人,用例列表中显示用户名,不显示姓名
|
||||
36074 附件下载链接带sid信息
|
||||
36826 执行的工时重复统计了父子任务的工时
|
||||
37048 后台文档模板中编辑模板的字段显示的是“创建模板”
|
||||
36981 无产品无迭代项目下文档详情页1.5级导航丢失
|
||||
36916 链接类型的文档升级后链接没有渲染出来
|
||||
35404 系统权限保存速度太慢
|
||||
35786 无产品的融合敏捷项目下的看板,批量提需求后,页面未刷新
|
||||
36405 创建产品页面选择项目集或删除项目集后产品线控件处加载2次
|
||||
37052 【性能】权限保存20s+
|
||||
25993 scrum看板任务看板按需分组切换排序条件卡片渲染不出来
|
||||
37122 在地盘仪表盘移动【我的待处理】区块,进入审批中的onlybody超链接,跳转到了页面而不是弹窗
|
||||
37046 多分支产品下提研发需求页面的“用户需求”无法正常加载
|
||||
35381 【4.4alpha1】无迭代项目需求分解任务慢
|
||||
26408 gogs服务器用户1千人时,进入绑定用户页面无加载信息
|
||||
27044 项目集下项目过多时,页面反应慢
|
||||
37084 18.5版本用例数据较多时,页面卡顿
|
||||
37243 多分支产品创建研发需求,用户需求没有根据分支联动
|
||||
37241 所有分支下创建研发需求,显示所有的用户需求
|
||||
37045 研发看板卡片拖动排序后刷新页面排序不成功
|
||||
34331 维护部门时,页面样式不正确
|
||||
37230 二次开发数据字典中左侧目录树无法正常展示
|
||||
企业版:
|
||||
36779 Bug类型统计表表头类型显示的不是中文
|
||||
36857 透视表下的项目Bug类型统计表中类型显示为了键名
|
||||
36920 BI下导出按钮失效
|
||||
36626 登录有代码报错
|
||||
旗舰版:
|
||||
34960 文档链接复制后在新页签中打开报错
|
||||
36453 linux一键安装包瀑布项目评审保存结果有报错
|
||||
33583 瀑布项目甘特图中阶段显示的计划开始、结束时间不正确
|
||||
36465 工作流开启审批流后进行评审时不发送webhook应用通知
|
||||
36115 私有产品可访问权限,增加项目所属项目集干系人
|
||||
35661 【调整优化】达梦数据库版本的禅道升级时,数据库备份页面需优化
|
||||
36051 地盘仪表盘中未完成的项目统计瀑布项目进度没有跟随周报进度
|
||||
37040 新增工作流字段后项目阶段测试用例搜索异常
|
||||
35828 状态为“已入库”的数据依然可以进行批量审批
|
||||
37235 里程碑报告中开始周数和结束周数不正确
|
||||
|
||||
2023-07-27 ipd1.0
|
||||
完成的需求
|
||||
42981 实现需求的导入功能
|
||||
42982 实现导出需求模板功能
|
||||
42983 实现导出需求数据功能
|
||||
43034 在需求列表的右上角打印导入导出按钮
|
||||
43407 实现关闭路标功能
|
||||
43408 实现删除路标功能
|
||||
43413 实现在路标用户需求列表的批量操作按钮组中打印路标菜单
|
||||
43414 实现在路标的用户需求列表中批量移除用户需求功能
|
||||
43415 实现在路标的用户需求列表中批量编辑用户需求功能
|
||||
43416 实现在路标的用户需求列表中批量调整所属路标功能
|
||||
43432 实现激活路标功能
|
||||
43511 实现将产品用户需求批量关联到路标中
|
||||
43974 实现关闭立项申请功能
|
||||
44225 实现激活立项申请功能
|
||||
44913 甘特图中可以修改评审点的截止日期
|
||||
44914 阶段列表中可以修改评审点的截止日期
|
||||
45138 根据关联的产品用户需求判断需求池需求的状态
|
||||
46700 一级导航中菜单名称与图标上下居中对齐显示
|
||||
46708 产品中提交需求保存后返回到全部列表
|
||||
46709 需求池中提交需求保存后返回到全部列表
|
||||
46710 产品提需求页面中BSA字段增加解释信息
|
||||
47058 地盘使用帮助中界面切换增加需求与市场管理界面
|
||||
47289 实现从禅道其他版本升级到IPD版本功能
|
||||
47395 用户需求详情页面增加所属路标字段
|
||||
修复的Bug
|
||||
35072 发起评审,相关文档内容及顺序显示错误
|
||||
35191 OR界面下导出的产品字段与页面不一致
|
||||
35252 英法德语下提交立项页面的类型显示不全
|
||||
35253 分发需求可以选择所有状态的路标
|
||||
35262 评审点都通过了,子阶段也都关闭了,但是父阶段仍是进行中的状态
|
||||
35312 将路标与立项解除关联,路标状态未改变
|
||||
35333 编辑需求所属产品下拉菜单宽度没有限制
|
||||
35418 研发用户到达授权人数,提示信息不准确
|
||||
35422 甘特图列表中可以点父级阶段进入阶段中
|
||||
35438 评审点计划完成时间显示错误
|
||||
35471 Windows新版一键安装包,系统右下角没有隐藏升级按钮
|
||||
35472 地盘-仪表盘中界面切换隐藏
|
||||
35473 OR界面点击仪表盘最新动态更多跳转到了组织动态页面
|
||||
35480 需求列表中细分需求的按钮与用户需求按钮不对齐
|
||||
35485 编辑需求页面所属产品下拉样式错误
|
||||
35490 阶段列表中评审点评审完成后还高亮评审按钮
|
||||
35493 多分支产品,研发需求无法关联到用户需求
|
||||
35523 运用管理界面中反馈办公工作流没有权限包
|
||||
36122 权限包信息显示不完整
|
||||
36477 OR界面产品列表中代码报错
|
||||
36479 激活立项后立项的状态显示成了英文
|
||||
36480 OR界面产品列表页代码报错
|
||||
36497 批量移除路标的用户需求,点击取消后移除按钮变白了
|
||||
36522 立项关闭后列表和详细页显示closed
|
||||
36533 阶段列表页草稿状态的评审点没有显示编辑按钮
|
||||
36536 阶段列表中编辑按钮只有icon部分可以点
|
||||
36551 英文下激活立项弹窗中没有显示提示文案
|
||||
36623 在路标的用户需求列表批量指派需求提示没有研发需求批量指派权限
|
||||
36624 甘特图中计划完成的编辑按钮可触范围与按钮大小不匹配
|
||||
36625 分支下的用户需求批量关联路标时列出了主干的路标
|
||||
36638 IPD界面产品路标下访问用户需求详情页提示访问对象不存在
|
||||
36645 批量编辑阶段更改状态可无视阶段进度
|
||||
36660 超级管理员在IPD界面项目用户需求列表中无法全选
|
||||
36672 15.3升级ipd1.0后,admin用户默认没有需求与管理界面的权限
|
||||
36677 IPD1.0.beta1升级到IPD1.0.stable版本删除文件后有报错
|
||||
36678 IPD界面下全局搜索项目集后进入项目集下可访问人员有代码报错
|
||||
36684 需求池导入需求,没有带入指派给和类别
|
||||
36687 需求池草稿需求提交评审提示502
|
||||
36689 修改评审点计划完成计划时间翻页时,控件位置移动到了左上角
|
||||
36696 OR界面添加产品区块报错
|
||||
36697 OR界面区块,没有统计未关闭产品信息
|
||||
36706 超级管理员在IPD项目用户需求列表页无法全选
|
||||
36707 超级管理员在IPD项目的用户需求列表页时,二级导航高亮了两个
|
||||
36710 分批次创建的阶段,会默认从最新添加的阶段开始
|
||||
36711 需求的指派给和最后修改时间应显示为空
|
||||
36712 地盘待处理不显示待我评审的用户需求
|
||||
36713 max4.5轻量模式升级到IPD1.0不是全生命周期模式
|
||||
36714 max4.0升级到ipd1.0,OR界面产品列表页代码报错
|
||||
36715 升级至ipd版本,用户需求应该默认开启
|
||||
36716 max4.0升级到ipd1.0后,无法创建IPD类型的项目
|
||||
36717 升级成功后超级管理员维护“需求与市场管理界面”权限保存后界面和内容不对应
|
||||
36718 关闭路标选择关闭原因后点保存控制台有报错
|
||||
36719 给admin OR界面权限后,界面显示错误
|
||||
36720 升级后OR界面没有默认权限分组
|
||||
36721 biz8.5升级ipd1.0,普通用户在OR界面看不到
|
||||
36726 需求池下导入权限有多余
|
||||
36728 需求池导入需求时提示需求名称不符合
|
||||
36740 批量编辑产品下用户需求可以将非激活状态需求编辑到路标下
|
||||
36741 升级后开启用户需求后二级导航同时高亮了用户需求和研发需求
|
||||
36743 18.4升ipd1.0,BI显示开源版的引导弹窗
|
||||
36744 路标关联了非激活状态的需求后,解除关联,需求状态变为了激活
|
||||
36745 没有打开用户需求功能的IPD界面,点击路标的需求列表的用户需求超链接二级导航没有高亮
|
||||
36747 路标中批量操作按钮应该隐藏评审按钮
|
||||
36748 IPD项目下编辑阶段页面选择父阶段后提示信息中显示undefined
|
||||
36749 biz4.1.3升级到ipd1.0.授权没替换成功
|
||||
36750 IPD界面学堂从云端导入课程,发送邮件内容有误
|
||||
36753 路标关联需求点击搜索搜索不到内容
|
||||
36760 1.0beta1升级到1.0stable版本后IPD项目下可以创建多套阶段
|
||||
36765 ipd项目创建评审,评审文档错误
|
||||
36766 创建文档保存后会保存两个文档
|
||||
36767 评审页面报错
|
||||
36771 IPD研发项目下打基线页面三级导航缺失
|
||||
36772 提交评审时选择一个以上文档,在评审页面文档内容为空
|
||||
36786 工单转研发需求选择来源后有代码报错
|
||||
36795 IPD界面创建的产品,在OR界面批量编辑后变成了已关闭状态
|
||||
36800 研发需求提交评审变成了页面
|
||||
36810 项目集列表页IPD项目前未显示复选框
|
||||
36831 瀑布/融合瀑布项目下的配置菜单没有了
|
||||
36858 OR界面产品总览区块统计数据不正确
|
||||
|
||||
2023-07-05 18.5
|
||||
完成的需求
|
||||
开源版:
|
||||
45633 优化产品模块中用户需求列表性能
|
||||
45632 优化产品模块中研发需求列表性能
|
||||
45630 优化项目列表性能
|
||||
45256 版本数据过多影响bug编辑页面加载速度
|
||||
企业版:
|
||||
46105 从云端导入课程完成后给用户邮件通知
|
||||
45927 后台BI权限实现数据表的导出权限
|
||||
45924 数据表浏览页面实现导出功能
|
||||
45498 学堂导入课程默认为上线状态
|
||||
45497 学堂后台课程列表中增加默认引导语
|
||||
45496 私有部署禅道实现从云端导入课程功能
|
||||
45268 项目型项目支持反馈功能
|
||||
44991 yaml课程打包工具支持打包PDF文件
|
||||
44918 调整授权到期规则,授权到期前30天在登录页面给用户提示
|
||||
43764 学堂后台课程列表中打印从云端导入按钮
|
||||
40829 学堂播放器支持PDF文件播放功能
|
||||
修复的Bug
|
||||
开源版:
|
||||
36161 运营界面点击任务默认跳转到看板视图
|
||||
36142 产品列表中需求完成率计算不对
|
||||
企业版:
|
||||
36057 透视表前台筛选条件能不正常查询
|
||||
36218 scrum项目型项目反馈转需求,点击反馈详情页历史记录的超链接报错
|
||||
禅道客户端:
|
||||
13775 成员被踢出讨论组后,还停留在讨论组会话页面
|
||||
15925 内网喧喧有新消息时不提醒
|
||||
16398 iOS端音视频会议没有声音
|
||||
16720 喧喧聊天窗口中的聊天记录的滚动条体验需要增强
|
||||
16806 跳转到某个比较老的消息后,会话列表消息中间会缺失一段范围
|
||||
17240 移动端登录后未读消息的情况与桌面端未读情况不一致
|
||||
17617 喧喧后台运行时再次打开喧喧有用户正在会议中实际没有在进行会议
|
||||
20444 右击复制聊天窗口收到的图片执行失败
|
||||
21380 喧喧文件查看卡白
|
||||
21533 设置白名单弹窗宽度过大且文字不居中
|
||||
21587 移动端收到的新消息少了一条
|
||||
21602 消息记录中存在搜索不到消息的情况
|
||||
21610 偶发新的消息只在左侧消息栏中部分显示
|
||||
21782 部门结构和按钮样式不统一
|
||||
21864 应用标签的前后按钮和窗口操作项重叠
|
||||
22053 从聊天列表中移除自己多次才可以生效
|
||||
22176 群合并人员退出群组白名单展示不对
|
||||
23356 消息记录搜索后无法收起下拉框
|
||||
26134 群管理员不能移除用户
|
||||
26215 6.2版本群设置白名单成员不成功
|
||||
27093 群组重命名后名字没有刷新
|
||||
27329 讨论组消息记录窗口白屏
|
||||
28232 打开固定到左侧边栏的应用时“一口X”会遮挡应用
|
||||
28907 群组归档完取消归档转发之前的消息界面崩溃(偶发)
|
||||
29117 开始会议挂断后一分钟后频繁提示连接超时
|
||||
29145 @成员的时候错误地把在群里的成员标红色
|
||||
29257 分组出现空分组
|
||||
29262 群管理--搜索的时候下方出现横线
|
||||
29391 低版本的xxc小喧喧提示小喧喧头像展示需优化
|
||||
29392 打开小喧喧对话框,发送指令,小喧喧的头像和名称展示有误
|
||||
29393 小喧喧头像展示不对
|
||||
29394 进入授权信息bot输入指令提示指令不存在
|
||||
29395 讨论组右上角下拉菜单出现横线
|
||||
29480 禅道客户端--小喧喧会话进入内置应用退出不了
|
||||
30293 两个用户同时退出讨论组点击两次才可以完全退出
|
||||
30738 小喧喧提醒左侧消息栏不展示该条信息
|
||||
31173 查看小喧喧消息记录提示获取消息记录失败
|
||||
31185 非admin账号私人会话协作文档入口没有了
|
||||
31340 会议共享屏幕非常模糊
|
||||
31590 freemind预览,没有展示图标
|
||||
31593 freemind预览中,文字颜色与原文件不一致
|
||||
32612 7.1版本喧喧用户点击查看图片放大、缩小按钮置灰不能点击
|
||||
32661 喧喧客户端登录内网,会话界面报错
|
||||
32808 讨论组成员列表群主右键踢人弹窗不展示有报错。
|
||||
32855 云端同步的数据量大的时候,喧喧客户端会卡顿,点击取消同步无响应
|
||||
33105 客户端7.1发着送信息过程中掉线了点重新发送提示需优化
|
||||
36060 文件应用,只显示了一个image.png
|
||||
|
||||
2023-06-14 18.4
|
||||
修复的Bug
|
||||
开源版:
|
||||
34705 pms升级到biz6.5过程报错
|
||||
35836 项目迭代页面有报错
|
||||
34720 后台聊天首页有代码报错
|
||||
35775 发布详情页点击右上角导出HTML控制台有很多报错
|
||||
企业版:
|
||||
35845 达梦数据库工作流中删除新增的流程失败
|
||||
35730 组织-日志汇总表按照上级部门统计显示没有数据
|
||||
35659 达梦数据库安装企业版8.4写入my.php完成后跳转到了upgrade.php
|
||||
35622 导入工单后联系人字段显示不正确
|
||||
34756 运营管理界面,创建工作流报错
|
||||
34716 工作流新增字段报错
|
||||
34656 【达梦】创建工作流报错
|
||||
34051 【按版本升级即可】同步代码缺少文件,打开浏览代码导致服务502
|
||||
35827 老版本水晶报表SQL查询中使用了左右连接的,升级后会报错
|
||||
35824 达梦数据库内置工作流添加字段/动作保存时报错
|
||||
35820 业务界面创建工作流保存时报错
|
||||
35758 biz4.1.3升级到biz8.4.beta1,反馈转研发需求报错
|
||||
35729 升级成功后没插入原内置的水晶报表
|
||||
35726 达梦数据库添加数据源sql报错
|
||||
35718 达梦数据库全文检索sql报错
|
||||
35700 达梦数据库,多平台产品,点击产品->矩阵导航,sql异常
|
||||
34819 达梦安装方式,透视表下不显示检索标签
|
||||
34610 创建上线计划有SQL报错
|
||||
30371 添加中间表所属分组的下拉菜单遮挡
|
||||
35852 达梦下BI透视表页面报错
|
||||
35724 达梦数据库 产品Bug类型统计表代码报错
|
||||
35722 达梦数据库透视表下的产品/项目/测试/组织下的内置透视表报错
|
||||
34920 大屏页面sql报错
|
||||
34930 产品Bug类型统计表有代码报错
|
||||
34931 透视表项目下有SQL报错
|
||||
34932 透视表组织下有SQL报错
|
||||
35854 反馈设置页面有报错
|
||||
35858 没有产品访问权限时无法提交反馈
|
||||
旗舰版:
|
||||
35829 英文语言下项目中问题列表有报错
|
||||
35748 biz5.3.1升级到max4.4beta1过程中代码报错
|
||||
35715 从其他软件点击禅道链接,可以看到本不能看到的内容
|
||||
34732 后台功能配置的创建度量数据页面有报错
|
||||
35559 升级时处理自定义水晶报表报错
|
||||
35554 无产品项目下研发需求从需求库导入页面二级导航下拉高亮不对
|
||||
34410 mysql慢日志反馈
|
||||
33930 产品计划列表有代码报错
|
||||
33391 选择审批人后提示保存成功,但是还提示数据未找到
|
||||
33171 反馈转风险类型的待办页面关联不到待办名称
|
||||
27055 后台文档模板中设置了文档目录无法使用
|
||||
|
||||
2023-05-31 18.4.beta1
|
||||
完成的需求
|
||||
开源版:
|
||||
@@ -3568,29 +3894,29 @@
|
||||
|
||||
2021-12-06 16.0.beat1
|
||||
完成的需求
|
||||
14005 能够按照平台分支浏览用户需求
|
||||
14005 能够按照平台分支浏览用户需求
|
||||
14429 父需求支持变更
|
||||
14761 选择某一个分支之后点击其他菜单希望能够保持分支下拉菜单状态
|
||||
14771 启用多分支功能后增加分支字样显示的控制
|
||||
14772 需求修改所属分支时如果有冲突给出提示
|
||||
14778 分支设置默认分支功能
|
||||
14877 根据分支提示上次版本计划名称
|
||||
14761 选择某一个分支之后点击其他菜单希望能够保持分支下拉菜单状态
|
||||
14771 启用多分支功能后增加分支字样显示的控制
|
||||
14772 需求修改所属分支时如果有冲突给出提示
|
||||
14778 分支设置默认分支功能
|
||||
14877 根据分支提示上次版本计划名称
|
||||
15134 员工负载表增加备注说明
|
||||
15470 看板可以设置一个单元格里面卡片的排列方式
|
||||
15478 我的地盘bug列表增加确认字段
|
||||
25665 梳理项目和执行关联产品分支的逻辑
|
||||
25666 可以将某一个分支关闭
|
||||
25667 将所有分支概念改为主干并处理历史数据
|
||||
25670 多分支产品浏览需求的时候将所有和主干区分开
|
||||
25673 分支增加排序功能
|
||||
15478 我的地盘bug列表增加确认字段
|
||||
25665 梳理项目和执行关联产品分支的逻辑
|
||||
25666 可以将某一个分支关闭
|
||||
25667 将所有分支概念改为主干并处理历史数据
|
||||
25670 多分支产品浏览需求的时候将所有和主干区分开
|
||||
25673 分支增加排序功能
|
||||
27484 文档库右侧目录增加文件的浮动操作菜单
|
||||
27485 文档库右侧目录增加目录的浮动操作菜单
|
||||
27486 wiki目录中,当鼠标悬浮到文章名称时展示文章快捷操作
|
||||
27487 wiki目录中,鼠标悬浮到具体章节时展示章节的快捷操作
|
||||
27927 执行看板默认只显示一屏滚动时再往下加载
|
||||
28098 需求批量转任务时对已经转换过任务的需求进行提示
|
||||
28131 待处理任务列表中子任务名称前显示父任务
|
||||
28138 员工负载表中增加项目名称信息
|
||||
28098 需求批量转任务时对已经转换过任务的需求进行提示
|
||||
28131 待处理任务列表中子任务名称前显示父任务
|
||||
28138 员工负载表中增加项目名称信息
|
||||
28147 统计列表中具备横向滚动条的列表可以直接展示出来
|
||||
28153 Bug创建表中优化执行查询条件
|
||||
28235 关闭项目时增加实际完成日期的记录
|
||||
@@ -3599,9 +3925,9 @@
|
||||
28238 关闭执行时增加实际完成日期的记录
|
||||
28239 执行工时统计中增加实际开始和实际完成的信息
|
||||
28310 未开始的项目
|
||||
28466 测试Bug列表中增加按所属项目的搜索条件
|
||||
28509 项目概况中增加项目代号的显示
|
||||
28510 项目列表中增加项目代号字段显示
|
||||
28466 测试Bug列表中增加按所属项目的搜索条件
|
||||
28509 项目概况中增加项目代号的显示
|
||||
28510 项目列表中增加项目代号字段显示
|
||||
28719 项目看板中看板列显示数量汇总
|
||||
28727 计划创建迭代时选择项目点击下一步后自动关闭选择弹窗
|
||||
28809 执行看板中进行中项目排序规则调整
|
||||
@@ -3616,29 +3942,29 @@
|
||||
28816 产品看板中调整项目集和产品的排序规则
|
||||
28817 项目集看板中调整项目集和产品的排序规则
|
||||
28818 项目集看板中看板列显示数量汇总
|
||||
28819 调整项目集/产品/项目/执行重名规则
|
||||
28833 创建执行页面可以直接维护相关负责人信息
|
||||
28819 调整项目集/产品/项目/执行重名规则
|
||||
28833 创建执行页面可以直接维护相关负责人信息
|
||||
28834 项目的分组权限中移除无用的模块和方法
|
||||
28835 关联多个产品的项目也可以选择归并方式
|
||||
28904 优化项目列表“我参与的”筛选结果 结
|
||||
28928 可以设置哪些人不需要提醒
|
||||
28929 编辑bug修改状态时如果未修改成功希望有错误提示
|
||||
28931 调整分支管理功能
|
||||
28932 实现分支的批量操作
|
||||
28941 重新登陆系统后产品下拉菜单应当保持上次选中的产品名称
|
||||
28931 调整分支管理功能
|
||||
28932 实现分支的批量操作
|
||||
28941 重新登陆系统后产品下拉菜单应当保持上次选中的产品名称
|
||||
28944 在开源版中增加瀑布模型的相关功能
|
||||
28959 老版本升级新版本数据归并的时候,可以修改项目、执行名称。
|
||||
28960 调整产品列表页面的宽度展示比例
|
||||
28965 实现分支的新增/编辑操作
|
||||
28965 实现分支的新增/编辑操作
|
||||
28970 需求列表批量选中希望可以通过shift快捷键操作
|
||||
28972 产品列表左侧的模块设置调整为显示设置
|
||||
28973 提交Bug时分支与影响版本要跟着联动
|
||||
28974 产品列表批量调整计划时在计划名称前显示分支信息
|
||||
28972 产品列表左侧的模块设置调整为显示设置
|
||||
28973 提交Bug时分支与影响版本要跟着联动
|
||||
28974 产品列表批量调整计划时在计划名称前显示分支信息
|
||||
28993 创建或者编辑用例时调整所属需求的查询逻辑
|
||||
29000 产品列表中调整字段显示宽度
|
||||
29002 动态支持按正序/倒序切换排序
|
||||
29030 已挂起的项目/执行下面的任务不在待办/待处理的任务中展示
|
||||
29059 多分支产品批量创建需求时分支字段设为默认项
|
||||
29059 多分支产品批量创建需求时分支字段设为默认项
|
||||
29069 组织团队成员任务列表增加优先级排序功能
|
||||
29074 用户下拉菜单中增加人员的头像/部门/职位信息
|
||||
29108 提交/编辑软件需求页面中增加反馈者和通知邮箱信息
|
||||
@@ -3647,12 +3973,12 @@
|
||||
29127 计划的Bug列表中增加批量编辑和调整计划功能
|
||||
29131 产品概况中增加评审人员的设置
|
||||
29134 看板页面的刷新不要抖动用更加平滑的方式呈现
|
||||
29141 启用多分支功能后要用例增加分支字样显示的控制
|
||||
29142 启用多分支功能后要Bug增加分支字样显示的控制
|
||||
29143 批量创建需求/BUG/用例时所属模块选择同上,需要检测上一行数据的所属分支和当前行的所属分支是否一致
|
||||
29144 所有分支下批量编辑需求/BUG/用例,所属模块数据默认为所有分支的模块时,需要处理分支与模块不一致的问题
|
||||
29145 项目和执行关联了产品的多个分支及计划时调整概况页面显示方式
|
||||
29147 产品下软件需求列表需求名称前显示主干的分支名
|
||||
29141 启用多分支功能后要用例增加分支字样显示的控制
|
||||
29142 启用多分支功能后要Bug增加分支字样显示的控制
|
||||
29143 批量创建需求/BUG/用例时所属模块选择同上,需要检测上一行数据的所属分支和当前行的所属分支是否一致
|
||||
29144 所有分支下批量编辑需求/BUG/用例,所属模块数据默认为所有分支的模块时,需要处理分支与模块不一致的问题
|
||||
29145 项目和执行关联了产品的多个分支及计划时调整概况页面显示方式
|
||||
29147 产品下软件需求列表需求名称前显示主干的分支名
|
||||
29156 启用多分支功能后项目需求列表增加是否显示分支名
|
||||
29157 启用多分支功能后执行需求列表增加是否显示分支名
|
||||
29158 启用多分支功能后执行任务列表增加是否显示分支名
|
||||
|
||||
@@ -963,7 +963,7 @@ $lang->resource->projectreview = new stdclass();
|
||||
$lang->resource->projecttrack = new stdclass();
|
||||
$lang->resource->projectqa = new stdclass();
|
||||
|
||||
if($config->edition == 'biz' or $config->edition == 'max')
|
||||
if($config->edition != 'open')
|
||||
{
|
||||
/* My module. */
|
||||
$lang->resource->my->effort = 'effort'; // pro effort
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<?php
|
||||
public function getExecutionStoryPairs($executionID = 0, $productID = 0, $branch = 'all', $moduleIdList = 0, $type = 'full', $status = 'all')
|
||||
public function getExecutionStoryPairs($executionID = 0, $productID = 0, $branch = 'all', $moduleIdList = 0, $type = 'full', $status = 'all', $storyType = 'story')
|
||||
{
|
||||
if($this->config->vision == 'lite')
|
||||
{
|
||||
$execution = $this->loadModel('execution')->getById($executionID);
|
||||
if($execution->project) $executionID = $execution->project;
|
||||
}
|
||||
return parent::getExecutionStoryPairs($executionID, $productID, $branch, $moduleIdList, $type, $status);
|
||||
|
||||
return parent::getExecutionStoryPairs($executionID, $productID, $branch, $moduleIdList, $type, $status, $storyType);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
$lang->SRCommon = 'Requirement';
|
||||
$lang->demandpool = new stdclass();
|
||||
$lang->demandpool->common = 'RM Hub';
|
||||
|
||||
$lang->demand = new stdclass();
|
||||
$lang->demand->common = 'Demand';
|
||||
|
||||
$lang->charter = new stdclass();
|
||||
$lang->charter->common = 'Charter';
|
||||
|
||||
$lang->navIcons['demandpool'] = "<i class='icon icon-bars'></i>";
|
||||
|
||||
/* Main Navigation. */
|
||||
$lang->mainNav = new stdclass();
|
||||
$lang->mainNav->my = "{$lang->navIcons['my']} {$lang->my->shortCommon}|my|index|";
|
||||
$lang->mainNav->demandpool = "{$lang->navIcons['demandpool']} {$lang->demandpool->common}|demandpool|browse|";
|
||||
$lang->mainNav->product = "{$lang->navIcons['product']} {$lang->productCommon}|product|all|";
|
||||
$lang->mainNav->charter = "{$lang->navIcons['project']} {$lang->charter->common}|charter|browse|";
|
||||
$lang->mainNav->doc = "{$lang->navIcons['doc']} {$lang->doc->common}|doc|index|";
|
||||
$lang->mainNav->admin = "{$lang->navIcons['admin']} {$lang->admin->common}|admin|index|";
|
||||
|
||||
//if($config->edition != 'open')
|
||||
//{
|
||||
// $lang->navIcons['feedback'] = "<i class='icon icon-feedback'></i>";
|
||||
//
|
||||
// $lang->mainNav->feedback = $lang->navIcons['feedback'] . 'Feedback|feedback|browse|browseType=unclosed';
|
||||
//
|
||||
// if($config->visions == ',lite,') unset($lang->mainNav->feedback);
|
||||
//}
|
||||
|
||||
$lang->mainNav->menuOrder[5] = 'my';
|
||||
$lang->mainNav->menuOrder[10] = 'demandpool';
|
||||
$lang->mainNav->menuOrder[15] = 'product';
|
||||
$lang->mainNav->menuOrder[20] = 'charter';
|
||||
//$lang->mainNav->menuOrder[25] = 'feedback';
|
||||
$lang->mainNav->menuOrder[30] = 'doc';
|
||||
$lang->mainNav->menuOrder[35] = 'admin';
|
||||
|
||||
$lang->navGroup->demandpool = 'demandpool';
|
||||
$lang->navGroup->demand = 'demandpool';
|
||||
$lang->navGroup->roadmap = 'product';
|
||||
$lang->navGroup->charter = 'charter';
|
||||
|
||||
$lang->demandpool->menu = new stdclass();
|
||||
$lang->demandpool->menu->browse = array('link' => "{$lang->demand->common}|demand|browse|poolID=%s", 'alias' => 'create,batchcreate,edit,managetree,view,tostory,showimport,review,change');
|
||||
//$lang->demandpool->menu->review = array('link' => "Review|demand|review|poolID=%s");
|
||||
//$lang->demandpool->menu->kanban = array('link' => "Kanban|demand|kanban|poolID=%s");
|
||||
//$lang->demandpool->menu->track = array('link' => "Track|demand|track|demandID=%s");
|
||||
//$lang->demandpool->menu->insight = array('link' => "Insight|demand|insight|demandID=%s");
|
||||
$lang->demandpool->menu->view = array('link' => "View|demandpool|view|poolID=%s", 'alias' => 'edit');
|
||||
|
||||
$lang->demandpool->menuOrder[5] = 'browse';
|
||||
$lang->demandpool->menuOrder[10] = 'review';
|
||||
$lang->demandpool->menuOrder[15] = 'kanban';
|
||||
$lang->demandpool->menuOrder[20] = 'track';
|
||||
$lang->demandpool->menuOrder[25] = 'insight';
|
||||
$lang->demandpool->menuOrder[30] = 'view';
|
||||
|
||||
$lang->product->menu = new stdclass();
|
||||
$lang->product->menu->requirement = array('link' => "Requirement|product|browse|productID=%s&branch=&browseType=assignedtome¶m=0&storyType=requirement", 'alias' => 'batchedit', 'subModule' => 'story');
|
||||
$lang->product->menu->roadmap = array('link' => "Roadmap|roadmap|browse|productID=%s");
|
||||
#$lang->product->menu->initiating = array('link' => "Initiating|product|initiating|productID=%s");
|
||||
$lang->product->menu->settings = array('link' => "{$lang->settings}|product|view|productID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
|
||||
|
||||
$lang->product->menu->settings['subMenu'] = new stdclass();
|
||||
$lang->product->menu->settings['subMenu']->view = array('link' => "{$lang->overview}|product|view|productID=%s", 'alias' => 'edit');
|
||||
$lang->product->menu->settings['subMenu']->module = array('link' => "{$lang->module}|tree|browse|product=%s&view=story", 'subModule' => 'tree');
|
||||
$lang->product->menu->settings['subMenu']->branch = array('link' => "@branch@|branch|manage|product=%s", 'subModule' => 'branch');
|
||||
$lang->product->menu->settings['subMenu']->whitelist = array('link' => "{$lang->whitelist}|product|whitelist|product=%s", 'subModule' => 'personnel');
|
||||
|
||||
$lang->product->menuOrder = array();
|
||||
$lang->product->menuOrder[5] = 'requirement';
|
||||
$lang->product->menuOrder[10] = 'roadmap';
|
||||
$lang->product->menuOrder[15] = 'initiating';
|
||||
$lang->product->menuOrder[20] = 'settings';
|
||||
|
||||
unset($lang->product->homeMenu->home);
|
||||
unset($lang->product->homeMenu->kanban);
|
||||
|
||||
$lang->charter->menu = new stdclass();
|
||||
$lang->charter->menu->all = array('link' => "All|charter|browse|browseType=all");
|
||||
$lang->charter->menu->wait = array('link' => "Wait|charter|browse|browseType=wait");
|
||||
$lang->charter->menu->launched = array('link' => "Launched|charter|browse|browseType=launched");
|
||||
$lang->charter->menu->failed = array('link' => "Failed|charter|browse|browseType=failed");
|
||||
//$lang->charter->menu->settings = array('link' => "{$lang->settings}|charter|view|charterID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
|
||||
|
||||
unset($lang->my->menu->project);
|
||||
unset($lang->my->menu->execution);
|
||||
unset($lang->my->menu->contribute);
|
||||
unset($lang->my->menu->meeting);
|
||||
unset($lang->doc->menu->project);
|
||||
unset($lang->doc->menu->api);
|
||||
|
||||
$lang->my->menu->work = array('link' => "{$lang->my->work}|my|work|mode=requirement", 'subModule' => 'task');
|
||||
|
||||
$lang->my->menu->work['subMenu'] = new stdclass();
|
||||
$lang->my->menu->work['subMenu']->requirement = "$lang->URCommon|my|work|mode=requirement";
|
||||
|
||||
unset($lang->createIcons['bug']);
|
||||
unset($lang->createIcons['story']);
|
||||
unset($lang->createIcons['task']);
|
||||
unset($lang->createIcons['testcase']);
|
||||
unset($lang->createIcons['program']);
|
||||
unset($lang->createIcons['project']);
|
||||
unset($lang->createIcons['execution']);
|
||||
unset($lang->createIcons['kanbanspace']);
|
||||
unset($lang->createIcons['kanban']);
|
||||
|
||||
$lang->searchObjects = array();
|
||||
$lang->searchObjects['all'] = 'All';
|
||||
$lang->searchObjects['story'] = 'Requirement';
|
||||
$lang->searchObjects['demandpool'] = 'DemandPool';
|
||||
$lang->searchObjects['demand'] = 'Demand';
|
||||
$lang->searchObjects['roadmap'] = 'Roadmap';
|
||||
$lang->searchObjects['charter'] = 'Charter';
|
||||
$lang->searchObjects['product'] = $lang->productCommon;
|
||||
$lang->searchObjects['doc'] = 'Document';
|
||||
$lang->searchTips = 'ID(ctrl+g)';
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
$lang->SRCommon = 'Requirement';
|
||||
$lang->demandpool = new stdclass();
|
||||
$lang->demandpool->common = 'RM Hub';
|
||||
|
||||
$lang->demand = new stdclass();
|
||||
$lang->demand->common = 'Demand';
|
||||
|
||||
$lang->charter = new stdclass();
|
||||
$lang->charter->common = 'Charter';
|
||||
|
||||
$lang->navIcons['demandpool'] = "<i class='icon icon-bars'></i>";
|
||||
|
||||
/* Main Navigation. */
|
||||
$lang->mainNav = new stdclass();
|
||||
$lang->mainNav->my = "{$lang->navIcons['my']} {$lang->my->shortCommon}|my|index|";
|
||||
$lang->mainNav->demandpool = "{$lang->navIcons['demandpool']} {$lang->demandpool->common}|demandpool|browse|";
|
||||
$lang->mainNav->product = "{$lang->navIcons['product']} {$lang->productCommon}|product|all|";
|
||||
$lang->mainNav->charter = "{$lang->navIcons['project']} {$lang->charter->common}|charter|browse|";
|
||||
$lang->mainNav->doc = "{$lang->navIcons['doc']} {$lang->doc->common}|doc|index|";
|
||||
$lang->mainNav->admin = "{$lang->navIcons['admin']} {$lang->admin->common}|admin|index|";
|
||||
|
||||
//if($config->edition != 'open')
|
||||
//{
|
||||
// $lang->navIcons['feedback'] = "<i class='icon icon-feedback'></i>";
|
||||
//
|
||||
// $lang->mainNav->feedback = $lang->navIcons['feedback'] . 'Feedback|feedback|browse|browseType=unclosed';
|
||||
//
|
||||
// if($config->visions == ',lite,') unset($lang->mainNav->feedback);
|
||||
//}
|
||||
|
||||
$lang->mainNav->menuOrder[5] = 'my';
|
||||
$lang->mainNav->menuOrder[10] = 'demandpool';
|
||||
$lang->mainNav->menuOrder[15] = 'product';
|
||||
$lang->mainNav->menuOrder[20] = 'charter';
|
||||
//$lang->mainNav->menuOrder[25] = 'feedback';
|
||||
$lang->mainNav->menuOrder[30] = 'doc';
|
||||
$lang->mainNav->menuOrder[35] = 'admin';
|
||||
|
||||
$lang->navGroup->demandpool = 'demandpool';
|
||||
$lang->navGroup->demand = 'demandpool';
|
||||
$lang->navGroup->roadmap = 'product';
|
||||
$lang->navGroup->charter = 'charter';
|
||||
|
||||
$lang->demandpool->menu = new stdclass();
|
||||
$lang->demandpool->menu->browse = array('link' => "{$lang->demand->common}|demand|browse|poolID=%s", 'alias' => 'create,batchcreate,edit,managetree,view,tostory,showimport,review,change');
|
||||
//$lang->demandpool->menu->review = array('link' => "Review|demand|review|poolID=%s");
|
||||
//$lang->demandpool->menu->kanban = array('link' => "Kanban|demand|kanban|poolID=%s");
|
||||
//$lang->demandpool->menu->track = array('link' => "Track|demand|track|demandID=%s");
|
||||
//$lang->demandpool->menu->insight = array('link' => "Insight|demand|insight|demandID=%s");
|
||||
$lang->demandpool->menu->view = array('link' => "View|demandpool|view|poolID=%s", 'alias' => 'edit');
|
||||
|
||||
$lang->demandpool->menuOrder[5] = 'browse';
|
||||
$lang->demandpool->menuOrder[10] = 'review';
|
||||
$lang->demandpool->menuOrder[15] = 'kanban';
|
||||
$lang->demandpool->menuOrder[20] = 'track';
|
||||
$lang->demandpool->menuOrder[25] = 'insight';
|
||||
$lang->demandpool->menuOrder[30] = 'view';
|
||||
|
||||
$lang->product->menu = new stdclass();
|
||||
$lang->product->menu->requirement = array('link' => "Requirement|product|browse|productID=%s&branch=&browseType=assignedtome¶m=0&storyType=requirement", 'alias' => 'batchedit', 'subModule' => 'story');
|
||||
$lang->product->menu->roadmap = array('link' => "Roadmap|roadmap|browse|productID=%s");
|
||||
#$lang->product->menu->initiating = array('link' => "Initiating|product|initiating|productID=%s");
|
||||
$lang->product->menu->settings = array('link' => "{$lang->settings}|product|view|productID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
|
||||
|
||||
$lang->product->menu->settings['subMenu'] = new stdclass();
|
||||
$lang->product->menu->settings['subMenu']->view = array('link' => "{$lang->overview}|product|view|productID=%s", 'alias' => 'edit');
|
||||
$lang->product->menu->settings['subMenu']->module = array('link' => "{$lang->module}|tree|browse|product=%s&view=story", 'subModule' => 'tree');
|
||||
$lang->product->menu->settings['subMenu']->branch = array('link' => "@branch@|branch|manage|product=%s", 'subModule' => 'branch');
|
||||
$lang->product->menu->settings['subMenu']->whitelist = array('link' => "{$lang->whitelist}|product|whitelist|product=%s", 'subModule' => 'personnel');
|
||||
|
||||
$lang->product->menuOrder = array();
|
||||
$lang->product->menuOrder[5] = 'requirement';
|
||||
$lang->product->menuOrder[10] = 'roadmap';
|
||||
$lang->product->menuOrder[15] = 'initiating';
|
||||
$lang->product->menuOrder[20] = 'settings';
|
||||
|
||||
unset($lang->product->homeMenu->home);
|
||||
unset($lang->product->homeMenu->kanban);
|
||||
|
||||
$lang->charter->menu = new stdclass();
|
||||
$lang->charter->menu->all = array('link' => "All|charter|browse|browseType=all");
|
||||
$lang->charter->menu->wait = array('link' => "Wait|charter|browse|browseType=wait");
|
||||
$lang->charter->menu->launched = array('link' => "Launched|charter|browse|browseType=launched");
|
||||
$lang->charter->menu->failed = array('link' => "Failed|charter|browse|browseType=failed");
|
||||
//$lang->charter->menu->settings = array('link' => "{$lang->settings}|charter|view|charterID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
|
||||
|
||||
unset($lang->my->menu->project);
|
||||
unset($lang->my->menu->execution);
|
||||
unset($lang->my->menu->contribute);
|
||||
unset($lang->my->menu->meeting);
|
||||
unset($lang->doc->menu->project);
|
||||
unset($lang->doc->menu->api);
|
||||
|
||||
$lang->my->menu->work = array('link' => "{$lang->my->work}|my|work|mode=requirement", 'subModule' => 'task');
|
||||
|
||||
$lang->my->menu->work['subMenu'] = new stdclass();
|
||||
$lang->my->menu->work['subMenu']->requirement = "$lang->URCommon|my|work|mode=requirement";
|
||||
|
||||
unset($lang->createIcons['bug']);
|
||||
unset($lang->createIcons['story']);
|
||||
unset($lang->createIcons['task']);
|
||||
unset($lang->createIcons['testcase']);
|
||||
unset($lang->createIcons['program']);
|
||||
unset($lang->createIcons['project']);
|
||||
unset($lang->createIcons['execution']);
|
||||
unset($lang->createIcons['kanbanspace']);
|
||||
unset($lang->createIcons['kanban']);
|
||||
|
||||
$lang->searchObjects = array();
|
||||
$lang->searchObjects['all'] = 'All';
|
||||
$lang->searchObjects['story'] = 'Requirement';
|
||||
$lang->searchObjects['demandpool'] = 'DemandPool';
|
||||
$lang->searchObjects['demand'] = 'Demand';
|
||||
$lang->searchObjects['roadmap'] = 'Roadmap';
|
||||
$lang->searchObjects['charter'] = 'Charter';
|
||||
$lang->searchObjects['product'] = $lang->productCommon;
|
||||
$lang->searchObjects['doc'] = 'Document';
|
||||
$lang->searchTips = 'ID(ctrl+g)';
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
$lang->SRCommon = 'Requirement';
|
||||
$lang->demandpool = new stdclass();
|
||||
$lang->demandpool->common = 'RM Hub';
|
||||
|
||||
$lang->demand = new stdclass();
|
||||
$lang->demand->common = 'Demand';
|
||||
|
||||
$lang->charter = new stdclass();
|
||||
$lang->charter->common = 'Charter';
|
||||
|
||||
$lang->navIcons['demandpool'] = "<i class='icon icon-bars'></i>";
|
||||
|
||||
/* Main Navigation. */
|
||||
$lang->mainNav = new stdclass();
|
||||
$lang->mainNav->my = "{$lang->navIcons['my']} {$lang->my->shortCommon}|my|index|";
|
||||
$lang->mainNav->demandpool = "{$lang->navIcons['demandpool']} {$lang->demandpool->common}|demandpool|browse|";
|
||||
$lang->mainNav->product = "{$lang->navIcons['product']} {$lang->productCommon}|product|all|";
|
||||
$lang->mainNav->charter = "{$lang->navIcons['project']} {$lang->charter->common}|charter|browse|";
|
||||
$lang->mainNav->doc = "{$lang->navIcons['doc']} {$lang->doc->common}|doc|index|";
|
||||
$lang->mainNav->admin = "{$lang->navIcons['admin']} {$lang->admin->common}|admin|index|";
|
||||
|
||||
//if($config->edition != 'open')
|
||||
//{
|
||||
// $lang->navIcons['feedback'] = "<i class='icon icon-feedback'></i>";
|
||||
//
|
||||
// $lang->mainNav->feedback = $lang->navIcons['feedback'] . 'Feedback|feedback|browse|browseType=unclosed';
|
||||
//
|
||||
// if($config->visions == ',lite,') unset($lang->mainNav->feedback);
|
||||
//}
|
||||
|
||||
$lang->mainNav->menuOrder[5] = 'my';
|
||||
$lang->mainNav->menuOrder[10] = 'demandpool';
|
||||
$lang->mainNav->menuOrder[15] = 'product';
|
||||
$lang->mainNav->menuOrder[20] = 'charter';
|
||||
//$lang->mainNav->menuOrder[25] = 'feedback';
|
||||
$lang->mainNav->menuOrder[30] = 'doc';
|
||||
$lang->mainNav->menuOrder[35] = 'admin';
|
||||
|
||||
$lang->navGroup->demandpool = 'demandpool';
|
||||
$lang->navGroup->demand = 'demandpool';
|
||||
$lang->navGroup->roadmap = 'product';
|
||||
$lang->navGroup->charter = 'charter';
|
||||
|
||||
$lang->demandpool->menu = new stdclass();
|
||||
$lang->demandpool->menu->browse = array('link' => "{$lang->demand->common}|demand|browse|poolID=%s", 'alias' => 'create,batchcreate,edit,managetree,view,tostory,showimport,review,change');
|
||||
//$lang->demandpool->menu->review = array('link' => "Review|demand|review|poolID=%s");
|
||||
//$lang->demandpool->menu->kanban = array('link' => "Kanban|demand|kanban|poolID=%s");
|
||||
//$lang->demandpool->menu->track = array('link' => "Track|demand|track|demandID=%s");
|
||||
//$lang->demandpool->menu->insight = array('link' => "Insight|demand|insight|demandID=%s");
|
||||
$lang->demandpool->menu->view = array('link' => "View|demandpool|view|poolID=%s", 'alias' => 'edit');
|
||||
|
||||
$lang->demandpool->menuOrder[5] = 'browse';
|
||||
$lang->demandpool->menuOrder[10] = 'review';
|
||||
$lang->demandpool->menuOrder[15] = 'kanban';
|
||||
$lang->demandpool->menuOrder[20] = 'track';
|
||||
$lang->demandpool->menuOrder[25] = 'insight';
|
||||
$lang->demandpool->menuOrder[30] = 'view';
|
||||
|
||||
$lang->product->menu = new stdclass();
|
||||
$lang->product->menu->requirement = array('link' => "Requirement|product|browse|productID=%s&branch=&browseType=assignedtome¶m=0&storyType=requirement", 'alias' => 'batchedit', 'subModule' => 'story');
|
||||
$lang->product->menu->roadmap = array('link' => "Roadmap|roadmap|browse|productID=%s");
|
||||
#$lang->product->menu->initiating = array('link' => "Initiating|product|initiating|productID=%s");
|
||||
$lang->product->menu->settings = array('link' => "{$lang->settings}|product|view|productID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
|
||||
|
||||
$lang->product->menu->settings['subMenu'] = new stdclass();
|
||||
$lang->product->menu->settings['subMenu']->view = array('link' => "{$lang->overview}|product|view|productID=%s", 'alias' => 'edit');
|
||||
$lang->product->menu->settings['subMenu']->module = array('link' => "{$lang->module}|tree|browse|product=%s&view=story", 'subModule' => 'tree');
|
||||
$lang->product->menu->settings['subMenu']->branch = array('link' => "@branch@|branch|manage|product=%s", 'subModule' => 'branch');
|
||||
$lang->product->menu->settings['subMenu']->whitelist = array('link' => "{$lang->whitelist}|product|whitelist|product=%s", 'subModule' => 'personnel');
|
||||
|
||||
$lang->product->menuOrder = array();
|
||||
$lang->product->menuOrder[5] = 'requirement';
|
||||
$lang->product->menuOrder[10] = 'roadmap';
|
||||
$lang->product->menuOrder[15] = 'initiating';
|
||||
$lang->product->menuOrder[20] = 'settings';
|
||||
|
||||
unset($lang->product->homeMenu->home);
|
||||
unset($lang->product->homeMenu->kanban);
|
||||
|
||||
$lang->charter->menu = new stdclass();
|
||||
$lang->charter->menu->all = array('link' => "All|charter|browse|browseType=all");
|
||||
$lang->charter->menu->wait = array('link' => "Wait|charter|browse|browseType=wait");
|
||||
$lang->charter->menu->launched = array('link' => "Launched|charter|browse|browseType=launched");
|
||||
$lang->charter->menu->failed = array('link' => "Failed|charter|browse|browseType=failed");
|
||||
//$lang->charter->menu->settings = array('link' => "{$lang->settings}|charter|view|charterID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
|
||||
|
||||
unset($lang->my->menu->project);
|
||||
unset($lang->my->menu->execution);
|
||||
unset($lang->my->menu->contribute);
|
||||
unset($lang->my->menu->meeting);
|
||||
unset($lang->doc->menu->project);
|
||||
unset($lang->doc->menu->api);
|
||||
|
||||
$lang->my->menu->work = array('link' => "{$lang->my->work}|my|work|mode=requirement", 'subModule' => 'task');
|
||||
|
||||
$lang->my->menu->work['subMenu'] = new stdclass();
|
||||
$lang->my->menu->work['subMenu']->requirement = "$lang->URCommon|my|work|mode=requirement";
|
||||
|
||||
unset($lang->createIcons['bug']);
|
||||
unset($lang->createIcons['story']);
|
||||
unset($lang->createIcons['task']);
|
||||
unset($lang->createIcons['testcase']);
|
||||
unset($lang->createIcons['program']);
|
||||
unset($lang->createIcons['project']);
|
||||
unset($lang->createIcons['execution']);
|
||||
unset($lang->createIcons['kanbanspace']);
|
||||
unset($lang->createIcons['kanban']);
|
||||
|
||||
$lang->searchObjects = array();
|
||||
$lang->searchObjects['all'] = 'All';
|
||||
$lang->searchObjects['story'] = 'Requirement';
|
||||
$lang->searchObjects['demandpool'] = 'DemandPool';
|
||||
$lang->searchObjects['demand'] = 'Demand';
|
||||
$lang->searchObjects['roadmap'] = 'Roadmap';
|
||||
$lang->searchObjects['charter'] = 'Charter';
|
||||
$lang->searchObjects['product'] = $lang->productCommon;
|
||||
$lang->searchObjects['doc'] = 'Document';
|
||||
$lang->searchTips = 'ID(ctrl+g)';
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
$lang->SRCommon = '用户需求';
|
||||
$lang->demandpool = new stdclass();
|
||||
$lang->demandpool->common = '需求池';
|
||||
|
||||
$lang->demand = new stdclass();
|
||||
$lang->demand->common = '需求';
|
||||
|
||||
$lang->charter = new stdclass();
|
||||
$lang->charter->common = '立项';
|
||||
|
||||
$lang->navIcons['demandpool'] = "<i class='icon icon-bars'></i>";
|
||||
|
||||
/* Main Navigation. */
|
||||
$lang->mainNav = new stdclass();
|
||||
$lang->mainNav->my = "{$lang->navIcons['my']} {$lang->my->shortCommon}|my|index|";
|
||||
$lang->mainNav->demandpool = "{$lang->navIcons['demandpool']} {$lang->demandpool->common}|demandpool|browse|";
|
||||
$lang->mainNav->product = "{$lang->navIcons['product']} {$lang->productCommon}|product|all|";
|
||||
$lang->mainNav->charter = "{$lang->navIcons['project']} {$lang->charter->common}|charter|browse|";
|
||||
$lang->mainNav->doc = "{$lang->navIcons['doc']} {$lang->doc->common}|doc|index|";
|
||||
$lang->mainNav->admin = "{$lang->navIcons['admin']} {$lang->admin->common}|admin|index|";
|
||||
|
||||
//if($config->edition != 'open')
|
||||
//{
|
||||
// $lang->navIcons['feedback'] = "<i class='icon icon-feedback'></i>";
|
||||
//
|
||||
// $lang->mainNav->feedback = $lang->navIcons['feedback'] . '反馈|feedback|browse|browseType=unclosed';
|
||||
//
|
||||
// if($config->visions == ',lite,') unset($lang->mainNav->feedback);
|
||||
//}
|
||||
|
||||
$lang->mainNav->menuOrder[5] = 'my';
|
||||
$lang->mainNav->menuOrder[10] = 'demandpool';
|
||||
$lang->mainNav->menuOrder[15] = 'product';
|
||||
$lang->mainNav->menuOrder[20] = 'charter';
|
||||
//$lang->mainNav->menuOrder[25] = 'feedback';
|
||||
$lang->mainNav->menuOrder[30] = 'doc';
|
||||
$lang->mainNav->menuOrder[35] = 'admin';
|
||||
|
||||
$lang->navGroup->demandpool = 'demandpool';
|
||||
$lang->navGroup->demand = 'demandpool';
|
||||
$lang->navGroup->roadmap = 'product';
|
||||
$lang->navGroup->charter = 'charter';
|
||||
|
||||
$lang->demandpool->menu = new stdclass();
|
||||
$lang->demandpool->menu->browse = array('link' => "{$lang->demand->common}|demand|browse|poolID=%s", 'alias' => 'create,batchcreate,edit,managetree,view,tostory,showimport,review,change');
|
||||
//$lang->demandpool->menu->review = array('link' => "评审|demand|review|poolID=%s");
|
||||
//$lang->demandpool->menu->kanban = array('link' => "看板|demand|kanban|poolID=%s");
|
||||
//$lang->demandpool->menu->track = array('link' => "矩阵图|demand|track|demandID=%s");
|
||||
//$lang->demandpool->menu->insight = array('link' => "洞察|demand|insight|demandID=%s");
|
||||
$lang->demandpool->menu->view = array('link' => "概况|demandpool|view|poolID=%s", 'alias' => 'edit');
|
||||
|
||||
$lang->demandpool->menuOrder[5] = 'browse';
|
||||
$lang->demandpool->menuOrder[10] = 'review';
|
||||
$lang->demandpool->menuOrder[15] = 'kanban';
|
||||
$lang->demandpool->menuOrder[20] = 'track';
|
||||
$lang->demandpool->menuOrder[25] = 'insight';
|
||||
$lang->demandpool->menuOrder[30] = 'view';
|
||||
|
||||
$lang->product->menu = new stdclass();
|
||||
$lang->product->menu->requirement = array('link' => "{$lang->URCommon}|product|browse|productID=%s&branch=&browseType=assignedtome¶m=0&storyType=requirement", 'alias' => 'batchedit', 'subModule' => 'story');
|
||||
$lang->product->menu->roadmap = array('link' => "路标|roadmap|browse|productID=%s");
|
||||
#$lang->product->menu->initiating = array('link' => "立项|product|initiating|productID=%s");
|
||||
$lang->product->menu->settings = array('link' => "{$lang->settings}|product|view|productID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
|
||||
|
||||
$lang->product->menu->settings['subMenu'] = new stdclass();
|
||||
$lang->product->menu->settings['subMenu']->view = array('link' => "{$lang->overview}|product|view|productID=%s", 'alias' => 'edit');
|
||||
$lang->product->menu->settings['subMenu']->module = array('link' => "{$lang->module}|tree|browse|product=%s&view=story", 'subModule' => 'tree');
|
||||
$lang->product->menu->settings['subMenu']->branch = array('link' => "@branch@|branch|manage|product=%s", 'subModule' => 'branch');
|
||||
$lang->product->menu->settings['subMenu']->whitelist = array('link' => "{$lang->whitelist}|product|whitelist|product=%s", 'subModule' => 'personnel');
|
||||
|
||||
$lang->product->menuOrder = array();
|
||||
$lang->product->menuOrder[5] = 'requirement';
|
||||
$lang->product->menuOrder[10] = 'roadmap';
|
||||
$lang->product->menuOrder[15] = 'initiating';
|
||||
$lang->product->menuOrder[20] = 'settings';
|
||||
|
||||
unset($lang->product->homeMenu->home);
|
||||
unset($lang->product->homeMenu->kanban);
|
||||
|
||||
$lang->charter->menu = new stdclass();
|
||||
$lang->charter->menu->all = array('link' => "全部|charter|browse|browseType=all");
|
||||
$lang->charter->menu->wait = array('link' => "待立项|charter|browse|browseType=wait");
|
||||
$lang->charter->menu->launched = array('link' => "已立项|charter|browse|browseType=launched");
|
||||
$lang->charter->menu->failed = array('link' => "未通过|charter|browse|browseType=failed");
|
||||
//$lang->charter->menu->settings = array('link' => "{$lang->settings}|charter|view|charterID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
|
||||
|
||||
unset($lang->my->menu->project);
|
||||
unset($lang->my->menu->execution);
|
||||
unset($lang->my->menu->contribute);
|
||||
unset($lang->my->menu->meeting);
|
||||
unset($lang->doc->menu->project);
|
||||
unset($lang->doc->menu->api);
|
||||
|
||||
$lang->my->menu->work = array('link' => "{$lang->my->work}|my|work|mode=requirement", 'subModule' => 'task');
|
||||
|
||||
$lang->my->menu->work['subMenu'] = new stdclass();
|
||||
$lang->my->menu->work['subMenu']->requirement = "$lang->URCommon|my|work|mode=requirement";
|
||||
|
||||
unset($lang->createIcons['bug']);
|
||||
unset($lang->createIcons['story']);
|
||||
unset($lang->createIcons['task']);
|
||||
unset($lang->createIcons['testcase']);
|
||||
unset($lang->createIcons['program']);
|
||||
unset($lang->createIcons['project']);
|
||||
unset($lang->createIcons['execution']);
|
||||
unset($lang->createIcons['kanbanspace']);
|
||||
unset($lang->createIcons['kanban']);
|
||||
|
||||
$lang->searchObjects = array();
|
||||
$lang->searchObjects['all'] = '全部';
|
||||
$lang->searchObjects['story'] = '需求';
|
||||
$lang->searchObjects['demandpool'] = '需求池';
|
||||
$lang->searchObjects['demand'] = '需求池需求';
|
||||
$lang->searchObjects['roadmap'] = '路标';
|
||||
$lang->searchObjects['charter'] = '立项';
|
||||
$lang->searchObjects['product'] = $lang->productCommon;
|
||||
$lang->searchObjects['doc'] = '文档';
|
||||
$lang->searchTips = '编号(ctrl+g)';
|
||||
@@ -417,7 +417,6 @@ class baseEntry
|
||||
*/
|
||||
public function setPost($key, $value)
|
||||
{
|
||||
if(in_array($key, array('desc', 'spec', 'verify', 'steps'))) $value = htmlspecialchars($value);
|
||||
$_POST[$key] = $value;
|
||||
}
|
||||
|
||||
@@ -476,6 +475,19 @@ class baseEntry
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否在后台启用了代号.
|
||||
* Check whether config->setCode are used in product,project,execution.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function checkCodeUsed()
|
||||
{
|
||||
return isset($this->config->setCode) ? $this->config->setCode : 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 格式化数据的字段类型.
|
||||
* Format fields of response data.
|
||||
|
||||
@@ -279,4 +279,38 @@ class api extends router
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置vision。
|
||||
* set Debug.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setVision()
|
||||
{
|
||||
$account = isset($_SESSION['user']) ? $_SESSION['user']->account : '';
|
||||
if(empty($account) and isset($_POST['account'])) $account = $_POST['account'];
|
||||
if(empty($account) and isset($_GET['account'])) $account = $_GET['account'];
|
||||
|
||||
$vision = 'rnd';
|
||||
if($this->config->installed and validater::checkAccount($account))
|
||||
{
|
||||
$sql = new sql();
|
||||
$account = $sql->quote($account);
|
||||
|
||||
$user = $this->dbh->query("SELECT * FROM " . TABLE_USER . " WHERE account = $account AND deleted = '0' LIMIT 1")->fetch();
|
||||
if(!empty($user->visions))
|
||||
{
|
||||
$userVisions = explode(',', $user->visions);
|
||||
if(!in_array($vision, $userVisions)) $vision = '';
|
||||
if(empty($vision)) list($vision) = $userVisions;
|
||||
}
|
||||
}
|
||||
|
||||
list($defaultVision) = explode(',', trim($this->config->visions, ','));
|
||||
if($vision and strpos($this->config->visions, ",{$vision},") === false) $vision = $defaultVision;
|
||||
|
||||
$this->config->vision = $vision ? $vision : $defaultVision;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -955,6 +955,7 @@ class baseControl
|
||||
for($i = 0; $i < $obLevel; $i++) ob_end_clean();
|
||||
|
||||
$response = helper::removeUTF8Bom(urldecode(json_encode($data)));
|
||||
$this->app->outputXhprof();
|
||||
die($response);
|
||||
}
|
||||
|
||||
|
||||
@@ -255,6 +255,7 @@ class baseHelper
|
||||
return "IN ('" . join("','", $idList) . "')";
|
||||
}
|
||||
|
||||
if(is_null($idList)) $idList = '';
|
||||
if(!is_string($idList)) $idList = json_encode($idList);
|
||||
$idList = addslashes($idList);
|
||||
return "IN ('" . str_replace(',', "','", str_replace(' ', '', $idList)) . "')";
|
||||
@@ -786,6 +787,19 @@ class baseHelper
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否启用缓存。
|
||||
* Check is enable cache.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isCacheEnabled()
|
||||
{
|
||||
if(isset($_GET['_nocache']) || isset($_SERVER['HTTP_X_ZT_REFRESH'])) return false;
|
||||
global $config;
|
||||
return $config->cache->enable;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------- 常用函数。Some tool functions.-------------------------------//
|
||||
|
||||
@@ -718,7 +718,7 @@ class baseRouter
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function outputXhprof()
|
||||
public function outputXhprof()
|
||||
{
|
||||
if(empty($this->config->debug) || $this->config->debug < 4 || !extension_loaded('xhprof')) return false;
|
||||
|
||||
@@ -2250,11 +2250,49 @@ class baseRouter
|
||||
return $module;
|
||||
} catch (EndResponseException $endResponseException) {
|
||||
echo $endResponseException->getContent();
|
||||
return false;
|
||||
}
|
||||
|
||||
return isset($module) ? $module : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出内容。
|
||||
* Output the content.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function outputPage()
|
||||
{
|
||||
$cacheEnable = $this->config->cache->enableFullPage;
|
||||
/* If caching is not turned on, pages that do not need to be cached, or when searching, they are not cached. */
|
||||
if(!$cacheEnable || !in_array("{$this->moduleName}|{$this->methodName}", $this->config->cache->fullPages) || stripos($this->server->request_uri, 'search') !== false || isset($_GET['_nocache']) || $this->server->http_x_zt_refresh)
|
||||
{
|
||||
$this->loadModule();
|
||||
return helper::removeUTF8Bom(ob_get_clean());
|
||||
}
|
||||
|
||||
$this->loadClass('cache', $static = true);
|
||||
$cacheKey = md5($this->server->request_uri);
|
||||
$namespace = isset($this->session->user->account) ? $this->session->user->account : 'guest';
|
||||
$cache = cache::create($this->config->cache->fullPageDriver, $namespace, $this->config->cache->fullPageLifetime);
|
||||
|
||||
if($cache->has($cacheKey))
|
||||
{
|
||||
if(!headers_sent()) header('X-Zt-Hit-Cache: 1');
|
||||
$content = $cache->get($cacheKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
ob_start();
|
||||
$result = $this->loadModule();
|
||||
$content = helper::removeUTF8Bom(ob_get_clean());
|
||||
/* If the module is loaded successfully, cache the content. */
|
||||
if($result !== false) $cache->set($cacheKey, $content);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载指定模块下的某种对象。
|
||||
* Load the target object of one module.
|
||||
|
||||
@@ -121,7 +121,7 @@ class control extends baseControl
|
||||
*/
|
||||
public function setDefaultPrivByWorkflow()
|
||||
{
|
||||
$actionList = $this->dao->select('module, action')->from(TABLE_WORKFLOWACTION)
|
||||
$actionList = $this->dao->select('module, `action`')->from(TABLE_WORKFLOWACTION)
|
||||
->where('createdBy')->eq($this->app->user->account)
|
||||
->andWhere('buildin')->eq('0')
|
||||
->fetchGroup('module');
|
||||
|
||||
@@ -350,6 +350,9 @@ class helper extends baseHelper
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是内网。
|
||||
* Check is intranet.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isIntranet()
|
||||
|
||||
@@ -97,10 +97,12 @@ class model extends baseModel
|
||||
if(empty($module)) $module = $moduleName;
|
||||
if(empty($method)) $method = $methodName;
|
||||
|
||||
static $actions = array();
|
||||
static $actions = array();
|
||||
static $hasAction = array();
|
||||
if(!isset($hasAction[$moduleName])) $hasAction[$moduleName] = true;
|
||||
if($this->config->edition != 'open')
|
||||
{
|
||||
if(empty($actions[$moduleName]))
|
||||
if($hasAction[$moduleName] and empty($actions[$moduleName]))
|
||||
{
|
||||
$actions[$moduleName] = $this->dao->select('*')->from(TABLE_WORKFLOWACTION)
|
||||
->where('module')->eq($moduleName)
|
||||
@@ -108,6 +110,8 @@ class model extends baseModel
|
||||
->andWhere('status')->eq('enable')
|
||||
->beginIF(!empty($this->config->vision))->andWhere('vision')->eq($this->config->vision)->fi()
|
||||
->fetchAll('action');
|
||||
|
||||
if(empty($actions[$moduleName])) $hasAction[$moduleName] = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -506,7 +506,10 @@ class router extends baseRouter
|
||||
}
|
||||
else
|
||||
{
|
||||
$action = $this->dbh->query("SELECT * FROM " . TABLE_WORKFLOWACTION . " WHERE `module` = '$this->moduleName' AND `action` = '$this->methodName' AND `vision` = '{$this->config->vision}'")->fetch();
|
||||
$actionQuery = "SELECT * FROM " . TABLE_WORKFLOWACTION . " WHERE `module` = '$this->moduleName' AND `action` = '$this->methodName'";
|
||||
if(isset($this->app->user) && $this->app->user->account != 'guest') $actionQuery .= " AND `vision` = '{$this->config->vision}'";
|
||||
|
||||
$action = $this->dbh->query($actionQuery)->fetch();
|
||||
if(zget($action, 'extensionType') == 'override')
|
||||
{
|
||||
$this->rawModule = $this->moduleName;
|
||||
|
||||
@@ -1259,7 +1259,7 @@ EOT;
|
||||
* Set js value.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mix $value
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
|
||||
+121
-8
@@ -151,14 +151,15 @@ class dbh
|
||||
public function tableExits($tableName)
|
||||
{
|
||||
$tableName = str_replace('`', "'", $tableName);
|
||||
$sql = "SHOW TABLES FROM {$this->config->name} like $tableName";
|
||||
$tableName = str_replace("'", "", $tableName);
|
||||
$sql = "SHOW TABLES FROM {$this->config->name} like '{$tableName}'";
|
||||
switch($this->config->driver)
|
||||
{
|
||||
case 'mysql':
|
||||
$sql = "SHOW TABLES FROM {$this->config->name} like {$tableName}";
|
||||
$sql = "SHOW TABLES FROM {$this->config->name} like '{$tableName}'";
|
||||
break;
|
||||
case 'dm':
|
||||
$sql = "SELECT * FROM all_tables WHERE owner='{$this->config->name}' AND table_name={$tableName}";
|
||||
$sql = "SELECT * FROM all_tables WHERE owner='{$this->config->name}' AND table_name='{$tableName}'";
|
||||
break;
|
||||
default:
|
||||
$sql = '';
|
||||
@@ -255,7 +256,8 @@ class dbh
|
||||
public function formatDmSQL($sql)
|
||||
{
|
||||
$sql = trim($sql);
|
||||
$sql = str_replace(array('\r', '\n'), ' ', $sql);
|
||||
/* '\\\\n' try to compatible screen json like \u0232\\nBug. */
|
||||
$sql = str_replace(array('\\\\n', '\r', '\n'), ' ', $sql);
|
||||
$sql = $this->formatFunction($sql);
|
||||
|
||||
$actionPos = strpos($sql, ' ');
|
||||
@@ -266,7 +268,10 @@ class dbh
|
||||
case 'SELECT':
|
||||
return $this->formatField($sql);
|
||||
case 'REPLACE':
|
||||
$sql = str_replace('REPLACE', 'INSERT', $sql);
|
||||
$result = $this->processReplace($sql);
|
||||
if($result != $sql) return $result;
|
||||
|
||||
$sql = str_replace('REPLACE', 'INSERT', $sql);
|
||||
$action = 'INSERT';
|
||||
case 'INSERT':
|
||||
case 'UPDATE':
|
||||
@@ -278,7 +283,7 @@ class dbh
|
||||
if(strpos($sql, '\\\\') !== FALSE) $sql = str_replace('\\\\', '\\', $sql);
|
||||
break;
|
||||
case 'CREATE':
|
||||
if(stripos($sql, 'CREATE VIEW') === 0) return '';
|
||||
if(stripos($sql, 'CREATE VIEW') === 0) $sql = str_replace('CREATE VIEW', 'CREATE OR REPLACE VIEW', $sql);
|
||||
if(stripos($sql, 'CREATE FUNCTION') === 0) return '';
|
||||
|
||||
if(stripos($sql, 'CREATE OR REPLACE VIEW ') === 0)
|
||||
@@ -306,10 +311,11 @@ class dbh
|
||||
$fields = implode(',', $fieldList);
|
||||
return substr($sql, 0, $fieldsBegin+6) . $fields . substr($sql, $fieldsEnd);
|
||||
}
|
||||
elseif(stripos($sql, 'CREATE UNIQUE INDEX') === 0)
|
||||
elseif(stripos($sql, 'CREATE UNIQUE INDEX') === 0 || stripos($sql, 'CREATE INDEX') === 0)
|
||||
{
|
||||
preg_match('/ON\ +[0-9a-zA-Z\_\.]+\`([0-9a-zA-Z\_]+)\`/', $sql, $matches);
|
||||
$tableName = explode('_', $matches[1]);
|
||||
|
||||
$tableName = str_replace($this->config->prefix, '', $matches);
|
||||
$sql = preg_replace('/INDEX\ +\`/', 'INDEX `' . strtolower($tableName[1]) . '_', $sql);
|
||||
}
|
||||
case 'ALTER':
|
||||
@@ -320,6 +326,9 @@ class dbh
|
||||
if(stripos($sql, 'SET SCHEMA') === 0) return $sql;
|
||||
case 'USE':
|
||||
return '';
|
||||
case 'DESC';
|
||||
$tableName = str_replace('DESC ', '', $sql);
|
||||
return "select COLUMN_NAME as Field from all_tab_columns where Table_Name='$tableName'";
|
||||
case 'DROP':
|
||||
return $this->formatField($sql);
|
||||
}
|
||||
@@ -452,11 +461,115 @@ class dbh
|
||||
$sql = preg_replace('/\,\s+key[\_\"0-9a-z ]+\(+[\,\_\"0-9a-z ]+\)+/i', '', $sql);
|
||||
$sql = preg_replace('/\,\s*(unique|fulltext)*\s+key[\_\"0-9a-z ]+\(+[\,\_\"0-9a-z ]+\)+/i', '', $sql);
|
||||
$sql = preg_replace('/ float\s*\(+[\,\_\"0-9a-z ]+\)+/i', ' float', $sql);
|
||||
|
||||
/* Convert "date" datetime to "date" datetime(0) to fix bug 25725, dm database datetime default 6 */
|
||||
preg_match_all('/"[0-9a-zA-Z]+" datetime/', $sql, $datetimeMatch);
|
||||
if(!empty($datetimeMatch))
|
||||
{
|
||||
foreach($datetimeMatch[0] as $match) $sql = str_replace($match, $match . '(0)', $sql);
|
||||
}
|
||||
|
||||
if(strpos($sql, "ALTER TABLE") !== false) $sql = $this->convertAlterTableSql($sql);
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process replace into sql.
|
||||
*
|
||||
* @param mixed $sql
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function processReplace($sql)
|
||||
{
|
||||
// 解析REPLACE INTO语句,提取出表名、字段和值
|
||||
$matches = [];
|
||||
preg_match('/^REPLACE\s+INTO\s+`?([\w_]+)`?\s*\((.*)\)\s+VALUES\s*\((.*?)\)\s*$/i', $sql, $matches);
|
||||
$table_name = $matches[1];
|
||||
$columns = array_map('trim', explode(',', $matches[2]));
|
||||
$values = array_map('trim', explode(', ', $matches[3]));
|
||||
if($table_name == '' or $columns == '' or $values == '') return $sql;
|
||||
|
||||
// 构造SELECT语句,查询数据是否存在
|
||||
$where = [];
|
||||
foreach ($columns as $index => $column) {
|
||||
$value = trim($values[$index], "'");
|
||||
$column = trim($column, '`');
|
||||
$values[$index] = $value;
|
||||
$columns[$index] = $column;
|
||||
$where[] = "`$column` = '$value'";
|
||||
}
|
||||
|
||||
$select_sql = "SELECT * FROM `$table_name` WHERE " . implode(' AND ', $where);
|
||||
|
||||
$result = $this->query($select_sql);
|
||||
$result = $result->fetchAll();
|
||||
$sql = in_array('id', $columns) ? "SET IDENTITY_INSERT `$table_name` ON;" : '';
|
||||
|
||||
if($result)
|
||||
{
|
||||
// 数据已存在,构造UPDATE语句并执行
|
||||
$set = [];
|
||||
$where = [];
|
||||
foreach ($columns as $index => $column) {
|
||||
$value = $values[$index];
|
||||
$set[] = "`$column` = '$value'";
|
||||
$where[] = "`$column` = '$value'";
|
||||
}
|
||||
|
||||
$sql .= "UPDATE `$table_name` SET " . implode(', ', $set) . " WHERE " . implode(' AND ', $where);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 数据不存在,构造INSERT INTO语句并执行
|
||||
$selectColumn = array();
|
||||
$selectValue = array();
|
||||
foreach ($columns as $index => $column) {
|
||||
$selectColumn[] .= "`$column`";
|
||||
$selectValue[] .= "'{$values[$index]}'";
|
||||
}
|
||||
$sql .= "INSERT INTO `$table_name` (" . implode(', ', $selectColumn) . ") VALUES (" . implode(', ', $selectValue) . ")";
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert alter table sql.
|
||||
*
|
||||
* @param mixed $sql
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function convertAlterTableSql($sql)
|
||||
{
|
||||
/* If table has datas and sql no default values defined, add default ''/0. */
|
||||
if(strpos($sql, "NOT NULL") !== false && strpos($sql, "DEFAULT") === false)
|
||||
{
|
||||
$default = '';
|
||||
if(strpos($sql, "integer") !== false) $default = 0;
|
||||
$sql = str_replace("NOT NULL", "NOT NULL DEFAULT '" . $default ."'", $sql);
|
||||
}
|
||||
|
||||
$pattern = '/ALTER TABLE "(.*?)" CHANGE "(.*?)" "(.*?)" (.*?)(?:;|$)/';
|
||||
preg_match($pattern, $sql, $matches);
|
||||
if(count($matches) != 5) return $sql;
|
||||
|
||||
$tableName = $matches[1];
|
||||
$oldColumnName = $matches[2];
|
||||
$newColumnName = $matches[3];
|
||||
$params = str_replace("'", "''", $matches[4]);
|
||||
|
||||
$sql = 'begin ';
|
||||
if($oldColumnName != $newColumnName) $sql .= "execute immediate 'ALTER TABLE $tableName ALTER " . '"' . $oldColumnName . '" RENAME TO "' . $newColumnName . '"' . "';";
|
||||
$sql .= "execute immediate 'ALTER TABLE $tableName MODIFY " . '"' . $newColumnName . '" ' . $params . "';";
|
||||
$sql .= 'end;';
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote.
|
||||
*
|
||||
|
||||
@@ -218,7 +218,7 @@ class mobile
|
||||
'iPad' => 'iPad|iPad.*Mobile',
|
||||
// Removed |^.*Android.*Nexus(?!(?:Mobile).)*$
|
||||
// @see #442
|
||||
'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)',
|
||||
'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)',
|
||||
'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715', // SCH-P709|SCH-P729|SM-T2558|GT-I9205 - Samsung Mega - treat them like a regular phone.
|
||||
// http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html
|
||||
'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI)\b',
|
||||
@@ -756,11 +756,11 @@ class mobile
|
||||
return self::$uaHttpHeaders;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set CloudFront headers
|
||||
* http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html#header-caching-web-device
|
||||
*
|
||||
*
|
||||
* @param array $cfHeaders List of HTTP headers
|
||||
*
|
||||
* @return boolean If there were CloudFront headers to be set
|
||||
@@ -1213,7 +1213,7 @@ class mobile
|
||||
*/
|
||||
public function match($regex, $userAgent = null)
|
||||
{
|
||||
$match = (bool) preg_match(sprintf('#%s#is', $regex), (false === empty($userAgent) ? $userAgent : $this->userAgent), $matches);
|
||||
$match = (bool) preg_match(sprintf('#%s#is', $regex), (false === empty($userAgent) ? $userAgent : ($this->userAgent ? $this->userAgent : '')), $matches);
|
||||
// If positive match is found, store the results for debug.
|
||||
if ($match) {
|
||||
$this->matchingRegex = $regex;
|
||||
|
||||
@@ -20,6 +20,28 @@ helper::import(dirname(dirname(__FILE__)) . '/base/pager/pager.class.php');
|
||||
*/
|
||||
class pager extends basePager
|
||||
{
|
||||
/**
|
||||
* 分页查询起始偏移量。
|
||||
* offset
|
||||
*
|
||||
* @var float
|
||||
* @access public
|
||||
*/
|
||||
public $offset = 0;
|
||||
|
||||
/**
|
||||
* 设置分页查询起始偏移量。
|
||||
* Set offset of paging query.
|
||||
*
|
||||
* @param int $offset
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setOffset($offset)
|
||||
{
|
||||
$this->offset = $offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置模块名。
|
||||
* Set the $moduleName property.
|
||||
@@ -85,6 +107,20 @@ class pager extends basePager
|
||||
if($this->app->isFlow) unset($this->params['module']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建limit语句。
|
||||
* Create the limit string.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function limit()
|
||||
{
|
||||
$limit = '';
|
||||
if($this->pageTotal > 1) $limit = ' lImiT ' . ($this->offset + ($this->pageID - 1) * $this->recPerPage) . ", $this->recPerPage";
|
||||
return $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show pager.
|
||||
*
|
||||
|
||||
@@ -15,7 +15,9 @@ class scm
|
||||
$className = $repo->SCM;
|
||||
if($className == 'Git') $className = 'GitRepo';
|
||||
if(!class_exists($className)) require(strtolower($className) . '.class.php');
|
||||
$this->engine = new $className($repo->client, $repo->path, $repo->account, $repo->password, $repo->encoding, $repo);
|
||||
$repoRoot = $repo->path;
|
||||
if('Subversion' == $className && !empty($repo->prefix)) $repoRoot = substr($repo->path, 0, strlen($repo->path) - strlen($repo->prefix));
|
||||
$this->engine = new $className($repo->client, $repoRoot, $repo->account, $repo->password, $repo->encoding, $repo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+28
-1
@@ -257,7 +257,7 @@ class zdb
|
||||
|
||||
/* Create a value sql. */
|
||||
$value = array_values($row);
|
||||
$value = array_map('addslashes', $value);
|
||||
$value = $this->addslashes($value);
|
||||
$value = join("','", $value);
|
||||
$value = "'" . $value . "'";
|
||||
$sql = "INSERT INTO `$table`($keys) VALUES (" . $value . ");\n";
|
||||
@@ -367,4 +367,31 @@ class zdb
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add slashes for string or string list.
|
||||
*
|
||||
* @param string|string[] $data
|
||||
* @return string|string[]
|
||||
*/
|
||||
public function addslashes($data)
|
||||
{
|
||||
if(is_string($data)) return addslashes($data);
|
||||
if((function_exists('array_is_list') && array_is_list($data)) || (is_array($data) && array_keys($data) === array_keys(array_keys($data))))
|
||||
{
|
||||
$result = array();
|
||||
foreach($data as $item)
|
||||
{
|
||||
if(is_string($item))
|
||||
$result[] = addslashes($item);
|
||||
elseif(is_null($item))
|
||||
$result[] = null;
|
||||
else
|
||||
$result[] = $item;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"require-dev": {
|
||||
"rector/rector": "0.15.*"
|
||||
},
|
||||
"scripts": {
|
||||
"rector": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
"rector process --no-diffs --no-progress-bar"
|
||||
],
|
||||
"rector-nocache": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
"rector process --no-diffs --no-progress-bar --clear-cache"
|
||||
]
|
||||
}
|
||||
}
|
||||
Executable
+319
@@ -0,0 +1,319 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
phpVer="7.4"
|
||||
installRector="false"
|
||||
codeRootDir=$PWD
|
||||
composerDir="$(dirname "$(realpath "$0")")"
|
||||
outputDir="$PWD/build"
|
||||
|
||||
helper() {
|
||||
cat << EOF
|
||||
Usage: $0 -p version dirs...
|
||||
Arguments:
|
||||
-p php版本号,如 7.4
|
||||
可以指定多个版本,用逗号分隔,如 7.4,7.0,5.4
|
||||
-i 在 misc 目录执行 composer install, 安装 rector
|
||||
-r 指定要降级的代码根目录, 默认为当前目录
|
||||
-o 降级补丁包输出目录
|
||||
EOF
|
||||
}
|
||||
|
||||
# 处理命令行参数, 获取要降级的目录
|
||||
[ $# -eq 0 ] && helper
|
||||
while getopts "ir:p:o:" opt; do
|
||||
case $opt in
|
||||
"p")
|
||||
phpVer=$OPTARG
|
||||
;;
|
||||
"r")
|
||||
codeRootDir=$(realpath "$OPTARG")
|
||||
;;
|
||||
"i")
|
||||
installRector="true"
|
||||
;;
|
||||
"o")
|
||||
outputDir=$OPTARG
|
||||
;;
|
||||
*)
|
||||
helper
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [ "$#" -eq 0 ];then
|
||||
echo "need at least one file or directory"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# 处理降级目录路径
|
||||
downGradeDirs=()
|
||||
for d in "$@"
|
||||
do
|
||||
targetDir="$codeRootDir/$d"
|
||||
test -d "$targetDir" || (echo "$d ($targetDir) is not a directory, abort."; exit 2)
|
||||
downGradeDirs+=("${targetDir}")
|
||||
done
|
||||
# 结束命令行参数处理
|
||||
|
||||
excludeRegexList=(
|
||||
module/holiday/ext/
|
||||
lib/purifier/HTMLPurifier.autoload-legacy.php
|
||||
lib/sqlparser/vendor/
|
||||
)
|
||||
|
||||
##################################
|
||||
# 在非容器环境,返回 cpu 核数减一
|
||||
# 在容器环境,如未对 cpu 做限制,返回宿主机核数减一,否则按实际限制的 cpu 核数
|
||||
##################################
|
||||
quotaFile="/sys/fs/cgroup/cpu.max"
|
||||
getCpuQuota() {
|
||||
if [ -f $quotaFile ];then
|
||||
quota=$(cut -d ' ' -f 1 $quotaFile)
|
||||
period=$(cut -d ' ' -f 2 $quotaFile)
|
||||
if [ "$quota" = "max" ];then
|
||||
echo $(($(nproc)-1))
|
||||
return
|
||||
else
|
||||
echo $((quota/period))
|
||||
return
|
||||
fi
|
||||
else
|
||||
echo $(($(nproc)-1))
|
||||
return
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查要降级版本的 php 命令行是否存在,将用于校验语法
|
||||
existsPHPCli() {
|
||||
phpVersion="$1"
|
||||
which php"${phpVersion}" >/dev/null
|
||||
}
|
||||
|
||||
#########################################
|
||||
# 执行降级命令
|
||||
# 参数:
|
||||
# 1. 降级版本, 如 7.4, 7.0
|
||||
# 2. 关闭缓存 (可选项), nocache
|
||||
# 3. 并行执行 (可选项), parallel
|
||||
# * 降级目录列表
|
||||
# 说明
|
||||
# 1. 由于降级命令有可能会发生异常,故设置了重试,
|
||||
# 在函数运行时,缓存目录不变,故重试时会减少部分时间
|
||||
# 2. 并行执行的个数,根据 cpu 最大核数减一处理,如果是容器环境,按分配的核数
|
||||
# 并行执行需要安装 parallel 包
|
||||
##########################################
|
||||
maxRectorRetries=3
|
||||
downGradeDir() {
|
||||
rectorCmd="rector"
|
||||
|
||||
export PHP_VERSION=${1/./}
|
||||
shift
|
||||
|
||||
if [ "$1" = "nocache" ];then
|
||||
rectorCmd="rector-nocache"
|
||||
shift
|
||||
fi
|
||||
|
||||
withParallel="false"
|
||||
if [ "$1" = "parallel" ];then
|
||||
withParallel="true"
|
||||
shift
|
||||
fi
|
||||
|
||||
downDirs=("$@")
|
||||
echo "set PHP_VERSION to $PHP_VERSION"
|
||||
echo "do downgrade on dir ${downDirs[*]}"
|
||||
|
||||
lastDir=$PWD
|
||||
cd "$composerDir" || exit
|
||||
rectorResult=0
|
||||
|
||||
set +e
|
||||
for ((i=0;i<maxRectorRetries;i++)) {
|
||||
if [ "$withParallel" = "true" ];then
|
||||
quotaCpu=$(getCpuQuota)
|
||||
parallel -j "$quotaCpu" -k composer "${rectorCmd}" ::: "${downDirs[@]}"
|
||||
else
|
||||
composer ${rectorCmd} -- "${downDirs[@]}"
|
||||
fi
|
||||
|
||||
rectorResult="$?"
|
||||
if [ "$rectorResult" -eq 0 ];then
|
||||
break
|
||||
fi
|
||||
}
|
||||
set -e
|
||||
|
||||
if [ "$rectorResult" -ne 0 ];then
|
||||
echo "Rector failed"
|
||||
return $rectorResult
|
||||
fi
|
||||
|
||||
cd "$lastDir" || exit
|
||||
}
|
||||
|
||||
############################
|
||||
# 校验单个 php 文件语法
|
||||
# 返回值
|
||||
# 0 没有语法错误
|
||||
# 1 语法异常,或是执行时异常
|
||||
############################
|
||||
syntaxCheck() {
|
||||
phpVersion="$1"
|
||||
phpFilePath="$2"
|
||||
|
||||
phpCli=$(which php"${phpVersion}")
|
||||
|
||||
$phpCli -l "$phpFilePath" | grep -v 'No syntax errors detected' && return 1 || return 0
|
||||
}
|
||||
|
||||
########################################
|
||||
# 确保php文件语法正确
|
||||
# 第一次校验失败后,对文件所在目录执行一次降级
|
||||
# 再做第二次校验,如继续失败,返回错误
|
||||
########################################
|
||||
ensureSyntaxPassed() {
|
||||
phpVersion="$1"
|
||||
phpFilePath="$2"
|
||||
beforeMD5=$(md5sum "$phpFilePath" | awk '{print $1}')
|
||||
|
||||
if syntaxCheck "$phpVersion" "$phpFilePath";then
|
||||
echo "Syntax OK, $phpFilePath"
|
||||
else
|
||||
downGradeDir "$phpVersion" "nocache" "$(dirname "$phpFilePath")"
|
||||
afterMD5=$(md5sum "$phpFilePath" | awk '{print $1}')
|
||||
if ! syntaxCheck "$phpVersion" "$phpFilePath";then
|
||||
echo "downgrade failed"
|
||||
echo "md5 compare (before:$beforeMD5) (after:$afterMD5)"
|
||||
return 1
|
||||
else
|
||||
echo "Syntax OK, $phpFilePath"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
#########################################
|
||||
# 将变更的文件打包
|
||||
# 判断条件为文件修改时间晚于脚本开始执行的时间
|
||||
#########################################
|
||||
archiveChangedFiles() {
|
||||
phpVersion="$1"
|
||||
pointTime=$2
|
||||
archiveDir=$3
|
||||
|
||||
find "$archiveDir" -type f -name '*.php' -newermt "$pointTime" -printf "%P\n" > /tmp/changedFiles
|
||||
|
||||
lastDir=$PWD
|
||||
cd "$archiveDir" || exit 1
|
||||
mkdir -p build/
|
||||
test -d "$outputDir" || mkdir -pv "$outputDir"
|
||||
|
||||
downPatchFile="${outputDir}/downgrade-php$phpVersion.tar.gz"
|
||||
tar zcf "$downPatchFile" --files-from=/tmp/changedFiles
|
||||
echo "Release downgrade patch file: $downPatchFile"
|
||||
|
||||
cd "$lastDir"
|
||||
}
|
||||
|
||||
# 正则匹配要排除的文件,跳过校验
|
||||
matchExclude() {
|
||||
filePath="$1"
|
||||
for reg in "${excludeRegexList[@]}"
|
||||
do
|
||||
if [[ "$filePath" =~ $reg ]];then
|
||||
echo "true"
|
||||
return
|
||||
fi
|
||||
done
|
||||
echo "false"
|
||||
}
|
||||
|
||||
#############################
|
||||
# 对单个 php 版本降级的主函数
|
||||
# 参数:
|
||||
# 1. php 版本
|
||||
# 2. 起始时间, 用于比较降级后变更的文件
|
||||
# * 降级目录列表
|
||||
# 步骤:
|
||||
# 设置临时缓存目录,执行降级
|
||||
# 对降级目录里所有 php 文件校验语法,确保通过
|
||||
# 打包变更文件
|
||||
########################################
|
||||
DownGrade() {
|
||||
phpVersion="$1"
|
||||
pointTime="$2"
|
||||
shift 2
|
||||
|
||||
downDirs=("$@")
|
||||
RECTOR_CACHE_DIR=$(mktemp -d)
|
||||
export RECTOR_CACHE_DIR
|
||||
|
||||
startTime="$(date +%s)"
|
||||
|
||||
if which parallel >/dev/null ;then
|
||||
downGradeDir "$phpVersion" parallel "${downDirs[@]}"
|
||||
else
|
||||
for d in "${downDirs[@]}"
|
||||
do
|
||||
downGradeDir "$phpVersion" "$d"
|
||||
done
|
||||
fi
|
||||
|
||||
for f in $(find "${downGradeDirs[@]}" -type f -name '*.php')
|
||||
do
|
||||
shouldIgnore=$(matchExclude "$f")
|
||||
if [ "$shouldIgnore" = "true" ];then
|
||||
echo "$f is excluded"
|
||||
continue
|
||||
fi
|
||||
ensureSyntaxPassed "$phpVersion" "$f"
|
||||
done
|
||||
|
||||
archiveChangedFiles "$phpVersion" "$pointTime" "$codeRootDir"
|
||||
test -d "$RECTOR_CACHE_DIR" && rm -rf "$RECTOR_CACHE_DIR"
|
||||
|
||||
endTime="$(date +%s)"
|
||||
echo "downgrade to ${phpVersion} cost $((endTime-startTime)) seconds"
|
||||
echo
|
||||
}
|
||||
|
||||
# 设置脚本启动时间
|
||||
startPointTime=$(date +'%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# 执行 composer 组件安装
|
||||
if [ "$installRector" = "true" ];then
|
||||
lastDir=$PWD
|
||||
cd "$composerDir" || exit 1
|
||||
|
||||
composer config -g repo.packagist composer https://mirrors.cloud.tencent.com/composer/
|
||||
composer install
|
||||
|
||||
cd "$lastDir" || exit 1
|
||||
fi
|
||||
|
||||
# 检查 -p 参数, 执行多版本降级或是单版本降级
|
||||
if [[ "$phpVer" =~ ^.*, ]];then
|
||||
IFS=',' read -r -a verList <<< "$phpVer"
|
||||
for v in "${verList[@]}"
|
||||
do
|
||||
existsPHPCli "$v" || (echo "php${v} is not found, abort."; exit 3)
|
||||
done
|
||||
|
||||
for v in "${verList[@]}"
|
||||
do
|
||||
DownGrade "$v" "$startPointTime" "${downGradeDirs[@]}"
|
||||
done
|
||||
else
|
||||
existsPHPCli "$phpVer" || (echo "php${phpVer} is not found, abort."; exit 3)
|
||||
DownGrade "$phpVer" "$startPointTime" "${downGradeDirs[@]}"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# syntaxCheck "$phpVer" /code/module/pipeline/model.php
|
||||
# downGradeDir "$phpVer" "${downGradeDirs[@]}"
|
||||
# archiveChangedFiles "$t" "$codeRootDir"
|
||||
Executable
+87
@@ -0,0 +1,87 @@
|
||||
#!/bin/bash
|
||||
|
||||
finishTime=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
blankLine() {
|
||||
echo
|
||||
}
|
||||
|
||||
outputFrame() {
|
||||
printf "$1"
|
||||
}
|
||||
|
||||
outputLine() {
|
||||
echo "$1"
|
||||
}
|
||||
|
||||
renderGitWebUrl() {
|
||||
if [ -z "$GIT_URL" ];then
|
||||
return
|
||||
fi
|
||||
|
||||
echo $GIT_URL | sed -r -e 's/^.+@/https:\/\//' -e 's/\.git$//'
|
||||
}
|
||||
|
||||
renderTagUrl() {
|
||||
GIT_WEB_BASE=$(renderGitWebUrl)
|
||||
if [ -n "$GIT_WEB_BASE" ];then
|
||||
echo "[${TAG_NAME}](${GIT_WEB_BASE}/src/tag/${TAG_NAME})"
|
||||
else
|
||||
echo ${TAG_NAME}
|
||||
fi
|
||||
}
|
||||
|
||||
renderCommitUrl() {
|
||||
GIT_WEB_BASE=$(renderGitWebUrl)
|
||||
if [ -n "$GIT_WEB_BASE" ];then
|
||||
echo "[${GIT_COMMIT:0:7}](${GIT_WEB_BASE}/commit/${GIT_COMMIT}) ([提交历史](${GIT_WEB_BASE}/commits/tag/${TAG_NAME}))"
|
||||
else
|
||||
echo ${GIT_COMMIT:0:7}
|
||||
fi
|
||||
}
|
||||
|
||||
outputLine "完成时间 **$finishTime**"
|
||||
blankLine
|
||||
|
||||
outputLine "#### Git 信息"
|
||||
|
||||
outputLine "* 触发 Tag: $(renderTagUrl)"
|
||||
|
||||
outputLine "* CommitId: $(renderCommitUrl)"
|
||||
|
||||
outputLine "* 触发人: ${GIT_TAGGER_NAME}"
|
||||
|
||||
blankLine
|
||||
|
||||
|
||||
# 触发人: qishiyao
|
||||
subGroupPath=`echo $GIT_TAG_BUILD_GROUP | sed 's/\./\//'`
|
||||
|
||||
outputLine "#### 下载地址"
|
||||
|
||||
outputLine "##### 开源版"
|
||||
outputFrame "[${PMS_VERSION} (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/pmsPack/$subGroupPath/ZenTaoPMS/${PMS_VERSION}/)"
|
||||
outputFrame "\t\t"
|
||||
outputLine "[${PMS_VERSION} (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/pmsPack/$subGroupPath/ZenTaoALM/${PMS_VERSION}/)"
|
||||
|
||||
outputLine "##### 企业版"
|
||||
outputFrame "[${BIZ_VERSION:3} (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/bizPack/$subGroupPath/ZenTaoPMS/${BIZ_VERSION}/)"
|
||||
outputFrame "\t\t"
|
||||
outputLine "[${BIZ_VERSION:3} (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/bizPack/$subGroupPath/ZenTaoALM/${BIZ_VERSION}/)"
|
||||
|
||||
|
||||
outputLine "##### 旗舰版"
|
||||
outputFrame "[${MAX_VERSION:3} (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/maxPack/$subGroupPath/ZenTaoPMS/${MAX_VERSION}/)"
|
||||
outputFrame "\t\t"
|
||||
outputLine "[${MAX_VERSION:3} (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/maxPack/$subGroupPath/ZenTaoALM/${MAX_VERSION}/)"
|
||||
|
||||
|
||||
if [ -n "$IPD_VERSION" ];then
|
||||
outputLine "##### IPD版"
|
||||
outputFrame "[${IPD_VERSION:3} (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/ipdPack/$subGroupPath/ZenTaoPMS/${IPD_VERSION}/)"
|
||||
outputFrame "\t\t"
|
||||
outputLine "[${IPD_VERSION:3} (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/ipdPack/$subGroupPath/ZenTaoALM/${IPD_VERSION}/)"
|
||||
fi
|
||||
|
||||
outputLine "##### 历史版本"
|
||||
outputLine "[查看历史版本](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/#browse/browse:${ARTIFACT_REPOSITORY})"
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
TAG=$1
|
||||
FIELD=$2
|
||||
|
||||
frameCount=`echo $TAG| grep -o '_' | wc -l`
|
||||
|
||||
build_id=''
|
||||
|
||||
if [ $frameCount -eq 3 ];then
|
||||
build_id=`echo $TAG | cut -d _ -f 3`
|
||||
fi
|
||||
|
||||
case $FIELD in
|
||||
group)
|
||||
case $frameCount in
|
||||
1)
|
||||
echo release
|
||||
;;
|
||||
*)
|
||||
build_date=${TAG##*_}
|
||||
if [ -n "$build_id" ];then
|
||||
echo "$build_date.$build_id"
|
||||
else
|
||||
echo "$build_date.release"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
type)
|
||||
if [ -n "$build_id" ];then
|
||||
echo snapshot
|
||||
else
|
||||
echo release
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
use Rector\Config\RectorConfig;
|
||||
use Rector\Set\ValueObject\DowngradeLevelSetList;
|
||||
use Rector\Set\ValueObject\DowngradeSetList;
|
||||
use Rector\Core\ValueObject\PhpVersion;
|
||||
use Rector\Caching\ValueObject\Storage\FileCacheStorage;
|
||||
|
||||
$version = getenv('PHP_VERSION');
|
||||
$version = $version ?: '72';
|
||||
$cacheDir = getenv('RECTOR_CACHE_DIR');
|
||||
$cacheDir = $cacheDir ?: '/tmp/rector_cached_files';
|
||||
|
||||
return static function (RectorConfig $rectorConfig) use ($version,$cacheDir): void {
|
||||
$rectorConfig->skip([
|
||||
'test/*',
|
||||
]);
|
||||
$rectorConfig->phpVersion(constant(PhpVersion::class . '::PHP_' . $version));
|
||||
$rectorConfig->sets([constant(DowngradeLevelSetList::class . '::DOWN_TO_PHP_' . $version)]);
|
||||
// $rectorConfig->sets([constant(DowngradeSetList::class . '::PHP_' . $version)]);
|
||||
$rectorConfig->cacheClass(FileCacheStorage::class);
|
||||
$rectorConfig->cacheDirectory($cacheDir);
|
||||
};
|
||||
@@ -71,7 +71,7 @@ $config->action->majorList['doc'] = array('releaseddoc', 'collected');
|
||||
$config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,';
|
||||
$config->action->needGetRelateField = ',branch,story,productplan,release,task,build,bug,testcase,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,module,review,';
|
||||
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,gitea,gogs,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,';
|
||||
$config->action->ignoreObjectType4Dynamic = 'kanbanregion,kanbanlane,kanbancolumn';
|
||||
$config->action->ignoreObjectType4Dynamic = 'kanbanregion,kanbanlane,kanbancolumn,disconnectxuanxuan,reconnectxuanxuan,loginxuanxuan,logoutxuanxuan,editmr,removemr';
|
||||
|
||||
$config->action->preferredTypeNum = 10;
|
||||
|
||||
@@ -93,3 +93,5 @@ $config->trash->search['params']['objectName'] = array('operator' => 'include',
|
||||
$config->trash->search['params']['objectID'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
|
||||
$config->trash->search['params']['actor'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
|
||||
$config->trash->search['params']['date'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
|
||||
|
||||
$config->action->latestDateList = array('today', 'yesterday', 'thisWeek', 'lastWeek', 'thisMonth');
|
||||
|
||||
@@ -453,4 +453,15 @@ class action extends control
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear dynamic records older than one month.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function cleanActions()
|
||||
{
|
||||
$this->action->cleanActions();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,11 +388,13 @@ $lang->action->label->estimated = 'estimated';
|
||||
$lang->action->label->reviewpassed = 'Pass';
|
||||
$lang->action->label->reviewrejected = 'Reject';
|
||||
$lang->action->label->reviewclarified = 'Clarify';
|
||||
$lang->action->label->reviewreverted = 'Revert';
|
||||
$lang->action->label->commitsummary = 'Commit Summary';
|
||||
$lang->action->label->updatetrainee = 'Update Trainee';
|
||||
$lang->action->label->setdefaultbranch = 'Set default branch';
|
||||
$lang->action->label->syncprogram = 'start';
|
||||
$lang->action->label->syncproject = 'start';
|
||||
$lang->action->label->syncmultipleproject = 'start';
|
||||
$lang->action->label->syncexecution = 'start';
|
||||
$lang->action->label->syncexecutionbychild = 'start';
|
||||
$lang->action->label->startProgram = '(The start of the project sets the status of the program as Ongoing)';
|
||||
|
||||
@@ -388,11 +388,13 @@ $lang->action->label->estimated = 'estimated';
|
||||
$lang->action->label->reviewpassed = 'Pass';
|
||||
$lang->action->label->reviewrejected = 'Reject';
|
||||
$lang->action->label->reviewclarified = 'Clarify';
|
||||
$lang->action->label->reviewreverted = 'Revert';
|
||||
$lang->action->label->commitsummary = 'Commit Summary';
|
||||
$lang->action->label->updatetrainee = 'Update Trainee';
|
||||
$lang->action->label->setdefaultbranch = 'Set default branch';
|
||||
$lang->action->label->syncprogram = 'start';
|
||||
$lang->action->label->syncproject = 'start';
|
||||
$lang->action->label->syncmultipleproject = 'start';
|
||||
$lang->action->label->syncexecution = 'start';
|
||||
$lang->action->label->syncexecutionbychild = 'start';
|
||||
$lang->action->label->startProgram = '(The start of the project sets the status of the program as Ongoing)';
|
||||
|
||||
@@ -388,11 +388,13 @@ $lang->action->label->estimated = 'estimated';
|
||||
$lang->action->label->reviewpassed = 'Pass';
|
||||
$lang->action->label->reviewrejected = 'Reject';
|
||||
$lang->action->label->reviewclarified = 'Clarify';
|
||||
$lang->action->label->reviewreverted = 'Revert';
|
||||
$lang->action->label->commitsummary = 'Commit Summary';
|
||||
$lang->action->label->updatetrainee = 'Update Trainee';
|
||||
$lang->action->label->setdefaultbranch = 'Set default branch';
|
||||
$lang->action->label->syncprogram = 'start';
|
||||
$lang->action->label->syncproject = 'start';
|
||||
$lang->action->label->syncmultipleproject = 'start';
|
||||
$lang->action->label->syncexecution = 'start';
|
||||
$lang->action->label->syncexecutionbychild = 'start';
|
||||
$lang->action->label->startProgram = '(The start of the project sets the status of the program as Ongoing)';
|
||||
|
||||
@@ -309,6 +309,7 @@ $lang->action->label->commitsummary = 'Commit Summary';
|
||||
$lang->action->label->updatetrainee = 'Update Trainee';
|
||||
$lang->action->label->syncprogram = 'start';
|
||||
$lang->action->label->syncproject = 'start';
|
||||
$lang->action->label->syncmultipleproject = 'start';
|
||||
$lang->action->label->syncexecution = 'start';
|
||||
$lang->action->label->startProgram = '(The start of the project sets the status of the program as Ongoing)';
|
||||
$lang->action->label->submitreview = 'submitted';
|
||||
|
||||
@@ -388,11 +388,13 @@ $lang->action->label->estimated = '估算了';
|
||||
$lang->action->label->reviewpassed = '确认通过';
|
||||
$lang->action->label->reviewrejected = '拒绝了';
|
||||
$lang->action->label->reviewclarified = '有待明确';
|
||||
$lang->action->label->reviewreverted = '撤销变更';
|
||||
$lang->action->label->commitsummary = '提交了培训总结';
|
||||
$lang->action->label->updatetrainee = '更新了培训人员';
|
||||
$lang->action->label->setdefaultbranch = '设置了默认分支';
|
||||
$lang->action->label->syncprogram = '开始了';
|
||||
$lang->action->label->syncproject = '开始了';
|
||||
$lang->action->label->syncmultipleproject = '开始了';
|
||||
$lang->action->label->syncexecution = '开始了';
|
||||
$lang->action->label->syncexecutionbychild = '开始了';
|
||||
$lang->action->label->startProgram = "(因{$lang->projectCommon}开始而启动项目集)";
|
||||
|
||||
+173
-83
@@ -71,6 +71,7 @@ class actionModel extends model
|
||||
$this->dao->insert(TABLE_ACTION)->data($action)->autoCheck()->exec();
|
||||
$actionID = $this->dao->lastInsertID();
|
||||
|
||||
$this->dao->insert(TABLE_ACTIONRECENT)->data($action)->autoCheck()->exec();
|
||||
if($this->post->uid) $this->file->updateObjectID($this->post->uid, $objectID, $objectType);
|
||||
|
||||
/* Call the message notification function. */
|
||||
@@ -249,7 +250,7 @@ class actionModel extends model
|
||||
case 'release':
|
||||
$result = $this->dao->select('product, build')->from($this->config->objectTables[$objectType])->where('id')->eq($objectID)->fetch();
|
||||
$record['product'] = $result->product;
|
||||
$record['project'] = $this->dao->select('project')->from(TABLE_BUILD)->where('id')->eq($result->build)->fetch('project');
|
||||
$record['project'] = $this->dao->select('project')->from(TABLE_BUILD)->where('id')->in($result->build)->fetch('project');
|
||||
break;
|
||||
case 'task':
|
||||
$fields = 'project, execution, story';
|
||||
@@ -356,7 +357,7 @@ class actionModel extends model
|
||||
->andWhere('((action')->ne('deleted')->andWhere('objectID')->in($objectID)->markRight(1)
|
||||
->orWhere('(action')->eq('deleted')->andWhere('objectID')->in($modules)->markRight(1)->markRight(1)
|
||||
->fi()
|
||||
->beginIF(strpos('project,case,story,module', $objectType) === false)
|
||||
->beginIF(!in_array($objectType, array('project', 'case', 'story', 'module')))
|
||||
->where('objectType')->eq($objectType)
|
||||
->andWhere('objectID')->in($objectID)
|
||||
->fi()
|
||||
@@ -406,13 +407,23 @@ class actionModel extends model
|
||||
$productID = trim($action->product, ',');
|
||||
$name = $project->name;
|
||||
$method = $project->model == 'kanban' ? 'index' : 'view';
|
||||
if($name) $action->extra = common::hasPriv('project', $method) ? html::a(helper::createLink('project', $method, "projectID=$action->project"), $name) : $name;
|
||||
if($name) $action->extra = (common::hasPriv('project', $method) and $this->config->vision != 'or') ? html::a(helper::createLink('project', $method, "projectID=$action->project"), $name) : $name;
|
||||
}
|
||||
elseif($actionName == 'linked2plan')
|
||||
{
|
||||
$title = $this->dao->select('title')->from(TABLE_PRODUCTPLAN)->where('id')->eq($action->extra)->fetch('title');
|
||||
if($title) $action->extra = common::hasPriv('productplan', 'view') ? html::a(helper::createLink('productplan', 'view', "planID=$action->extra"), $title) : $title;
|
||||
}
|
||||
elseif($actionName == 'changedbycharter')
|
||||
{
|
||||
$name = $this->dao->select('name')->from(TABLE_CHARTER)->where('id')->eq($action->extra)->fetch('name');
|
||||
if($name) $action->extra = common::hasPriv('charter', 'view') ? html::a(helper::createLink('charter', 'view', "charterID=$action->extra"), $name) : $name;
|
||||
}
|
||||
elseif($actionName == 'linked2roadmap' and $action->objectType == 'story')
|
||||
{
|
||||
$name = $this->dao->select('name')->from(TABLE_ROADMAP)->where('id')->eq($action->extra)->fetch('name');
|
||||
if($name) $action->extra = common::hasPriv('roadmap', 'view') ? html::a(helper::createLink('roadmap', 'view', "roadmapID=$action->extra"), $name) : $name;
|
||||
}
|
||||
elseif($actionName == 'linked2build')
|
||||
{
|
||||
$name = $this->dao->select('name')->from(TABLE_BUILD)->where('id')->eq($action->extra)->fetch('name');
|
||||
@@ -477,6 +488,11 @@ class actionModel extends model
|
||||
$title = $this->dao->select('title')->from(TABLE_PRODUCTPLAN)->where('id')->eq($action->extra)->fetch('title');
|
||||
if($title) $action->extra = common::hasPriv('productplan', 'view') ? html::a(helper::createLink('productplan', 'view', "planID=$action->extra"), "#$action->extra " . $title) : "#$action->extra " . $title;
|
||||
}
|
||||
elseif($actionName == 'unlinkedfromroadmap' and $action->objectType == 'story')
|
||||
{
|
||||
$name = $this->dao->select('name')->from(TABLE_ROADMAP)->where('id')->eq($action->extra)->fetch('name');
|
||||
if($name) $action->extra = common::hasPriv('roadmap', 'view') ? html::a(helper::createLink('roadmap', 'view', "roadmapID=$action->extra"), "#$action->extra " . $name) : "#$action->extra " . $name;
|
||||
}
|
||||
elseif($actionName == 'unlinkedfromtesttask')
|
||||
{
|
||||
$name = $this->dao->select('name')->from(TABLE_TESTTASK)->where('id')->eq($action->extra)->fetch('name');
|
||||
@@ -533,6 +549,11 @@ class actionModel extends model
|
||||
$name = $this->dao->select('title')->from(TABLE_STORY)->where('id')->eq($action->extra)->fetch('title');
|
||||
if($name) $action->extra = common::hasPriv('story', 'view') ? html::a(helper::createLink('story', 'view', "storyID=$action->extra"), "#$action->extra " . $name) : "#$action->extra " . $name;
|
||||
}
|
||||
elseif($actionName == 'deletechildrendemand')
|
||||
{
|
||||
$name = $this->dao->select('title')->from(TABLE_DEMAND)->where('id')->eq($action->extra)->fetch('title');
|
||||
if($name) $action->extra = common::hasPriv('demand', 'view') ? html::a(helper::createLink('demand', 'view', "demandID=$action->extra"), "#$action->extra " . $name) : "#$action->extra " . $name;
|
||||
}
|
||||
elseif($actionName == 'buildopened')
|
||||
{
|
||||
$name = $this->dao->select('name')->from(TABLE_BUILD)->where('id')->eq($action->objectID)->fetch('name');
|
||||
@@ -548,7 +569,7 @@ class actionModel extends model
|
||||
$name = $this->dao->select('name')->from(TABLE_TESTSUITE)->where('id')->eq($action->extra)->fetch('name');
|
||||
if($name) $action->extra = common::hasPriv('caselib', 'browse') ? html::a(helper::createLink('caselib', 'browse', "libID=$action->extra"), $name) : $name;
|
||||
}
|
||||
elseif(strpos(',importfromstorylib,importfromrisklib,importfromissuelib,importfromopportunitylib,', ",{$actionName},") !== false and $this->config->edition == 'max')
|
||||
elseif(strpos(',importfromstorylib,importfromrisklib,importfromissuelib,importfromopportunitylib,', ",{$actionName},") !== false and ($this->config->edition == 'max' or $this->config->edition == 'ipd'))
|
||||
{
|
||||
$name = $this->dao->select('name')->from(TABLE_ASSETLIB)->where('id')->eq($action->extra)->fetch('name');
|
||||
if($name) $action->extra = common::hasPriv('assetlib', $action->objectType) ? html::a(helper::createLink('assetlib', $action->objectType, "libID=$action->extra"), $name) : $name;
|
||||
@@ -569,6 +590,21 @@ class actionModel extends model
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif($actionName == 'closed' and $action->objectType == 'demand')
|
||||
{
|
||||
$action->appendLink = '';
|
||||
if(strpos($action->extra, '|') !== false) $action->extra = substr($action->extra, 0, strpos($action->extra, '|'));
|
||||
if(strpos($action->extra, ':') !== false)
|
||||
{
|
||||
list($extra, $id) = explode(':', $action->extra);
|
||||
$action->extra = $extra;
|
||||
if($id)
|
||||
{
|
||||
$name = $this->dao->select('title')->from(TABLE_DEMAND)->where('id')->eq($id)->fetch('title');
|
||||
if($name) $action->appendLink = html::a(helper::createLink($action->objectType, 'view', "id=$id"), "#$id " . $name);
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif($actionName == 'finished' and $objectType == 'todo')
|
||||
{
|
||||
$action->appendLink = '';
|
||||
@@ -613,7 +649,7 @@ class actionModel extends model
|
||||
if($history->field == 'git') $history->diff = str_replace('+', '%2B', $history->diff);
|
||||
}
|
||||
}
|
||||
elseif(strpos(',linkstory,unlinkstory,createchildrenstory,', ",$actionName,") !== false)
|
||||
elseif(strpos(',linkstory,unlinkstory,createchildrenstory,linkur,unlinkur,', ",$actionName,") !== false)
|
||||
{
|
||||
$extra = '';
|
||||
foreach(explode(',', $action->extra) as $id) $extra .= common::hasPriv('story', 'view') ? html::a(helper::createLink('story', 'view', "storyID=$id"), "#$id ") . ', ' : "#$id, ";
|
||||
@@ -777,7 +813,7 @@ class actionModel extends model
|
||||
$trashQuery = $this->session->trashQuery;
|
||||
$trashQuery = str_replace(array('`objectID`', '`actor`', '`date`'), array('t1.`objectID`', 't1.`actor`', 't1.`date`'), $trashQuery);
|
||||
$table = $this->config->objectTables[$objectType];
|
||||
$nameField = isset($this->config->action->objectNameFields[$objectType]) ? 't2.' . "`{$this->config->action->objectNameFields[$objectType]}`" : '';
|
||||
$nameField = isset($this->config->action->objectNameFields[$objectType]) ? 't2.' . '`' . $this->config->action->objectNameFields[$objectType] . '`' : '';
|
||||
|
||||
if($nameField) $trashQuery = preg_replace("/`objectName`/", $nameField, $trashQuery);
|
||||
|
||||
@@ -887,7 +923,7 @@ class actionModel extends model
|
||||
*/
|
||||
if(empty($desc))
|
||||
{
|
||||
if($action->objectType == 'story' and $action->action == 'reviewed' and strpos($action->extra, ',') !== false)
|
||||
if(($action->objectType == 'story' or $action->objectType == 'demand') and $action->action == 'reviewed' and strpos($action->extra, ',') !== false)
|
||||
{
|
||||
$desc = $this->lang->$objectType->action->rejectreviewed;
|
||||
}
|
||||
@@ -909,7 +945,7 @@ class actionModel extends model
|
||||
$this->app->loadLang('mr');
|
||||
$desc = sprintf($this->lang->mr->$mrAction, $mrDate, $mrActor, $mrLink);
|
||||
}
|
||||
elseif($this->config->edition == 'max' and strpos($this->config->action->assetType, ",{$action->objectType},") !== false and $action->action == 'approved')
|
||||
elseif(($this->config->edition == 'max' or $this->config->edition == 'ipd') and strpos($this->config->action->assetType, ",{$action->objectType},") !== false and $action->action == 'approved')
|
||||
{
|
||||
$desc = empty($this->lang->action->approve->{$action->extra}) ? '' : $this->lang->action->approve->{$action->extra};
|
||||
}
|
||||
@@ -974,7 +1010,7 @@ class actionModel extends model
|
||||
$actionDesc = str_replace('$extra', $action->extra, $desc['main']);
|
||||
}
|
||||
|
||||
if($action->objectType == 'story' and $action->action == 'reviewed')
|
||||
if(($action->objectType == 'story' or $action->objectType == 'demand') and $action->action == 'reviewed')
|
||||
{
|
||||
if(strpos($action->extra, ',') !== false)
|
||||
{
|
||||
@@ -1029,7 +1065,7 @@ class actionModel extends model
|
||||
* @param string $account
|
||||
* @param string $period
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @param int $limit
|
||||
* @param string|int $productID all|int(like 123)|notzero all => include zero, notzero, greater than 0
|
||||
* @param string|int $projectID same as productID
|
||||
* @param string|int $executionID same as productID
|
||||
@@ -1038,8 +1074,10 @@ class actionModel extends model
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getDynamic($account = 'all', $period = 'all', $orderBy = 'date_desc', $pager = null, $productID = 'all', $projectID = 'all', $executionID = 'all', $date = '', $direction = 'next')
|
||||
public function getDynamic($account = 'all', $period = 'all', $orderBy = 'date_desc', $limit = 50, $productID = 'all', $projectID = 'all', $executionID = 'all', $date = '', $direction = 'next')
|
||||
{
|
||||
$this->cleanActions();
|
||||
|
||||
/* Computer the begin and end date of a period. */
|
||||
$beginAndEnd = $this->computeBeginAndEnd($period);
|
||||
extract($beginAndEnd);
|
||||
@@ -1050,34 +1088,32 @@ class actionModel extends model
|
||||
if(!$this->app->user->admin)
|
||||
{
|
||||
$aclViews = isset($this->app->user->rights['acls']['views']) ? $this->app->user->rights['acls']['views'] : array();
|
||||
if($productID == 'all') $authedProducts = (empty($aclViews) or (!empty($aclViews) and !empty($aclViews['product']))) ? $this->app->user->view->products : '0';
|
||||
if($projectID == 'all') $authedProjects = (empty($aclViews) or (!empty($aclViews) and !empty($aclViews['project']))) ? $this->app->user->view->projects : '0';
|
||||
if($executionID == 'all') $authedExecutions = (empty($aclViews) or (!empty($aclViews) and !empty($aclViews['execution']))) ? $this->app->user->view->sprints : '0';
|
||||
|
||||
if(empty($authedProducts)) $authedProducts = '0';
|
||||
if($productID == 'all') $grantedProducts = !empty($aclViews['product']) ? $this->app->user->view->products : '0';
|
||||
if($projectID == 'all') $grantedProjects = !empty($aclViews['project']) ? $this->app->user->view->projects : '0';
|
||||
if($executionID == 'all') $grantedExecutions = !empty($aclViews['execution']) ? $this->app->user->view->sprints : '0';
|
||||
|
||||
if($productID == 'all' and $projectID == 'all')
|
||||
{
|
||||
$productCondition = '';
|
||||
foreach(explode(',', $authedProducts) as $product) $productCondition = empty($productCondition) ? "(execution = '0' and project = '0' and (product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'";
|
||||
foreach(explode(',', $grantedProducts) as $product) $productCondition = empty($productCondition) ? "(execution = '0' and project = '0' and (product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'";
|
||||
if(!empty($productCondition)) $productCondition .= '))';
|
||||
|
||||
$projectCondition = "(execution = '0' and project != '0' and project " . helper::dbIN($authedProjects) . ')';
|
||||
$executionCondition = isset($authedExecutions) ? "(execution != 0 and execution " . helper::dbIN($authedExecutions) . ')' : "(execution != 0 and execution = '$executionID')";
|
||||
$projectCondition = "(execution = '0' and project != '0' and project " . helper::dbIN($grantedProjects) . ')';
|
||||
$executionCondition = isset($grantedExecutions) ? "(execution != 0 and execution " . helper::dbIN($grantedExecutions) . ')' : "(execution != 0 and execution = '$executionID')";
|
||||
}
|
||||
elseif($productID == 'all' and is_numeric($projectID))
|
||||
{
|
||||
$products = $this->loadModel('product')->getProductPairsByProject($projectID);
|
||||
$executions = $this->loadModel('execution')->getPairs($projectID) + array(0 => 0);
|
||||
$executions = $this->loadModel('execution')->fetchPairs($projectID) + array(0 => 0);
|
||||
|
||||
$authedExecutions = isset($authedExecutions) ? array_intersect(array_keys($executions), explode(',', $authedExecutions)) : array_keys($executions);
|
||||
$grantedExecutions = isset($grantedExecutions) ? array_intersect(array_keys($executions), explode(',', $grantedExecutions)) : array_keys($executions);
|
||||
|
||||
$productCondition = '';
|
||||
foreach(array_keys($products) as $product) $productCondition = empty($productCondition) ? "(execution = '0' and project = '0' and (product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'";
|
||||
if(!empty($productCondition)) $productCondition .= '))';
|
||||
|
||||
$projectCondition = "(execution = '0' and project = '$projectID')";
|
||||
$executionCondition = "(execution != '0' and execution " . helper::dbIN($authedExecutions) . ')';
|
||||
$executionCondition = "(execution != '0' and execution " . helper::dbIN($grantedExecutions) . ')';
|
||||
}
|
||||
elseif(is_numeric($productID) and $projectID == 'all')
|
||||
{
|
||||
@@ -1085,12 +1121,12 @@ class actionModel extends model
|
||||
$projects = $this->product->getProjectPairsByProduct($productID);
|
||||
$executions = $this->product->getExecutionPairsByProduct($productID) + array(0 => 0);
|
||||
|
||||
$authedProjects = array_intersect(array_keys($projects), explode(',', $authedProjects));
|
||||
$authedExecutions = isset($authedExecutions) ? array_intersect(array_keys($executions), explode(',', $authedExecutions)) : array_keys($executions);
|
||||
$grantedProjects = array_intersect(array_keys($projects), explode(',', $grantedProjects));
|
||||
$grantedExecutions = isset($grantedExecutions) ? array_intersect(array_keys($executions), explode(',', $grantedExecutions)) : array_keys($executions);
|
||||
|
||||
$productCondition = "(execution = '0' and project = '0' and product like '%,$productID,%')";
|
||||
$projectCondition = "(execution = '0' and project != '0' and project " . helper::dbIN($authedProjects) . ')';
|
||||
$executionCondition = "(execution != '0' and execution " . helper::dbIN($authedExecutions) . ')';
|
||||
$projectCondition = "(execution = '0' and project != '0' and project " . helper::dbIN($grantedProjects) . ')';
|
||||
$executionCondition = "(execution != '0' and execution " . helper::dbIN($grantedExecutions) . ')';
|
||||
}
|
||||
|
||||
$condition = "((product =',0,' or product = '0' or product=',,') AND project = '0' AND execution = '0')";
|
||||
@@ -1113,46 +1149,58 @@ class actionModel extends model
|
||||
if($this->app->getMethodName() == 'dynamic') $beginDate = $year - 1 . '-01-01';
|
||||
}
|
||||
|
||||
$programCondition = empty($this->app->user->view->programs) ? '0' : $this->app->user->view->programs;
|
||||
if(is_numeric($projectID))
|
||||
{
|
||||
$openedDate = $this->dao->select('openedDate')->from(TABLE_PROJECT)->where('id')->eq($projectID)->fetch('openedDate');
|
||||
$beginDate = $openedDate > $beginDate ? $openedDate : $beginDate;
|
||||
}
|
||||
|
||||
$efforts = $this->dao->select('id')->from(TABLE_EFFORT)->where($condition)->fetchPairs();
|
||||
$efforts = !empty($efforts) ? implode(',', $efforts) : 0;
|
||||
$condition = "(($condition) OR `objectType` IN ('doc', 'doclib'))";
|
||||
|
||||
$noMultipleExecutions = $this->dao->select('id')->from(TABLE_PROJECT)->where('multiple')->eq(0)->andWhere('type')->in('sprint,kanban')->fetchPairs('id', 'id');
|
||||
|
||||
$condition = "(`objectType` IN ('doc', 'doclib') OR ($condition)) AND `objectType` NOT IN ('program', 'effort', 'execution')";
|
||||
if($noMultipleExecutions) $condition .= " OR (`objectID` NOT " . helper::dbIN($noMultipleExecutions) . " AND `objectType` = 'execution')";
|
||||
|
||||
$programCondition = empty($this->app->user->view->programs) ? '0' : $this->app->user->view->programs;
|
||||
$condition .= " OR (`objectID` in ($programCondition) AND `objectType` = 'program')";
|
||||
|
||||
$efforts = $this->dao->select('id')->from(TABLE_EFFORT)
|
||||
->where($condition)
|
||||
->beginIF($period != 'all')
|
||||
->beginIF(isset($begin))->andWhere('date')->gt($begin)->fi()
|
||||
->beginIF(isset($end))->andWhere('date')->lt($end)->fi()
|
||||
->fi()
|
||||
->beginIF($beginDate)->andWhere('date')->ge($beginDate)->fi()
|
||||
->fetchPairs();
|
||||
$efforts = !empty($efforts) ? implode(',', $efforts) : 0;
|
||||
$condition .= " OR (`objectID` in ($efforts) AND `objectType` = 'effort')";
|
||||
$condition = "($condition)";
|
||||
|
||||
/* Get actions. */
|
||||
$actions = $this->dao->select('*')->from(TABLE_ACTION)
|
||||
$actionTable = in_array($period, $this->config->action->latestDateList) ? TABLE_ACTIONRECENT : TABLE_ACTION;
|
||||
|
||||
$actions = $this->dao->select('*')->from($actionTable)
|
||||
->where('objectType')->notIN($this->config->action->ignoreObjectType4Dynamic)
|
||||
->beginIF($this->config->vision == 'lite')->andWhere('objectType')->notin('product')->fi()
|
||||
->beginIF($this->config->systemMode == 'light')->andWhere('objectType')->notin('program')->fi()
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->beginIF($period != 'all')->andWhere('date')->gt($begin)->fi()
|
||||
->beginIF($period != 'all')->andWhere('date')->lt($end)->fi()
|
||||
->beginIF($period != 'all')
|
||||
->andWhere('date')->gt($begin)
|
||||
->andWhere('date')->lt($end)
|
||||
->fi()
|
||||
->beginIF($date)->andWhere('date' . ($direction == 'next' ? '<' : '>') . "'{$date}'")->fi()
|
||||
->beginIF($account != 'all')->andWhere('actor')->eq($account)->fi()
|
||||
->beginIF($beginDate)->andWhere('date')->ge($beginDate)->fi()
|
||||
->beginIF($account != 'all')->andWhere('actor')->eq($account)->fi()
|
||||
->beginIF(is_numeric($productID))->andWhere('product')->like("%,$productID,%")->fi()
|
||||
->andWhere('1=1', true)
|
||||
->beginIF(is_numeric($projectID))->andWhere('project')->eq($projectID)->fi()
|
||||
->beginIF(!empty($executions))->andWhere('execution')->in(array_keys($executions))->fi()
|
||||
->beginIF(is_numeric($executionID))->andWhere('execution')->eq($executionID)->fi()
|
||||
->markRight(1)
|
||||
/* Types excluded from Lite. */
|
||||
->beginIF($this->config->vision == 'lite')->andWhere('objectType')->notin('product')->fi()
|
||||
->beginIF($this->config->systemMode == 'light')->andWhere('objectType')->notin('program')->fi()
|
||||
->beginIF($productID == 'notzero')->andWhere('product')->gt(0)->andWhere('product')->notlike('%,0,%')->fi()
|
||||
->beginIF($projectID == 'notzero')->andWhere('project')->gt(0)->fi()
|
||||
->beginIF($executionID == 'notzero')->andWhere('execution')->gt(0)->fi()
|
||||
->andWhere($condition)
|
||||
->beginIF($actionCondition)->andWhere("($actionCondition)")->fi()
|
||||
/* Filter out client login/logout actions. */
|
||||
->andWhere('action')->notin('disconnectxuanxuan,reconnectxuanxuan,loginxuanxuan,logoutxuanxuan,editmr,removemr')
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->limit($limit)
|
||||
->fetchAll();
|
||||
|
||||
if(!$actions) return array();
|
||||
@@ -1193,13 +1241,13 @@ class actionModel extends model
|
||||
* @param array $executions
|
||||
* @param int $queryID
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @param int $limit
|
||||
* @param string $date
|
||||
* @param string $direction
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getDynamicBySearch($products, $projects, $executions, $queryID, $orderBy = 'date_desc', $pager = null, $date = '', $direction = 'next')
|
||||
public function getDynamicBySearch($products, $projects, $executions, $queryID, $orderBy = 'date_desc', $limit = 50, $date = '', $direction = 'next')
|
||||
{
|
||||
$query = $queryID ? $this->loadModel('search')->getQuery($queryID) : '';
|
||||
|
||||
@@ -1248,7 +1296,7 @@ class actionModel extends model
|
||||
if($this->config->vision == 'lite') $actionQuery .= " AND objectType != 'product'";
|
||||
|
||||
$actionQuery .= " AND vision = '" . $this->config->vision . "'";
|
||||
$actions = $this->getBySQL($actionQuery, $orderBy, $pager);
|
||||
$actions = $this->getBySQL($actionQuery, $orderBy, $limit);
|
||||
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'action');
|
||||
if(!$actions) return array();
|
||||
@@ -1260,11 +1308,11 @@ class actionModel extends model
|
||||
*
|
||||
* @param string $sql
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @param int $limit
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getBySQL($sql, $orderBy, $pager = null)
|
||||
public function getBySQL($sql, $orderBy, $limit = 50)
|
||||
{
|
||||
$actionCondition = $this->getActionCondition();
|
||||
if(is_array($actionCondition)) return array();
|
||||
@@ -1273,7 +1321,7 @@ class actionModel extends model
|
||||
->where($sql)
|
||||
->beginIF(!empty($actionCondition))->andWhere("($actionCondition)")->fi()
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->limit($limit)
|
||||
->fetchAll();
|
||||
}
|
||||
|
||||
@@ -1304,6 +1352,17 @@ class actionModel extends model
|
||||
$projectIdList = array();
|
||||
foreach($relatedProjects as $objectType => $idList) $projectIdList += $idList;
|
||||
|
||||
/* If idList include ',*,' Format ',*,' to '*'. */
|
||||
foreach($projectIdList as $key => $idList)
|
||||
{
|
||||
$idList = explode(',', $idList);
|
||||
|
||||
foreach($idList as $id) $projectIdList[] = $id;
|
||||
unset($projectIdList[$key]);
|
||||
}
|
||||
|
||||
if($projectIdList) $projectIdList = array_unique($projectIdList);
|
||||
|
||||
$shadowProducts = $this->dao->select('id')->from(TABLE_PRODUCT)->where('shadow')->eq(1)->fetchPairs();
|
||||
$projectMultiples = $this->dao->select('id,type,multiple')->from(TABLE_PROJECT)->where('id')->in($projectIdList)->fetchAll('id');
|
||||
$docList = $this->loadModel('doc')->getPrivDocs('', 0, 'all');
|
||||
@@ -1424,7 +1483,7 @@ class actionModel extends model
|
||||
$relatedProject = array();
|
||||
if(strpos(",{$this->config->action->needGetProjectType},", ",{$objectType},") !== false)
|
||||
{
|
||||
$objectInfo = $this->dao->select("id, project, $field AS name")->from($table)->where('id')->in($objectIdList)->fetchAll();
|
||||
$objectInfo = $this->dao->select("id, project, `$field` AS name")->from($table)->where('id')->in($objectIdList)->fetchAll();
|
||||
if($objectType == 'gapanalysis') $users = $this->user->getPairs('noletter');
|
||||
foreach($objectInfo as $object)
|
||||
{
|
||||
@@ -1434,7 +1493,7 @@ class actionModel extends model
|
||||
}
|
||||
elseif($objectType == 'project' or $objectType == 'execution')
|
||||
{
|
||||
$objectInfo = $this->dao->select("id, project, $field AS name")->from($table)->where('id')->in($objectIdList)->fetchAll();
|
||||
$objectInfo = $this->dao->select("id, project, `$field` AS name")->from($table)->where('id')->in($objectIdList)->fetchAll();
|
||||
foreach($objectInfo as $object)
|
||||
{
|
||||
$objectName[$object->id] = $object->name;
|
||||
@@ -1467,7 +1526,7 @@ class actionModel extends model
|
||||
elseif($objectType == 'stakeholder')
|
||||
{
|
||||
$objectName = $this->dao->select("t1.id, t2.realname")->from($table)->alias('t1')
|
||||
->leftJoin(TABLE_USER)->alias('t2')->on("t1.{$field} = t2.account")
|
||||
->leftJoin(TABLE_USER)->alias('t2')->on("t1.`$field` = t2.account")
|
||||
->where('t1.id')->in($objectIdList)
|
||||
->fetchPairs();
|
||||
}
|
||||
@@ -1479,11 +1538,11 @@ class actionModel extends model
|
||||
}
|
||||
elseif($objectType == 'privlang')
|
||||
{
|
||||
$objectName = $this->dao->select("objectID AS id, $field AS name")->from($table)->where('objectID')->in($objectIdList)->andWhere('objectType')->eq('priv')->fetchPairs();
|
||||
$objectName = $this->dao->select("objectID AS id, `$field` AS name")->from($table)->where('objectID')->in($objectIdList)->andWhere('objectType')->eq('priv')->fetchPairs();
|
||||
}
|
||||
else
|
||||
{
|
||||
$objectName = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIdList)->fetchPairs();
|
||||
$objectName = $this->dao->select("id, `$field` AS name")->from($table)->where('id')->in($objectIdList)->fetchPairs();
|
||||
}
|
||||
|
||||
$objectNames[$objectType] = $objectName;
|
||||
@@ -1544,7 +1603,7 @@ class actionModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
if($this->config->edition == 'max' and $objectType == 'assetlib')
|
||||
if(($this->config->edition == 'max' or $this->config->edition == 'ipd') and $objectType == 'assetlib')
|
||||
{
|
||||
$libType = $this->dao->select('type')->from(TABLE_ASSETLIB)->where('id')->eq($objectID)->fetch('type');
|
||||
if(strpos('story,issue,risk,opportunity,practice,component', $libType) !== false) $actionObjectLabel = $this->lang->action->label->{$libType . 'assetlib'};
|
||||
@@ -1588,7 +1647,7 @@ class actionModel extends model
|
||||
if($objectDeleted) return $action;
|
||||
}
|
||||
|
||||
if($this->config->edition == 'max'
|
||||
if(($this->config->edition == 'max' or $this->config->edition == 'ipd')
|
||||
and strpos($this->config->action->assetType, ",{$action->objectType},") !== false
|
||||
and empty($action->project) and empty($action->product) and empty($action->execution))
|
||||
{
|
||||
@@ -1786,22 +1845,16 @@ class actionModel extends model
|
||||
|
||||
$period = strtolower($period);
|
||||
|
||||
if($period == 'all') return array('begin' => '1970-1-1', 'end' => '2109-1-1');
|
||||
if($period == 'today') return array('begin' => $today, 'end' => $tomorrow);
|
||||
if($period == 'yesterday') return array('begin' => $yesterday, 'end' => $today);
|
||||
if($period == 'twodaysago') return array('begin' => $twoDaysAgo, 'end' => $yesterday);
|
||||
if($period == 'latest3days')return array('begin' => $twoDaysAgo, 'end' => $tomorrow);
|
||||
if($period == 'all') return array('begin' => '1970-1-1', 'end' => LONG_TIME);
|
||||
if($period == 'today') return array('begin' => $today, 'end' => $tomorrow);
|
||||
if($period == 'yesterday') return array('begin' => $yesterday, 'end' => $today);
|
||||
if($period == 'twodaysago') return array('begin' => $twoDaysAgo, 'end' => $yesterday);
|
||||
if($period == 'latest3days') return array('begin' => $twoDaysAgo, 'end' => $tomorrow);
|
||||
if($period == 'lastweek') return date::getLastWeek();
|
||||
if($period == 'thismonth') return date::getThisMonth();
|
||||
if($period == 'lastmonth') return date::getLastMonth();
|
||||
|
||||
/* If the period is by week, add the end time to the end date. */
|
||||
if($period == 'thisweek' or $period == 'lastweek')
|
||||
{
|
||||
$func = "get$period";
|
||||
extract(date::$func());
|
||||
return array('begin' => $begin, 'end' => $end . ' 23:59:59');
|
||||
}
|
||||
|
||||
if($period == 'thismonth') return date::getThisMonth();
|
||||
if($period == 'lastmonth') return date::getLastMonth();
|
||||
return date::getThisWeek();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1944,21 +1997,21 @@ class actionModel extends model
|
||||
|
||||
if($action->objectType == 'case')
|
||||
{
|
||||
$case = $this->dao->select('*')->from(TABLE_CASE)->where('id')->eq($action->objectID)->fetch();
|
||||
if($case->scene)
|
||||
$caseScene = $this->dao->select('scene')->from(TABLE_CASE)->where('id')->eq($action->objectID)->fetch('scene');
|
||||
if($caseScene)
|
||||
{
|
||||
$scene = $this->dao->select('*')->from(VIEW_SCENECASE)->where('id')->eq($case->scene)->fetch();
|
||||
$scene = $this->loadModel('testcase')->getSceneByID($caseScene);
|
||||
if($scene->deleted) return print(js::error($this->lang->action->refusecase));
|
||||
}
|
||||
}
|
||||
|
||||
if($action->objectType == 'scene')
|
||||
{
|
||||
$scene = $this->dao->select('*')->from("zt_scene")->where('id')->eq($action->objectID)->fetch();
|
||||
$scene = $this->loadModel('testcase')->getSceneByID($action->objectID);
|
||||
if($scene->parent)
|
||||
{
|
||||
$scenerow = $this->dao->select('*')->from(VIEW_SCENECASE)->where('id')->eq($scene->parent)->fetch();
|
||||
if($scenerow->deleted) return print(js::error($this->lang->action->refusescene));
|
||||
$parentScene = $this->testcase->getSceneByID($scene->parent);
|
||||
if($parentScene->deleted) return print(js::error($this->lang->action->refusescene));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1992,6 +2045,12 @@ class actionModel extends model
|
||||
$this->dao->update(TABLE_DOCLIB)->set('deleted')->eq(0)->where($action->objectType)->eq($action->objectID)->exec();
|
||||
}
|
||||
|
||||
if($action->objectType == 'demand')
|
||||
{
|
||||
$demand = $this->dao->select('*')->from(TABLE_DEMAND)->where('id')->eq($action->objectID)->fetch();
|
||||
if($demand->parent) $this->loadModel('demand')->updateParentStatus($action->objectID, $demand->parent);
|
||||
}
|
||||
|
||||
/* Revert productplan parent status. */
|
||||
if($action->objectType == 'productplan') $this->loadModel('productplan')->changeParentField($action->objectID);
|
||||
|
||||
@@ -2080,7 +2139,8 @@ class actionModel extends model
|
||||
|
||||
if($dateGroup)
|
||||
{
|
||||
$lastDateActions = $this->dao->select('*')->from(TABLE_ACTION)->where($this->session->actionQueryCondition)->andWhere("(LEFT(`date`, 10) = '" . substr($action->originalDate, 0, 10) . "')")->orderBy($this->session->actionOrderBy)->fetchAll('id');
|
||||
$lastDate = date(DT_DATE1, $timeStamp);
|
||||
$lastDateActions = $this->dao->select('*')->from(TABLE_ACTION)->where('`date`')->ge($lastDate)->andWhere('`date`')->le("{$lastDate} 23:59:59")->andWhere($this->session->actionQueryCondition)->orderBy($this->session->actionOrderBy)->fetchAll('id');
|
||||
if(count($dateGroup[$date]) < count($lastDateActions))
|
||||
{
|
||||
unset($dateGroup[$date]);
|
||||
@@ -2124,11 +2184,13 @@ class actionModel extends model
|
||||
$condition = $this->session->actionQueryCondition;
|
||||
|
||||
/* Remove date condition for direction. */
|
||||
$condition = preg_replace("/AND +date[\<\>]'\d{4}\-\d{2}\-\d{2}'/", '', $condition);
|
||||
$count = $this->dao->select('count(*) as count')->from(TABLE_ACTION)->where($condition)
|
||||
->andWhere('date' . ($direction == 'next' ? '<' : '>') . "'{$date}'")
|
||||
->fetch('count');
|
||||
return $count > 0;
|
||||
$condition = preg_replace("/AND +[`]?date[`]?[ ]*[\<\>][ |=]*'\d{4}\-\d{2}\-\d{2}'/", '', $condition);
|
||||
$actions = $this->dao->select('id')->from(TABLE_ACTION)
|
||||
->where('date' . ($direction == 'next' ? '<' : '>') . "'{$date}'")
|
||||
->andWhere($condition)
|
||||
->limit(1)
|
||||
->fetch('id');
|
||||
return !empty($actions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2340,4 +2402,32 @@ class actionModel extends model
|
||||
$this->create($deletedAction->objectType, $deletedAction->objectID, 'undeleted');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear dynamic records older than one month.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function cleanActions()
|
||||
{
|
||||
$lastMonth = date('Y-m-d', strtotime('-1 month'));
|
||||
$this->dao->delete()->from(TABLE_ACTIONRECENT)->where('date')->lt($lastMonth)->exec();
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get dynamic count.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getDynamicCount()
|
||||
{
|
||||
$condition = $this->session->actionQueryCondition;
|
||||
$count = $this->dao->select('count(1) as count')->from(TABLE_ACTION)
|
||||
->where($condition)
|
||||
->fetch('count');
|
||||
return $count;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +122,11 @@
|
||||
$methodName = 'setSQL';
|
||||
$params = "id={$action->objectID}";
|
||||
}
|
||||
if($module == 'deploystep')
|
||||
{
|
||||
$module = 'deploy';
|
||||
$methodName = 'viewStep';
|
||||
}
|
||||
if($action->objectType == 'api')
|
||||
{
|
||||
$params = "libID=0&moduelID=0&apiID={$action->objectID}";
|
||||
|
||||
@@ -32,11 +32,14 @@ class admin extends control
|
||||
|
||||
/**
|
||||
* Index page.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
set_time_limit(0);
|
||||
|
||||
$community = zget($this->config->global, 'community', '');
|
||||
if(!$community or $community == 'na')
|
||||
{
|
||||
@@ -78,7 +81,7 @@ class admin extends control
|
||||
*/
|
||||
public function ajaxSetZentaoData()
|
||||
{
|
||||
if(helper::isIntranet()) return $this->send(array('result' => 'fail'));
|
||||
if(helper::isIntranet()) return $this->send(array('result' => 'ignore'));
|
||||
|
||||
$hasInternet = $this->admin->checkInternet();
|
||||
|
||||
|
||||
@@ -39,10 +39,13 @@ $lang->admin->menuList->dev['name'] = $lang->admin->menuSetting['dev']['name'];
|
||||
$lang->admin->menuList->dev['desc'] = $lang->admin->menuSetting['dev']['desc'];
|
||||
$lang->admin->menuList->dev['order'] = 45;
|
||||
|
||||
$lang->admin->menuList->convert['name'] = $lang->admin->menuSetting['convert']['name'];
|
||||
$lang->admin->menuList->convert['desc'] = $lang->admin->menuSetting['convert']['desc'];
|
||||
$lang->admin->menuList->convert['link'] = 'convert|convertjira';
|
||||
$lang->admin->menuList->convert['order'] = 50;
|
||||
if($config->db->driver == 'mysql')
|
||||
{
|
||||
$lang->admin->menuList->convert['name'] = $lang->admin->menuSetting['convert']['name'];
|
||||
$lang->admin->menuList->convert['desc'] = $lang->admin->menuSetting['convert']['desc'];
|
||||
$lang->admin->menuList->convert['link'] = 'convert|convertjira';
|
||||
$lang->admin->menuList->convert['order'] = 50;
|
||||
}
|
||||
|
||||
$lang->admin->menuList->ai['name'] = $lang->admin->menuSetting['ai']['name'];
|
||||
$lang->admin->menuList->ai['desc'] = $lang->admin->menuSetting['ai']['desc'];
|
||||
@@ -190,7 +193,15 @@ $lang->admin->menuList->ai['menuOrder']['5'] = 'prompts';
|
||||
// $lang->admin->menuList->ai['menuOrder']['10'] = 'conversations';
|
||||
$lang->admin->menuList->ai['menuOrder']['15'] = 'models';
|
||||
|
||||
if($config->edition != 'max')
|
||||
$lang->admin->menuList->ai['subMenu']['prompts'] = array('link' => "{$lang->admin->ai->prompt}|ai|prompts|", 'alias' => 'promptview,promptassignrole,promptselectdatasource,promptsetpurpose,promptsettargetform,promptfinalize,promptedit');
|
||||
// $lang->admin->menuList->ai['subMenu']['conversations'] = array('link' => "{$lang->admin->ai->conversation}|ai|conversations|");
|
||||
$lang->admin->menuList->ai['subMenu']['models'] = array('link' => "{$lang->admin->ai->model}|ai|models|", 'alias' => 'editmodel');
|
||||
|
||||
$lang->admin->menuList->ai['menuOrder']['5'] = 'prompts';
|
||||
// $lang->admin->menuList->ai['menuOrder']['10'] = 'conversations';
|
||||
$lang->admin->menuList->ai['menuOrder']['15'] = 'models';
|
||||
|
||||
if($config->edition != 'max' and $config->edition != 'ipd')
|
||||
{
|
||||
unset($lang->admin->menuList->model['subMenu']['scrum']);
|
||||
unset($lang->admin->menuList->model['subMenu']['agileplus']);
|
||||
@@ -208,7 +219,7 @@ if(!helper::hasFeature('waterfallplus'))
|
||||
unset($lang->admin->menuList->model['subMenu']['waterfallplus']);
|
||||
unset($lang->admin->menuList->model['menuOrder']['25']);
|
||||
}
|
||||
if($config->edition == 'max')
|
||||
if($config->edition == 'max' or $config->edition == 'ipd')
|
||||
{
|
||||
if(!helper::hasFeature('scrum_auditplan') and !helper::hasFeature('scrum_process')) unset($lang->admin->menuList->model['subMenu']['scrum'], $lang->admin->menuList->model['menuOrder']['10']);
|
||||
if(!helper::hasFeature('agileplus_auditplan') and !helper::hasFeature('agileplus_process')) unset($lang->admin->menuList->model['subMenu']['agileplus'], $lang->admin->menuList->model['menuOrder']['20']);
|
||||
|
||||
@@ -701,10 +701,10 @@ class adminModel extends model
|
||||
}
|
||||
else
|
||||
{
|
||||
$news = json_decode($zentaoData['news']);
|
||||
$publicclass = json_decode($zentaoData['publicclass']);
|
||||
$plugins = json_decode($zentaoData['plugin']);
|
||||
$patches = json_decode($zentaoData['patch']);
|
||||
if(!empty($zentaoData['news'])) $news = json_decode($zentaoData['news']);
|
||||
if(!empty($zentaoData['publicclass'])) $publicclass = json_decode($zentaoData['publicclass']);
|
||||
if(!empty($zentaoData['plugin'])) $plugins = json_decode($zentaoData['plugin']);
|
||||
if(!empty($zentaoData['patch'])) $patches = json_decode($zentaoData['patch']);
|
||||
if(common::checkNotCN()) array_pop($plugins);
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
<?php if($config->edition != 'max'):?>
|
||||
<?php if(!in_array($config->edition, array('max', 'ipd'))):?>
|
||||
<div class="border-gray mb-16 radius-4">
|
||||
<div class="h-40 pl-16 flex align-center justify-between">
|
||||
<div class="panel-title"><?php echo $lang->admin->upgradeRecommend?></div>
|
||||
|
||||
@@ -587,7 +587,7 @@ class api extends control
|
||||
|
||||
if($changes)
|
||||
{
|
||||
$actionID = $this->action->create('api', $apiID, 'edited');
|
||||
$actionID = $this->action->create('api', $apiID, 'edited', '', '', '', false);
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
|
||||
@@ -630,7 +630,7 @@ class api extends control
|
||||
$api = $this->api->create();
|
||||
if($api === false) return $this->sendError(dao::getError());
|
||||
|
||||
$this->action->create('api', $api->id, 'Created');
|
||||
$this->action->create('api', $api->id, 'Created', '', '', '', false);
|
||||
|
||||
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => 'true', 'callback' => "parentLocate({$api->id}, {$api->lib}, {$api->module})"));
|
||||
return $this->sendSuccess(array('locate' => helper::createLink('api', 'index', "libID={$api->lib}&moduleID={$api->module}&apiID={$api->id}")));
|
||||
|
||||
@@ -69,6 +69,11 @@ class backup extends control
|
||||
}
|
||||
krsort($backups);
|
||||
|
||||
$diskSapce = $this->backup->checkDiskSpace($this->backupPath);
|
||||
$alertTips = sprintf($this->lang->backup->insufficientDisk, round($diskSapce / (1024 * 1024 * 1024), 2));
|
||||
|
||||
$this->view->diskSapce = $diskSapce;
|
||||
$this->view->alertTips = $alertTips;
|
||||
$this->view->title = $this->lang->backup->common;
|
||||
$this->view->position[] = $this->lang->backup->common;
|
||||
$this->view->backups = $backups;
|
||||
|
||||
+43
-36
@@ -2,46 +2,22 @@ $(function()
|
||||
{
|
||||
$('.backup').click(function()
|
||||
{
|
||||
var timeID = null;
|
||||
|
||||
$.ajax({
|
||||
url: $(this).attr('data-link'),
|
||||
success: function(data)
|
||||
{
|
||||
clearInterval(timeID);
|
||||
|
||||
$('#waitting .modal-body #message').append(data);
|
||||
|
||||
setTimeout(function(){return location.reload();}, 2000);
|
||||
},
|
||||
error: function(request, textstatus, error)
|
||||
{
|
||||
clearInterval(timeID);
|
||||
|
||||
if(textstatus == 'timeout') $('#waitting .modal-body #message').append("<p class='text-danger'>" + backupTimeout + '</p>');
|
||||
|
||||
setTimeout(function(){return location.reload();}, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
$('#waitting .modal-body #backupType').html(backup);
|
||||
$('#waitting').modal('show');
|
||||
|
||||
timeID = setInterval(function()
|
||||
if(diskSapce)
|
||||
{
|
||||
$.get(createLink('backup', 'ajaxGetProgress'), function(data)
|
||||
{
|
||||
$('#waitting .modal-content #message').html(data);
|
||||
});
|
||||
}, 1000);
|
||||
})
|
||||
$('#spaceConfirm').modal('show', 'center');
|
||||
}
|
||||
else
|
||||
{
|
||||
backupData();
|
||||
}
|
||||
});
|
||||
|
||||
$('.rmPHPHeader').click(function()
|
||||
{
|
||||
$('#waitting .modal-body #backupType').html(rmPHPHeader);
|
||||
$('#waitting .modal-content #message').hide();
|
||||
$('#waitting').modal('show');
|
||||
})
|
||||
});
|
||||
|
||||
$('.restore').click(function()
|
||||
{
|
||||
@@ -64,8 +40,39 @@ $(function()
|
||||
{
|
||||
return location.reload();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return false;
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
function backupData()
|
||||
{
|
||||
var timeID = null;
|
||||
$.ajax({
|
||||
url: $('.backup').attr('data-link'),
|
||||
success: function(data)
|
||||
{
|
||||
clearInterval(timeID);
|
||||
$('#waitting .modal-body #message').append(data);
|
||||
setTimeout(function(){return location.reload();}, 2000);
|
||||
},
|
||||
error: function(request, textstatus, error)
|
||||
{
|
||||
clearInterval(timeID);
|
||||
if(textstatus == 'timeout') $('#waitting .modal-body #message').append("<p class='text-danger'>" + backupTimeout + '</p>');
|
||||
setTimeout(function(){return location.reload();}, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
$('#waitting .modal-body #backupType').html(backup);
|
||||
$('#waitting').modal('show');
|
||||
|
||||
timeID = setInterval(function()
|
||||
{
|
||||
$.get(createLink('backup', 'ajaxGetProgress'), function(data)
|
||||
{
|
||||
$('#waitting .modal-content #message').html(data);
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
@@ -27,15 +27,18 @@ $lang->backup->settingDir = 'Backup Directory';
|
||||
$lang->backup->settingList['nofile'] = 'Do not back up files or codes.';
|
||||
$lang->backup->settingList['nosafe'] = 'Do not prevent downloading PHP file header.';
|
||||
|
||||
$lang->backup->waitting = '<span id="backupType"></span> In Arbeit. Bitte warten...';
|
||||
$lang->backup->progressSQL = '<p>SQL backup: %s is backed up.</p>';
|
||||
$lang->backup->progressAttach = '<p>SQL backup is completed.</p><p>Attachment backing up.</p>';
|
||||
$lang->backup->progressCode = '<p>SQL backup is completed.</p><p>Attachment backup is completed.</p><p>Code backing up.</p>';
|
||||
$lang->backup->confirmDelete = 'Möchten Sie das Backup löschen?';
|
||||
$lang->backup->confirmRestore = 'Möchten Sie das Backup wiederherstellen?';
|
||||
$lang->backup->holdDays = 'Behalten der letzen %s Tage der Backups';
|
||||
$lang->backup->copiedFail = 'Copy failed files: ';
|
||||
$lang->backup->restoreTip = 'Nur Dateien und Datenbanken können wiederhergestellt werden. Code kann manuell wieder hergestellt werden.';
|
||||
$lang->backup->waitting = '<span id="backupType"></span> In Arbeit. Bitte warten...';
|
||||
$lang->backup->progressSQL = '<p>SQL backup: %s is backed up.</p>';
|
||||
$lang->backup->progressAttach = '<p>SQL backup is completed.</p><p>Attachment backing up.</p>';
|
||||
$lang->backup->progressCode = '<p>SQL backup is completed.</p><p>Attachment backup is completed.</p><p>Code backing up.</p>';
|
||||
$lang->backup->confirmDelete = 'Möchten Sie das Backup löschen?';
|
||||
$lang->backup->confirmRestore = 'Möchten Sie das Backup wiederherstellen?';
|
||||
$lang->backup->holdDays = 'Behalten der letzen %s Tage der Backups';
|
||||
$lang->backup->copiedFail = 'Copy failed files: ';
|
||||
$lang->backup->restoreTip = 'Nur Dateien und Datenbanken können wiederhergestellt werden. Code kann manuell wieder hergestellt werden.';
|
||||
$lang->backup->insufficientDisk = 'Disk space less than%.2fG, it may cause insufficient backup space or affect the use, please process it and try again.';
|
||||
$lang->backup->ongoBackup = 'ongoing backup';
|
||||
$lang->backup->cancelBackup = 'cancel backup';
|
||||
|
||||
$lang->backup->success = new stdclass();
|
||||
$lang->backup->success->backup = 'Erledigt!';
|
||||
|
||||
@@ -27,15 +27,18 @@ $lang->backup->settingDir = 'Backup Directory';
|
||||
$lang->backup->settingList['nofile'] = 'Do not back up files or codes.';
|
||||
$lang->backup->settingList['nosafe'] = 'Do not prevent downloading PHP file header.';
|
||||
|
||||
$lang->backup->waitting = '<span id="backupType"></span> is ongoing. Please wait...';
|
||||
$lang->backup->progressSQL = '<p>SQL backup: %s is backed up.</p>';
|
||||
$lang->backup->progressAttach = '<p>SQL backup is completed.</p><p>Attachment backing up.</p>';
|
||||
$lang->backup->progressCode = '<p>SQL backup is completed.</p><p>Attachment backup is completed.</p><p>Code backing up.</p>';
|
||||
$lang->backup->confirmDelete = 'Do you want to delete the backup?';
|
||||
$lang->backup->confirmRestore = 'Do you want to restore the backup?';
|
||||
$lang->backup->holdDays = 'Hold last %s days of backup';
|
||||
$lang->backup->copiedFail = 'Copy failed files: ';
|
||||
$lang->backup->restoreTip = 'Only files and databases can be restored by clicking Restore. Code can be restored manually.';
|
||||
$lang->backup->waitting = '<span id="backupType"></span> is ongoing. Please wait...';
|
||||
$lang->backup->progressSQL = '<p>SQL backup: %s is backed up.</p>';
|
||||
$lang->backup->progressAttach = '<p>SQL backup is completed.</p><p>Attachment backing up.</p>';
|
||||
$lang->backup->progressCode = '<p>SQL backup is completed.</p><p>Attachment backup is completed.</p><p>Code backing up.</p>';
|
||||
$lang->backup->confirmDelete = 'Do you want to delete the backup?';
|
||||
$lang->backup->confirmRestore = 'Do you want to restore the backup?';
|
||||
$lang->backup->holdDays = 'Hold last %s days of backup';
|
||||
$lang->backup->copiedFail = 'Copy failed files: ';
|
||||
$lang->backup->restoreTip = 'Only files and databases can be restored by clicking Restore. Code can be restored manually.';
|
||||
$lang->backup->insufficientDisk = 'Disk space less than%.2fG, it may cause insufficient backup space or affect the use, please process it and try again.';
|
||||
$lang->backup->ongoBackup = 'ongoing backup';
|
||||
$lang->backup->cancelBackup = 'cancel backup';
|
||||
|
||||
$lang->backup->success = new stdclass();
|
||||
$lang->backup->success->backup = 'Done!';
|
||||
|
||||
@@ -27,15 +27,18 @@ $lang->backup->settingDir = 'Répertoire Backup';
|
||||
$lang->backup->settingList['nofile'] = 'Ne pas archiver fichiers et codes.';
|
||||
$lang->backup->settingList['nosafe'] = 'Ne pas prévenir du téléchargement par PHP file header.';
|
||||
|
||||
$lang->backup->waitting = '<span id="backupType"></span> est en cours. Patientez s´il vous plait...';
|
||||
$lang->backup->progressSQL = '<p>SQL backup: %s est sauvegardé.</p>';
|
||||
$lang->backup->progressAttach = '<p>SQL backup est terminé.</p><p>Les fichiers sont en cours de sauvegarde.</p>';
|
||||
$lang->backup->progressCode = '<p>SQL backup est terminé.</p><p>Sauvegarde des fichiers terminée.</p><p>Sauvegarde du code en cours.</p>';
|
||||
$lang->backup->confirmDelete = 'Voulez-vous supprimer la sauvegarde ?';
|
||||
$lang->backup->confirmRestore = 'Voulez-vous restaurer la sauvegarde ?';
|
||||
$lang->backup->holdDays = 'conserver les derniers %s jours de backup';
|
||||
$lang->backup->copiedFail = 'Fichiers en échec de copie : ';
|
||||
$lang->backup->restoreTip = 'Seulement les fichiers et les bases peuvent être restaurées en cliquant sur Restaurer. Le code doit être restauré manuellement.';
|
||||
$lang->backup->waitting = '<span id="backupType"></span> est en cours. Patientez s´il vous plait...';
|
||||
$lang->backup->progressSQL = '<p>SQL backup: %s est sauvegardé.</p>';
|
||||
$lang->backup->progressAttach = '<p>SQL backup est terminé.</p><p>Les fichiers sont en cours de sauvegarde.</p>';
|
||||
$lang->backup->progressCode = '<p>SQL backup est terminé.</p><p>Sauvegarde des fichiers terminée.</p><p>Sauvegarde du code en cours.</p>';
|
||||
$lang->backup->confirmDelete = 'Voulez-vous supprimer la sauvegarde ?';
|
||||
$lang->backup->confirmRestore = 'Voulez-vous restaurer la sauvegarde ?';
|
||||
$lang->backup->holdDays = 'conserver les derniers %s jours de backup';
|
||||
$lang->backup->copiedFail = 'Fichiers en échec de copie : ';
|
||||
$lang->backup->restoreTip = 'Seulement les fichiers et les bases peuvent être restaurées en cliquant sur Restaurer. Le code doit être restauré manuellement.';
|
||||
$lang->backup->insufficientDisk = 'Disk space less than%.2fG, it may cause insufficient backup space or affect the use, please process it and try again.';
|
||||
$lang->backup->ongoBackup = 'ongoing backup';
|
||||
$lang->backup->cancelBackup = 'cancel backup';
|
||||
|
||||
$lang->backup->success = new stdclass();
|
||||
$lang->backup->success->backup = 'Terminé avec succès !';
|
||||
|
||||
@@ -24,15 +24,18 @@ $lang->backup->settingDir = 'Thư mục sao lưu';
|
||||
$lang->backup->settingList['nofile'] = 'Không sao lưu tập tin hoặc mã nguồn.';
|
||||
$lang->backup->settingList['nosafe'] = 'Không ngăn tải xuống tập tin PHP.';
|
||||
|
||||
$lang->backup->waitting = '<span id="backupType"></span> đang diễn ra. Vui lòng đợi...';
|
||||
$lang->backup->progressSQL = '<p>Sao lưu SQL: %s được sao lưu.</p>';
|
||||
$lang->backup->progressAttach = '<p>Sao lưu SQL đã hoàn thành.</p><p>Sao lưu đính kèm: %s được sao lưu.</p>';
|
||||
$lang->backup->progressCode = '<p>Sao lưu SQL đã hoàn thành.</p><p>Sao lưu đính kèm đã hoàn thành.</p><p>Sao lưu mã nguồn: %s được sao lưu.</p>';
|
||||
$lang->backup->confirmDelete = 'Bạn có muốn xóa sao lưu này?';
|
||||
$lang->backup->confirmRestore = 'Bạn có muốn khôi phục sao lưu này?';
|
||||
$lang->backup->holdDays = 'Giữ ít nhất %s ngày sao lưu';
|
||||
$lang->backup->copiedFail = 'Copy failed files: ';
|
||||
$lang->backup->restoreTip = 'Chỉ tập tin và CSDL có thể được khôi phục bằng cách Click Khôi phục. Mã nguồn có thể khôi phục thủ công.';
|
||||
$lang->backup->waitting = '<span id="backupType"></span> đang diễn ra. Vui lòng đợi...';
|
||||
$lang->backup->progressSQL = '<p>Sao lưu SQL: %s được sao lưu.</p>';
|
||||
$lang->backup->progressAttach = '<p>Sao lưu SQL đã hoàn thành.</p><p>Sao lưu đính kèm: %s được sao lưu.</p>';
|
||||
$lang->backup->progressCode = '<p>Sao lưu SQL đã hoàn thành.</p><p>Sao lưu đính kèm đã hoàn thành.</p><p>Sao lưu mã nguồn: %s được sao lưu.</p>';
|
||||
$lang->backup->confirmDelete = 'Bạn có muốn xóa sao lưu này?';
|
||||
$lang->backup->confirmRestore = 'Bạn có muốn khôi phục sao lưu này?';
|
||||
$lang->backup->holdDays = 'Giữ ít nhất %s ngày sao lưu';
|
||||
$lang->backup->copiedFail = 'Copy failed files: ';
|
||||
$lang->backup->restoreTip = 'Chỉ tập tin và CSDL có thể được khôi phục bằng cách Click Khôi phục. Mã nguồn có thể khôi phục thủ công.';
|
||||
$lang->backup->insufficientDisk = 'Không gian đĩa nhỏ hơn%.2fG, Nó có thể gây ra không đủ dung lượng sao lưu hoặc ảnh hưởng đến việc sử dụng, vui lòng xử lý và thử lại.';
|
||||
$lang->backup->ongoBackup = 'tiếp tục sao lưu';
|
||||
$lang->backup->cancelBackup = 'hủy sao lưu';
|
||||
|
||||
$lang->backup->success = new stdclass();
|
||||
$lang->backup->success->backup = 'Sao lưu hoàn thành!';
|
||||
|
||||
@@ -27,15 +27,18 @@ $lang->backup->settingDir = '备份目录';
|
||||
$lang->backup->settingList['nofile'] = '不备份附件和代码';
|
||||
$lang->backup->settingList['nosafe'] = '不需要防下载PHP文件头';
|
||||
|
||||
$lang->backup->waitting = '<span id="backupType"></span>正在进行中,请稍候...';
|
||||
$lang->backup->progressSQL = '<p>SQL备份中,已备份%s</p>';
|
||||
$lang->backup->progressAttach = '<p>SQL备份完成</p><p>附件备份中,共有%s个文件,已经备份%s个</p>';
|
||||
$lang->backup->progressCode = '<p>SQL备份完成</p><p>附件备份完成</p><p>代码备份中,共有%s个文件,已经备份%s个</p>';
|
||||
$lang->backup->confirmDelete = '是否删除备份?';
|
||||
$lang->backup->confirmRestore = '是否还原该备份?';
|
||||
$lang->backup->holdDays = '备份保留最近 %s 天';
|
||||
$lang->backup->copiedFail = '复制失败的文件:';
|
||||
$lang->backup->restoreTip = '还原功能只还原附件和数据库,如果需要还原代码,可以手动还原。';
|
||||
$lang->backup->waitting = '<span id="backupType"></span>正在进行中,请稍候...';
|
||||
$lang->backup->progressSQL = '<p>SQL备份中,已备份%s</p>';
|
||||
$lang->backup->progressAttach = '<p>SQL备份完成</p><p>附件备份中,共有%s个文件,已经备份%s个</p>';
|
||||
$lang->backup->progressCode = '<p>SQL备份完成</p><p>附件备份完成</p><p>代码备份中,共有%s个文件,已经备份%s个</p>';
|
||||
$lang->backup->confirmDelete = '是否删除备份?';
|
||||
$lang->backup->confirmRestore = '是否还原该备份?';
|
||||
$lang->backup->holdDays = '备份保留最近 %s 天';
|
||||
$lang->backup->copiedFail = '复制失败的文件:';
|
||||
$lang->backup->restoreTip = '还原功能只还原附件和数据库,如果需要还原代码,可以手动还原。';
|
||||
$lang->backup->insufficientDisk = '磁盘空间小于%.2fG,可能会导致备份空间不足或影响使用,请处理后再试。';
|
||||
$lang->backup->ongoBackup = '继续备份';
|
||||
$lang->backup->cancelBackup = '取消备份';
|
||||
|
||||
$lang->backup->success = new stdclass();
|
||||
$lang->backup->success->backup = '备份成功!';
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user