From decfddd1d24a72d312ff00faf8b2ffa241bb0a97 Mon Sep 17 00:00:00 2001 From: liuhong Date: Wed, 23 Nov 2022 06:34:32 +0000 Subject: [PATCH 01/43] * Fix bug #23961. --- module/my/css/preference.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/my/css/preference.css b/module/my/css/preference.css index d5e009ffa0..81ccd2f8ab 100644 --- a/module/my/css/preference.css +++ b/module/my/css/preference.css @@ -1 +1,3 @@ .tip {margin-top: 10px;} +.table-form>tbody>tr>th {white-space: nowrap; !important} +.table-form>tbody>tr>td {width: 75%; !important} From db08e26957fd3a2c451d2e2ba8d9eaf85ab83f07 Mon Sep 17 00:00:00 2001 From: chaideqing Date: Tue, 29 Nov 2022 08:48:10 +0800 Subject: [PATCH 02/43] * Fix feedback #1446. --- module/file/model.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/file/model.php b/module/file/model.php index 9783d7250b..7bca92a246 100755 --- a/module/file/model.php +++ b/module/file/model.php @@ -667,7 +667,6 @@ class fileModel extends model public function pasteImage($data, $uid = '', $safe = false) { if(empty($data)) return ''; - $data = str_replace('\"', '"', $data); $dataLength = strlen($data); if(ini_get('pcre.backtrack_limit') < $dataLength) ini_set('pcre.backtrack_limit', $dataLength); @@ -676,7 +675,8 @@ class fileModel extends model { foreach($out[3] as $key => $base64Image) { - $extension = strtolower($out[2][$key]); + $base64Image = str_replace('\"', '"', $base64Image); + $extension = strtolower($out[2][$key]); if(!in_array($extension, $this->config->file->imageExtensions)) helper::end(); $imageData = base64_decode($base64Image); From e460772fc4d84a1be07c67149ddc17a24cbbc098 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Tue, 29 Nov 2022 10:52:01 +0800 Subject: [PATCH 03/43] * code for task #77129. --- framework/base/router.class.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/framework/base/router.class.php b/framework/base/router.class.php index cceaba51cd..de909ac83a 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -734,10 +734,13 @@ class baseRouter $account = $sql->quote($account); $vision = $this->dbh->query("SELECT * FROM " . TABLE_CONFIG . " WHERE owner = $account AND `key` = 'vision' LIMIT 1")->fetch(); if($vision) $vision = $vision->value; - if(empty($vision)) + + $user = $this->dbh->query("SELECT * FROM " . TABLE_USER . " WHERE account = $account AND deleted = '0' LIMIT 1")->fetch(); + if(!empty($user->visions)) { - $user = $this->dbh->query("SELECT * FROM " . TABLE_USER . " WHERE account = $account AND deleted = '0' LIMIT 1")->fetch(); - if(!empty($user->visions)) list($vision) = explode(',', $user->visions); + $userVisions = explode(',', $user->visions); + if(!in_array($vision, $userVisions)) $vision = ''; + if(empty($vision)) list($vision) = $userVisions; } } From 9b63267e1067d7b344069e91a15399fb61d110d8 Mon Sep 17 00:00:00 2001 From: zenggang Date: Tue, 29 Nov 2022 03:01:45 +0000 Subject: [PATCH 04/43] * Fix bug#30309 --- module/product/control.php | 27 ++++++++++++++++++++++----- module/product/view/browse.html.php | 1 + 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/module/product/control.php b/module/product/control.php index 410d0206bb..e2e4757e2b 100755 --- a/module/product/control.php +++ b/module/product/control.php @@ -271,13 +271,30 @@ class product extends control /* Display status of branch. */ $branchOption = array(); $branchTagOption = array(); - if($product and $product->type != 'normal') + if(!$product and $isProjectStory) { - $branches = $this->loadModel('branch')->getList($productID, $projectID, 'all'); - foreach($branches as $branchInfo) + /* Get branch display under multiple products. */ + foreach($projectProducts as $projectProduct) { - $branchOption[$branchInfo->id] = $branchInfo->name; - $branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : ''); + if($projectProduct and $projectProduct->type != 'normal') + { + $branches = $this->loadModel('branch')->getList($projectProduct->id, $projectID, 'all'); + foreach($branches as $branchInfo) $branchOptions[$projectProduct->id][$branchInfo->id] = $branchInfo->name; + } + } + + $this->view->branchOptions = $branchOptions; + } + else + { + if($product and $product->type != 'normal') + { + $branches = $this->loadModel('branch')->getList($productID, $projectID, 'all'); + foreach($branches as $branchInfo) + { + $branchOption[$branchInfo->id] = $branchInfo->name; + $branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : ''); + } } } diff --git a/module/product/view/browse.html.php b/module/product/view/browse.html.php index 30b0729413..dffefb71c9 100755 --- a/module/product/view/browse.html.php +++ b/module/product/view/browse.html.php @@ -357,6 +357,7 @@ js::set('vision', $this->config->vision); children)) echo "data-children=" . count($story->children);?> data-cases='id, 0);?>'> from = $from;?> + product])) $branchOption = $branchOptions[$story->product];?> app->getViewType() == 'xhtml'):?> $value) From b908e942a8deeb7ec112e8debd192e6ea48d89ac Mon Sep 17 00:00:00 2001 From: zenggang Date: Tue, 29 Nov 2022 06:35:11 +0000 Subject: [PATCH 05/43] * Fix bug#29140 --- module/doc/lang/de.php | 1 + module/doc/lang/en.php | 1 + module/doc/lang/fr.php | 1 + module/doc/lang/zh-cn.php | 1 + module/doc/model.php | 10 ++++++++++ 5 files changed, 14 insertions(+) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 1bdbf6a030..00bc38149e 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -249,6 +249,7 @@ $lang->doc->errorEmptyLib = 'No data in document library.'; $lang->doc->confirmUpdateContent = 'You have a document that is not saved from last time. Do you want to continue editing it?'; $lang->doc->selectLibType = 'Please select a type of doc library.'; $lang->doc->noLibreOffice = 'You does not have access to office conversion settings!'; +$lang->doc->errorParentChapter = 'The parent chapter cannot be its own chapter or sub chapter!'; $lang->doc->noticeAcl['lib']['product']['default'] = 'Users who can access the selected product can access it.'; $lang->doc->noticeAcl['lib']['product']['custom'] = 'Users who can access the selected product or users in the whiltelist can access it.'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 0fe692fd76..905f4b0b4d 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -249,6 +249,7 @@ $lang->doc->errorEmptyLib = 'No data in document library.'; $lang->doc->confirmUpdateContent = 'You have a document that is not saved from last time. Do you want to continue editing it?'; $lang->doc->selectLibType = 'Please select a type of doc library.'; $lang->doc->noLibreOffice = 'You does not have access to office conversion settings!'; +$lang->doc->errorParentChapter = 'The parent chapter cannot be its own chapter or sub chapter!'; $lang->doc->noticeAcl['lib']['product']['default'] = 'Users who can access the selected product can access it.'; $lang->doc->noticeAcl['lib']['product']['custom'] = 'Users who can access the selected product or users in the whiltelist can access it.'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 7fb46c8e44..53de6d24f9 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -249,6 +249,7 @@ $lang->doc->errorEmptyLib = 'No data in document library.'; $lang->doc->confirmUpdateContent = 'You have a document that is not saved from last time. Do you want to continue editing it?'; $lang->doc->selectLibType = 'Please select a type of doc library.'; $lang->doc->noLibreOffice = 'You does not have access to office conversion settings!'; +$lang->doc->errorParentChapter = 'The parent chapter cannot be its own chapter or sub chapter!'; $lang->doc->noticeAcl['lib']['product']['default'] = 'Les utilisateurs qui ont accès au Product peuvent y accéder.'; $lang->doc->noticeAcl['lib']['product']['custom'] = 'Les utilisateurs qui ont accès au Product ou les utilisateurs de la Liste Blanche peuvent y accéder.'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 28c4093d1a..df60f7cd10 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -249,6 +249,7 @@ $lang->doc->errorEmptyLib = '文档库暂无数据。'; $lang->doc->confirmUpdateContent = '检查到您有未保存的文档内容,是否继续编辑?'; $lang->doc->selectLibType = '请选择文档库类型'; $lang->doc->noLibreOffice = '您还没有office转换设置访问权限!'; +$lang->doc->errorParentChapter = '父章节不能是自身章节及子章节!'; $lang->doc->noticeAcl['lib']['product']['default'] = '有所选产品访问权限的用户可以访问。'; $lang->doc->noticeAcl['lib']['product']['custom'] = '有所选产品访问权限或白名单里的用户可以访问。'; diff --git a/module/doc/model.php b/module/doc/model.php index 61370b13f5..9c08b6d366 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -821,6 +821,16 @@ class docModel extends model ->remove('comment,files,labels,uid,contactListMenu') ->get(); + if($doc->type == 'chapter' and $doc->parent) + { + $parentDoc = $this->dao->select('*')->from(TABLE_DOC)->where('id')->eq((int)$doc->parent)->fetch(); + if(strpos($parentDoc->path, ",$docID,") !== false) + { + dao::$errors['parent'] = $this->lang->doc->errorParentChapter; + return false; + } + } + if(!empty($doc->acl) and $doc->acl == 'private') $doc->users = $oldDoc->addedBy; $oldDocContent = $this->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->eq($docID)->andWhere('version')->eq($oldDoc->version)->fetch(); From 71c1466f5a471c4cb6520972fe8420c546724c9f Mon Sep 17 00:00:00 2001 From: wangyidong Date: Tue, 29 Nov 2022 14:42:05 +0800 Subject: [PATCH 06/43] * code for task #77617. --- module/build/model.php | 32 ++++++++++ module/projectrelease/control.php | 20 ++++--- module/projectrelease/js/create.js | 27 ++++++--- module/projectrelease/view/create.html.php | 1 + module/release/control.php | 23 +------ module/release/js/create.js | 2 - test/class/build.class.php | 14 +++++ test/model/build/getnotemptybuilds.php | 70 ++++++++++++++++++++++ 8 files changed, 149 insertions(+), 40 deletions(-) create mode 100644 test/model/build/getnotemptybuilds.php diff --git a/module/build/model.php b/module/build/model.php index 1e9f333b90..38152234fd 100644 --- a/module/build/model.php +++ b/module/build/model.php @@ -181,6 +181,38 @@ class buildModel extends model return $this->getExecutionBuilds($executionID, 'bysearch', $buildQuery); } + /** + * Get link stories or bugs builds. + * + * @param array $buildIdList + * @access public + * @return array + */ + public function getNotEmptyBuilds($buildIdList) + { + $notEmptyBuilds = array(); + $buildList = $this->getByList($buildIdList); + foreach($buildList as $build) + { + if(!$build->execution && !empty($build->builds)) + { + $childBuilds = $this->getByList($build->builds); + foreach($childBuilds as $childBuild) + { + $childBuild->stories = trim($childBuild->stories, ','); + $childBuild->bugs = trim($childBuild->bugs, ','); + + if($childBuild->stories) $build->stories .= ',' . $childBuild->stories; + if($childBuild->bugs) $build->bugs .= ',' . $childBuild->bugs; + } + } + + if(!empty($build->stories) or !empty($build->bugs)) $notEmptyBuilds[$build->id] = $build->id; + } + + return $notEmptyBuilds; + } + /** * Get story builds. * diff --git a/module/projectrelease/control.php b/module/projectrelease/control.php index 671d20c340..18a016922d 100644 --- a/module/projectrelease/control.php +++ b/module/projectrelease/control.php @@ -133,14 +133,14 @@ class projectrelease extends control $builds = $this->build->getBuildPairs($this->view->product->id, $this->view->branch, 'notrunk,withbranch|hasproject', $projectID, 'project'); $releasedBuilds = $this->projectrelease->getReleasedBuilds($projectID); foreach($releasedBuilds as $build) unset($builds[$build]); - unset($builds['trunk']); - $this->view->title = $this->view->project->name . $this->lang->colon . $this->lang->release->create; - $this->view->projectID = $projectID; - $this->view->builds = $builds; - $this->view->lastRelease = $this->projectrelease->getLast($projectID); - $this->view->users = $this->loadModel('user')->getPairs('noclosed'); - $this->view->confirmLink = $this->lang->release->confirmLink; + $this->view->title = $this->view->project->name . $this->lang->colon . $this->lang->release->create; + $this->view->projectID = $projectID; + $this->view->builds = $builds; + $this->view->lastRelease = $this->projectrelease->getLast($projectID); + $this->view->users = $this->loadModel('user')->getPairs('noclosed'); + $this->view->confirmLink = $this->lang->release->confirmLink; + $this->view->notEmptyBuilds = $this->build->getNotEmptyBuilds(array_keys($builds)); $this->display(); } @@ -811,8 +811,10 @@ class projectrelease extends control $builds = $this->loadModel('build')->getBuildPairs($productID, $branch, 'notrunk,withbranch,hasproject', $projectID, 'project', '', false); $releasedBuilds = $this->projectrelease->getReleasedBuilds($projectID); foreach($releasedBuilds as $build) unset($builds[$build]); - unset($builds['trunk']); - return print(html::select('build[]', $builds, '', "class='form-control chosen' multiple")); + /* Get the builds of the linked stories or bugs. */ + $notEmptyBuilds = $this->build->getNotEmptyBuilds(array_keys($builds)); + + return print(html::select('build[]', $builds, '', "class='form-control chosen' multiple data-notemptybuilds='" . join(',', $notEmptyBuilds) . "'")); } } diff --git a/module/projectrelease/js/create.js b/module/projectrelease/js/create.js index 8b848d6351..43c1298bac 100644 --- a/module/projectrelease/js/create.js +++ b/module/projectrelease/js/create.js @@ -1,18 +1,27 @@ $('#submit').click(function() { - var dateFormat = new RegExp(/^\d{4}\-\d{2}\-\d{2}$/); - var name = $('#name').val(); - var date = $('#date').val(); - var build = $('#build').val(); - if(name && build && dateFormat.test(date)) + var dateFormat = new RegExp(/^\d{4}\-\d{2}\-\d{2}$/); + var name = $('#name').val(); + var date = $('#date').val(); + var build = $('#build').val(); + var notEmptyBuild = false; + + $.each(build, function(index, value) + { + if(typeof(notEmptyBuilds[value]) != 'undefined') + { + notEmptyBuild = true; + return false; + } + }) + + if(name && build && notEmptyBuild && dateFormat.test(date)) { var result = confirm(confirmLink) ? true : false; $('#sync').val(result); } }); -$('[data-toggle="popover"]').popover(); - /** * Ajax load unlinked builds with project and product. * @@ -26,6 +35,10 @@ function loadBuilds() $('#buildBox').load(createLink('projectrelease', 'ajaxLoadBuilds', "projectID=" + projectID + "&productID=" + productID + "&branch=" + branch), function() { $('#build').attr('data-placeholder', multipleSelect).chosen(); + $.each($('#build').attr('data-notemptybuilds').split(','), function(index, value) + { + notEmptyBuilds[value] = value; + }); }); } diff --git a/module/projectrelease/view/create.html.php b/module/projectrelease/view/create.html.php index ab669607a3..fa3671ae44 100644 --- a/module/projectrelease/view/create.html.php +++ b/module/projectrelease/view/create.html.php @@ -13,6 +13,7 @@ +
diff --git a/module/release/control.php b/module/release/control.php index 3f8297186f..6446cbfdd1 100644 --- a/module/release/control.php +++ b/module/release/control.php @@ -86,27 +86,6 @@ class release extends control $releasedBuilds = $this->release->getReleasedBuilds($productID, $branch); foreach($releasedBuilds as $build) unset($builds[$build]); - /* Get the builds of the linked stories or bugs. */ - $notEmptyBuilds = array(); - $buildList = $this->build->getByList(array_keys($builds)); - foreach($buildList as $build) - { - if(!$build->execution && !empty($build->builds)) - { - $childBuilds = $this->build->getByList($build->builds); - foreach($childBuilds as $childBuild) - { - $childBuild->stories = trim($childBuild->stories, ','); - $childBuild->bugs = trim($childBuild->bugs, ','); - - if($childBuild->stories) $build->stories .= ',' . $childBuild->stories; - if($childBuild->bugs) $build->bugs .= ',' . $childBuild->bugs; - } - } - - if(!empty($build->stories) or !empty($build->bugs)) $notEmptyBuilds[$build->id] = $build->id; - } - $this->commonAction($productID, $branch); $this->view->title = $this->view->product->name . $this->lang->colon . $this->lang->release->create; $this->view->position[] = $this->lang->release->create; @@ -114,7 +93,7 @@ class release extends control $this->view->builds = $builds; $this->view->users = $this->loadModel('user')->getPairs('noclosed'); $this->view->lastRelease = $this->release->getLast($productID, $branch); - $this->view->notEmptyBuilds = $notEmptyBuilds; + $this->view->notEmptyBuilds = $this->build->getNotEmptyBuilds(array_keys($builds)); $this->display(); } diff --git a/module/release/js/create.js b/module/release/js/create.js index 1b64abc7c2..87a9d72468 100644 --- a/module/release/js/create.js +++ b/module/release/js/create.js @@ -21,5 +21,3 @@ $('#submit').click(function() $('#sync').val(result); } }); - -$('[data-toggle="popover"]').popover(); diff --git a/test/class/build.class.php b/test/class/build.class.php index a51cd8ba1f..e3ce509607 100644 --- a/test/class/build.class.php +++ b/test/class/build.class.php @@ -149,6 +149,20 @@ class buildTest return $objects; } + /** + * Test for getNotEmptyBuilds method + * + * @param array $buildIdList + * @access public + * @return string + */ + public function getNotEmptyBuildsTest($buildIdList) + { + $notEmptyBuilds = $this->objectModel->getNotEmptyBuilds($buildIdList); + sort($notEmptyBuilds); + return empty($notEmptyBuilds) ? 'null' : join(',', $notEmptyBuilds); + } + /** * Function getLast test by build * diff --git a/test/model/build/getnotemptybuilds.php b/test/model/build/getnotemptybuilds.php new file mode 100644 index 0000000000..f868343e7c --- /dev/null +++ b/test/model/build/getnotemptybuilds.php @@ -0,0 +1,70 @@ +#!/usr/bin/env php +getNotEmptyBuilds(); +cid=1 +pid=1 + +不传任何数据 >> null +迭代版本未关联需求和Bug >> null +迭代版本关联需求和Bug >> 101 +项目版本关联版本关联需求和Bug >> 102 +项目版本关联版本未关联需求和Bug >> null +版本列表中关联需求和Bug >> 101 +版本列表中混合项目版本和迭代版本 >> 101,102 + +*/ + +$build = new buildTest(); + +$buildData = new stdclass(); +$buildData->id = 100; +$buildData->product = 1; +$buildData->project = 1; +$buildData->execution = 2; +$buildData->name = 'test1'; +$buildData->date = date('Y-m-d'); +$build->objectModel->dao->replace(TABLE_BUILD)->data($buildData)->exec(); +$buildId1 = $buildData->id; + +$buildData->id = 101; +$buildData->name = 'test2'; +$buildData->stories = '1,2,3'; +$build->objectModel->dao->replace(TABLE_BUILD)->data($buildData)->exec(); +$buildId2 = $buildData->id; + +$buildData = new stdclass(); +$buildData->id = 102; +$buildData->product = 1; +$buildData->project = 1; +$buildData->execution = 0; +$buildData->builds = ",$buildId2,"; +$buildData->name = 'test3'; +$buildData->date = date('Y-m-d'); +$build->objectModel->dao->replace(TABLE_BUILD)->data($buildData)->exec(); +$buildId3 = $buildData->id; + +$buildData = new stdclass(); +$buildData->id = 103; +$buildData->product = 1; +$buildData->project = 1; +$buildData->execution = 0; +$buildData->builds = ",$buildId1,"; +$buildData->name = 'test4'; +$buildData->date = date('Y-m-d'); +$build->objectModel->dao->replace(TABLE_BUILD)->data($buildData)->exec(); +$buildId4 = $buildData->id; + + +r($build->getNotEmptyBuildsTest(array())) && p() && e('null'); //不传任何数据 +r($build->getNotEmptyBuildsTest(array($buildId1))) && p() && e('null'); //迭代版本未关联需求和Bug +r($build->getNotEmptyBuildsTest(array($buildId2))) && p() && e('101'); //迭代版本关联需求和Bug +r($build->getNotEmptyBuildsTest(array($buildId3))) && p() && e('102'); //项目版本关联版本关联需求和Bug +r($build->getNotEmptyBuildsTest(array($buildId4))) && p() && e('null'); //项目版本关联版本未关联需求和Bug +r($build->getNotEmptyBuildsTest(array($buildId1, $buildId2))) && p() && e('101'); //版本列表中关联需求和Bug +r($build->getNotEmptyBuildsTest(array($buildId3, $buildId2))) && p() && e('101,102'); //版本列表中混合项目版本和迭代版本 From 8d41badb9ef074f5f8aa75b03cbb6c87a5ad0bf9 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Tue, 29 Nov 2022 15:50:49 +0800 Subject: [PATCH 07/43] * code for task #77242. --- module/build/view/view.html.php | 6 +++++- module/projectrelease/control.php | 13 +++++++++---- module/release/control.php | 11 ++++++++--- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/module/build/view/view.html.php b/module/build/view/view.html.php index aa18d5ecae..fe31522f6a 100644 --- a/module/build/view/view.html.php +++ b/module/build/view/view.html.php @@ -26,7 +26,11 @@ tbody tr td:first-child input {display: none;}