From 2eb3300ca6314f720a3e235bd462e80f9f7697e8 Mon Sep 17 00:00:00 2001 From: chaideqing Date: Wed, 28 Sep 2022 13:29:26 +0800 Subject: [PATCH 001/608] * add xuanxuan notification send feedback and review --- .../ext/model/class/xuanxuan.class.php | 72 +++++++++++++++++-- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/xuanxuan/extension/xuan/message/ext/model/class/xuanxuan.class.php b/xuanxuan/extension/xuan/message/ext/model/class/xuanxuan.class.php index 8a33333ac8..9ea25f0734 100644 --- a/xuanxuan/extension/xuan/message/ext/model/class/xuanxuan.class.php +++ b/xuanxuan/extension/xuan/message/ext/model/class/xuanxuan.class.php @@ -23,10 +23,19 @@ class xuanxuanMessage extends messageModel { $field = 'obj.*,project.name as projectName,product.name as productName,execu.name as execuName'; } + else if($objectType == 'feedback') + { + $field = 'obj.*,product.name as productName'; + } + else if($objectType == 'review') + { + $field = 'obj.*,project.name as projectName'; + } else { $field = 'obj.*'; } + $object = $this->dao->select($field)->from($this->config->objectTables[$objectType])->alias('obj') ->beginIF($objectType == 'task') ->leftJoin($this->config->objectTables['project'])->alias('project')->on('project.id = obj.project') @@ -40,6 +49,12 @@ class xuanxuanMessage extends messageModel ->leftJoin($this->config->objectTables['execution'])->alias('execu')->on('execu.id = obj.execution') ->leftJoin($this->config->objectTables['product'])->alias('product')->on('product.id = obj.product') ->fi() + ->beginIF($objectType == 'feedback') + ->leftJoin($this->config->objectTables['product'])->alias('product')->on('product.id = obj.product') + ->fi() + ->beginIF($objectType == 'review') + ->leftJoin($this->config->objectTables['project'])->alias('project')->on('project.id = obj.project') + ->fi() ->where('obj.id')->eq($objectID) ->fetch(); $field = $this->config->action->objectNameFields[$objectType]; @@ -49,18 +64,43 @@ class xuanxuanMessage extends messageModel $notifyType = strtolower(explode(',', $extra)[0]); if ($notifyType == 'pass') { - $title = $objectType == 'mr' ? '' : sprintf($this->lang->message->notifyPassTitle, $this->app->user->realname, 1); + $title = sprintf($this->lang->message->notifyPassTitle, $this->app->user->realname, 1); } else if($notifyType == 'clarify') { - $title = $objectType == 'mr' ? '' : sprintf($this->lang->message->notifyClarifyTitle, $this->app->user->realname, 1); + $title = sprintf($this->lang->message->notifyClarifyTitle, $this->app->user->realname, 1); } else if($notifyType == 'reject') { - $title = $objectType == 'mr' ? '' : sprintf($this->lang->message->notifyRejectTitle, $this->app->user->realname, 1); + $title = sprintf($this->lang->message->notifyRejectTitle, $this->app->user->realname, 1); } } + if ($objectType == 'feedback' && ($actionType == 'tobug' || $actionType == 'tostory' || $actionType == 'totask' || $actionType == 'todo')) + { + if ($actionType == 'tobug') + { + $title = sprintf($this->lang->message->feedbackToBugTitle, $this->app->user->realname, 1); + } + else if($actionType == 'tostory') + { + $title = sprintf($this->lang->message->feedbackToStoryTitle, $this->app->user->realname, 1); + } + else if($actionType == 'totask') + { + $title = sprintf($this->lang->message->feedbackToTaskTitle, $this->app->user->realname, 1); + } + else if($actionType == 'todo') + { + $title = sprintf($this->lang->message->feedbackToDoTitle, $this->app->user->realname, 1); + } + } + + if ($objectType == 'review' && $actionType == 'toaudit') + { + $title = sprintf($this->lang->message->reviewToauditTitle, $this->app->user->realname, 1); + } + $server = $this->loadModel('im')->getServer('zentao'); $onlybody = isset($_GET['onlybody']) ? $_GET['onlybody'] : ''; unset($_GET['onlybody']); @@ -71,10 +111,12 @@ class xuanxuanMessage extends messageModel if(!empty($object->assignedTo)) $target .= $object->assignedTo == 'closed' ? $object->openedBy : $object->assignedTo; if(!empty($object->mailto)) $target .= ",{$object->mailto}"; if(($objectType == 'mr' or $objectType == 'kanbancard') and !empty($object->createdBy)) $target .= ",{$object->createdBy}"; + if($objectType == 'review') $target .= ",{$object->auditedBy}"; $target = trim($target, ','); + $target = explode(',', $target); $target = $this->dao->select('id')->from(TABLE_USER) ->where('account')->in($target) - ->beginIF($objectType != 'mr')->andWhere('account')->ne($this->app->user->account)->fi() + ->beginIF($objectType != 'mr' && $objectType != 'review')->andWhere('account')->ne($this->app->user->account)->fi() ->fetchAll('id'); $target = array_keys($target); @@ -110,6 +152,24 @@ class xuanxuanMessage extends messageModel $subcontent->parentURL = "xxc:openInApp/zentao-integrated/" . urlencode($server . helper::createLink($parentType, 'browse', "id=$subcontent->parent", 'html')); $subcontent->cardURL = $url; } + elseif($objectType == 'feedback') + { + $subcontent->headTitle = $object->productName; + $subcontent->headSubTitle = $object->execuName; + $subcontent->parentType = 'product'; + $subcontent->parent = $object->product; + $subcontent->parentURL = "xxc:openInApp/zentao-integrated/" . urlencode($server . helper::createLink('feedback', 'browse', "id=$object->product", 'html')); + $subcontent->cardURL = $url; + } + elseif($objectType == 'review') + { + $subcontent->headTitle = $object->projectName; + $subcontent->headSubTitle = $object->execuName; + $subcontent->parentType = 'product'; + $subcontent->parent = $object->product; + $subcontent->parentURL = "xxc:openInApp/zentao-integrated/" . urlencode($server . helper::createLink('review', 'browse', "id=$object->product", 'html')); + $subcontent->cardURL = $url; + } else { $subcontent->parentType = $objectType; @@ -146,11 +206,11 @@ class xuanxuanMessage extends messageModel $contentData->actions = array(); $contentData->url = "xxc:openInApp/zentao-integrated/" . urlencode($url); } - $contentData->extra = $extra; + $contentData->extra = is_array($extra) ? $extra : ''; $content = json_encode($contentData); $avatarUrl = $server . $this->app->getWebRoot() . 'favicon.ico'; - if($target && ($objectType == 'bug' || $objectType == 'task' || $objectType == 'story')) $this->loadModel('im')->messageCreateNotify($target, $title, $subtitle = '', $content, $contentType = 'object', $url, $actions = array(), $sender = array('id' => 'zentao', 'realname' => $this->lang->message->sender, 'name' => $this->lang->message->sender, 'avatar' => $avatarUrl)); + if($target && ($objectType == 'bug' || $objectType == 'task' || $objectType == 'story' || $objectType == 'feedback' || $objectType == 'review')) $this->loadModel('im')->messageCreateNotify($target, $title, $subtitle = '', $content, $contentType = 'object', $url, $actions = array(), $sender = array('id' => 'zentao', 'realname' => $this->lang->message->sender, 'name' => $this->lang->message->sender, 'avatar' => $avatarUrl)); if($objectType == 'mr' and is_array($this->lang->message->mr->$actionType) and !empty($object->assignee)) { From 434afe33af0d7b175fcf229e368d03ebc4ce2df0 Mon Sep 17 00:00:00 2001 From: chaideqing Date: Wed, 28 Sep 2022 16:03:11 +0800 Subject: [PATCH 002/608] * add lang about zentao client notification feedback and review --- xuanxuan/extension/xuan/message/ext/lang/de/xuanxuan.php | 7 +++++++ xuanxuan/extension/xuan/message/ext/lang/en/xuanxuan.php | 7 +++++++ xuanxuan/extension/xuan/message/ext/lang/fr/xuanxuan.php | 7 +++++++ .../extension/xuan/message/ext/lang/zh-cn/xuanxuan.php | 7 +++++++ 4 files changed, 28 insertions(+) diff --git a/xuanxuan/extension/xuan/message/ext/lang/de/xuanxuan.php b/xuanxuan/extension/xuan/message/ext/lang/de/xuanxuan.php index 8fbd39f334..73807b5a85 100644 --- a/xuanxuan/extension/xuan/message/ext/lang/de/xuanxuan.php +++ b/xuanxuan/extension/xuan/message/ext/lang/de/xuanxuan.php @@ -8,6 +8,13 @@ $lang->message->notifyPassTitle = '%s passed %d stories'; $lang->message->notifyClarifyTitle = '%s clarify %d stories'; $lang->message->notifyRejectTitle = '%s reject %d stories'; +$lang->message->feedbackToBugTitle = '%s have forwarded %d feedback to bug'; +$lang->message->feedbackToTaskTitle = '%s have forwarded %d feedback to task'; +$lang->message->feedbackToDoTitle = '%s have forwarded %d feedback to todo'; +$lang->message->feedbackToStoryTitle = '%s have forwarded %d feedback to story'; + +$lang->message->reviewToauditTitle = '%s have submit %d audits'; + $lang->message->mr = new stdClass(); $lang->message->mr->logTitle = 'Build log'; $lang->message->mr->compilefail = 'Your submitted merge request: %s, build failed'; diff --git a/xuanxuan/extension/xuan/message/ext/lang/en/xuanxuan.php b/xuanxuan/extension/xuan/message/ext/lang/en/xuanxuan.php index 8fbd39f334..73807b5a85 100644 --- a/xuanxuan/extension/xuan/message/ext/lang/en/xuanxuan.php +++ b/xuanxuan/extension/xuan/message/ext/lang/en/xuanxuan.php @@ -8,6 +8,13 @@ $lang->message->notifyPassTitle = '%s passed %d stories'; $lang->message->notifyClarifyTitle = '%s clarify %d stories'; $lang->message->notifyRejectTitle = '%s reject %d stories'; +$lang->message->feedbackToBugTitle = '%s have forwarded %d feedback to bug'; +$lang->message->feedbackToTaskTitle = '%s have forwarded %d feedback to task'; +$lang->message->feedbackToDoTitle = '%s have forwarded %d feedback to todo'; +$lang->message->feedbackToStoryTitle = '%s have forwarded %d feedback to story'; + +$lang->message->reviewToauditTitle = '%s have submit %d audits'; + $lang->message->mr = new stdClass(); $lang->message->mr->logTitle = 'Build log'; $lang->message->mr->compilefail = 'Your submitted merge request: %s, build failed'; diff --git a/xuanxuan/extension/xuan/message/ext/lang/fr/xuanxuan.php b/xuanxuan/extension/xuan/message/ext/lang/fr/xuanxuan.php index 8fbd39f334..73807b5a85 100644 --- a/xuanxuan/extension/xuan/message/ext/lang/fr/xuanxuan.php +++ b/xuanxuan/extension/xuan/message/ext/lang/fr/xuanxuan.php @@ -8,6 +8,13 @@ $lang->message->notifyPassTitle = '%s passed %d stories'; $lang->message->notifyClarifyTitle = '%s clarify %d stories'; $lang->message->notifyRejectTitle = '%s reject %d stories'; +$lang->message->feedbackToBugTitle = '%s have forwarded %d feedback to bug'; +$lang->message->feedbackToTaskTitle = '%s have forwarded %d feedback to task'; +$lang->message->feedbackToDoTitle = '%s have forwarded %d feedback to todo'; +$lang->message->feedbackToStoryTitle = '%s have forwarded %d feedback to story'; + +$lang->message->reviewToauditTitle = '%s have submit %d audits'; + $lang->message->mr = new stdClass(); $lang->message->mr->logTitle = 'Build log'; $lang->message->mr->compilefail = 'Your submitted merge request: %s, build failed'; diff --git a/xuanxuan/extension/xuan/message/ext/lang/zh-cn/xuanxuan.php b/xuanxuan/extension/xuan/message/ext/lang/zh-cn/xuanxuan.php index 7503db0276..2d71146eab 100644 --- a/xuanxuan/extension/xuan/message/ext/lang/zh-cn/xuanxuan.php +++ b/xuanxuan/extension/xuan/message/ext/lang/zh-cn/xuanxuan.php @@ -8,6 +8,13 @@ $lang->message->notifyPassTitle = '%s 通过了%d个研发需求'; $lang->message->notifyClarifyTitle = '%s 驳回了%d个研发需求'; $lang->message->notifyRejectTitle = '%s 拒绝了%d个研发需求'; +$lang->message->feedbackToBugTitle = '%s 已将%d个反馈转至bug'; +$lang->message->feedbackToTaskTitle = '%s 已将%d个反馈转至任务'; +$lang->message->feedbackToDoTitle = '%s 已将%d个反馈转至待办'; +$lang->message->feedbackToStoryTitle = '%s 已将%d个反馈转至研发需求'; + +$lang->message->reviewToauditTitle = '%s 已经提交了%d个审计'; + $lang->message->mr = new stdClass(); $lang->message->mr->logTitle = '构建日志'; $lang->message->mr->compilefail = '您提交的合并请求:%s,构建任务执行失败'; From d807c2d0d1ef882358fbd18735af3eb9843e27d4 Mon Sep 17 00:00:00 2001 From: chaideqing Date: Wed, 28 Sep 2022 16:54:01 +0800 Subject: [PATCH 003/608] * fix delete user show dialog abnormal in zentao client --- module/user/css/delete.css | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 module/user/css/delete.css diff --git a/module/user/css/delete.css b/module/user/css/delete.css new file mode 100644 index 0000000000..21e3b77e30 --- /dev/null +++ b/module/user/css/delete.css @@ -0,0 +1,4 @@ +.xxc-embed.body-modal #mainContent { + position: relative; + top: 70px; +} \ No newline at end of file From 9637c6d3030461983922fb08f2ddbbaba5004d52 Mon Sep 17 00:00:00 2001 From: jyeu Date: Thu, 29 Sep 2022 16:20:02 +0800 Subject: [PATCH 004/608] * add an exception for approval flow notifications. --- .../extension/xuan/im/ext/model/class/xuanxuan.class.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xuanxuan/extension/xuan/im/ext/model/class/xuanxuan.class.php b/xuanxuan/extension/xuan/im/ext/model/class/xuanxuan.class.php index 8391277656..d1074e6e53 100644 --- a/xuanxuan/extension/xuan/im/ext/model/class/xuanxuan.class.php +++ b/xuanxuan/extension/xuan/im/ext/model/class/xuanxuan.class.php @@ -214,11 +214,16 @@ class xuanxuanIm extends imModel $messageGroups[$contentData->contentType][] = $message; continue; } - if ($contentData->objectType == 'story' && $contentData->action == 'reviewed') + if($contentData->objectType == 'story' && $contentData->action == 'reviewed') { $extra = explode(',', $contentDataOuter->extra)[0]; $messageGroups["$contentData->objectType-$contentData->parentType-$contentData->action-$contentData->actor-$extra"][] = $message; } + if($message->contentType == 'text') + { + $messageGroups['text'][] = $message; + continue; + } else { $messageGroups["$contentData->objectType-$contentData->parentType-$contentData->action-$contentData->actor"][] = $message; From 98bb2938b77cf8fb2c670ea79a6dc74345ddcedc Mon Sep 17 00:00:00 2001 From: denghongtao Date: Mon, 10 Oct 2022 01:36:40 +0000 Subject: [PATCH 005/608] Add repo unittest. --- test/class/repo.class.php | 22 ++++++++++++++++++---- test/model/repo/getcloneurl.php | 15 ++++++++++++++- test/model/repo/getlistbyscm.php | 7 ++++++- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/test/class/repo.class.php b/test/class/repo.class.php index 7ed1021ee4..85ced91220 100644 --- a/test/class/repo.class.php +++ b/test/class/repo.class.php @@ -43,20 +43,34 @@ class repoTest public function getListTest($projectID = 0, $SCM = '', $orderBy = 'id_desc', $pager = null) { - $objects = $this->objectModel->getList($projectID, $SCM, $orderBy, $pager); + $objects = $this->objectModel->getList($projectID , $SCM, $orderBy , $pager ); if(dao::isError()) return dao::getError(); - return $objects; + if(!empty($objects)) + { + return $objects[1]->name; + } + else + { + return 'empty'; + } } public function getListBySCMTest($scm, $type = 'all') { - $objects = $this->objectModel->getListBySCM($scm, $type); + $objects = $this->objectModel->getListBySCM($scm, $type = 'all'); if(dao::isError()) return dao::getError(); - return $objects; + if(!empty($objects)) + { + return $objects[0]->name; + } + else + { + return 'empty'; + } } public function createTest() diff --git a/test/model/repo/getcloneurl.php b/test/model/repo/getcloneurl.php index 0cb095ca1c..8ec0ae5734 100644 --- a/test/model/repo/getcloneurl.php +++ b/test/model/repo/getcloneurl.php @@ -13,5 +13,18 @@ pid=1 */ $repo = new repoTest(); +$result1 = $repo->getCloneUrlTest(1); +$result2 = $repo->getCloneUrlTest(2); +$result3 = $repo->getCloneUrlTest(3); +$result4 = $repo->getCloneUrlTest(4); +$result5 = $repo->getCloneUrlTest(7); +$result6 = $repo->getCloneUrlTest(11); +$result7 = $repo->getCloneUrlTest(0); -r($repo->getCloneUrlTest()) && p() && e(); \ No newline at end of file +r($result1) && p('http') && e(''); +r($result2) && p('http') && e(''); +r($result3) && p('http') && e(''); +r($result4) && p('http') && e(''); +r($result5) && p('http') && e(''); +r($result6) && p('http') && e(''); +r($result7) && p('http') && e(''); diff --git a/test/model/repo/getlistbyscm.php b/test/model/repo/getlistbyscm.php index ad618ee52b..d5f4a2b09e 100644 --- a/test/model/repo/getlistbyscm.php +++ b/test/model/repo/getlistbyscm.php @@ -13,5 +13,10 @@ pid=1 */ $repo = new repoTest(); +$result1 = $repo->getListBySCMTest('Gitlab'); +$result2 = $repo->getListBySCMTest('gogs'); +$result3 = $repo->getListBySCMTest('empty'); -r($repo->getListBySCMTest()) && p() && e(); \ No newline at end of file +r($result1) && p('') && e('723test'); +r($result2) && p('') && e('empty'); +r($result3) && p('') && e('empty'); From 3e953772b9700f25d3c0b23f0fa9d2130c44424d Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Tue, 18 Oct 2022 16:01:56 +0800 Subject: [PATCH 006/608] * Refactor codes to extend the export fields and the editor fields by workflow. --- framework/control.class.php | 95 +++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/framework/control.class.php b/framework/control.class.php index 209cf5fb76..e2c6d700d1 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -42,48 +42,71 @@ class control extends baseControl /* Code for task #9224. Set requiredFields for workflow. */ if($this->dbh and (defined('IN_USE') or (defined('RUN_MODE') and RUN_MODE == 'api'))) { - if(isset($this->config->{$this->moduleName}) and strpos($this->methodName, 'export') !== false) - { - if(isset($this->config->{$this->moduleName}->exportFields) or isset($this->config->{$this->moduleName}->list->exportFields)) - { - $exportFields = $this->dao->select('*')->from(TABLE_WORKFLOWFIELD)->where('module')->eq($this->moduleName)->andWhere('canExport')->eq('1')->andWhere('buildin')->eq('0')->fetchAll('field'); - - if(isset($this->config->{$this->moduleName}->exportFields)) - { - foreach($exportFields as $field) $this->config->{$this->moduleName}->exportFields .= ",{$field->field}"; - } - - if(isset($this->config->{$this->moduleName}->list->exportFields)) - { - foreach($exportFields as $field) $this->config->{$this->moduleName}->list->exportFields .= ",{$field->field}"; - } - - foreach($exportFields as $flowField => $exportField) - { - if(!isset($this->lang->{$this->moduleName}->$flowField)) $this->lang->{$this->moduleName}->$flowField = $exportField->name; - } - } - } - - /* Append editor field to this module config from workflow. */ - $textareaFields = $this->dao->select('*')->from(TABLE_WORKFLOWFIELD)->where('module')->eq($this->moduleName)->andWhere('control')->eq('richtext')->andWhere('buildin')->eq('0')->fetchAll('field'); - if($textareaFields) - { - $editorIdList = array(); - foreach($textareaFields as $textareaField) $editorIdList[] = $textareaField->field; - - if(!isset($this->config->{$this->moduleName})) $this->config->{$this->moduleName} = new stdclass(); - if(!isset($this->config->{$this->moduleName}->editor)) $this->config->{$this->moduleName}->editor = new stdclass(); - if(!isset($this->config->{$this->moduleName}->editor->{$this->methodName})) $this->config->{$this->moduleName}->editor->{$this->methodName} = array('id' => '', 'tools' => 'simpleTools'); - $this->config->{$this->moduleName}->editor->{$this->methodName}['id'] .= ',' . join(',', $editorIdList); - trim($this->config->{$this->moduleName}->editor->{$this->methodName}['id'], ','); - } + $this->extendExportFields(); + $this->extendEditorFields(); /* If workflow is created by a normal user, set priv. */ if(isset($this->app->user) and !$this->app->user->admin) $this->setDefaultPrivByWorkflow(); } } + /** + * Append export fields to the config of this module from workflow. + * + * @access public + * @return void + */ + public function extendExportFields() + { + if(isset($this->config->{$this->moduleName}) and strpos($this->methodName, 'export') !== false) + { + if(isset($this->config->{$this->moduleName}->exportFields) or isset($this->config->{$this->moduleName}->list->exportFields)) + { + $exportFields = $this->dao->select('*')->from(TABLE_WORKFLOWFIELD)->where('module')->eq($this->moduleName)->andWhere('canExport')->eq('1')->andWhere('buildin')->eq('0')->fetchAll('field'); + + if(isset($this->config->{$this->moduleName}->exportFields)) + { + foreach($exportFields as $field) $this->config->{$this->moduleName}->exportFields .= ",{$field->field}"; + } + + if(isset($this->config->{$this->moduleName}->list->exportFields)) + { + foreach($exportFields as $field) $this->config->{$this->moduleName}->list->exportFields .= ",{$field->field}"; + } + + foreach($exportFields as $flowField => $exportField) + { + if(!isset($this->lang->{$this->moduleName}->$flowField)) $this->lang->{$this->moduleName}->$flowField = $exportField->name; + } + } + } + } + + /** + * Append editor fields to the config of this module from workflow. + * + * @access public + * @return void + */ + public function extendEditorFields() + { + $moduleName = $this->moduleName; + $methodName = $this->methodName; + + $textareaFields = $this->dao->select('*')->from(TABLE_WORKFLOWFIELD)->where('module')->eq($this->moduleName)->andWhere('control')->eq('richtext')->andWhere('buildin')->eq('0')->fetchAll('field'); + if($textareaFields) + { + $editorIdList = array(); + foreach($textareaFields as $textareaField) $editorIdList[] = $textareaField->field; + + if(!isset($this->config->{$moduleName})) $this->config->{$moduleName} = new stdclass(); + if(!isset($this->config->{$moduleName}->editor)) $this->config->{$moduleName}->editor = new stdclass(); + if(!isset($this->config->{$moduleName}->editor->{$methodName})) $this->config->{$moduleName}->editor->{$methodName} = array('id' => '', 'tools' => 'simpleTools'); + $this->config->{$moduleName}->editor->{$methodName}['id'] .= ',' . join(',', $editorIdList); + trim($this->config->{$moduleName}->editor->{$methodName}['id'], ','); + } + } + /** * Det default priv by workflow. * From ca19766cbc815ae4ff76c4a86991d2f7bfaff6bc Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Tue, 18 Oct 2022 16:14:48 +0800 Subject: [PATCH 007/608] * Refactor functions to support loading the zen files and the tao files. --- framework/base/control.class.php | 34 +++++++++++++++++--------------- framework/base/model.class.php | 24 +++++++++++----------- framework/base/router.class.php | 24 +++++++++++----------- 3 files changed, 43 insertions(+), 39 deletions(-) diff --git a/framework/base/control.class.php b/framework/base/control.class.php index 1576843b29..7ea4882f38 100644 --- a/framework/base/control.class.php +++ b/framework/base/control.class.php @@ -270,20 +270,22 @@ class baseControl * @access public * @return object|bool 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object. */ - public function loadModel($moduleName = '', $appName = '') + public function loadModel($moduleName = '', $appName = '', $type = 'model') { if(empty($moduleName)) $moduleName = $this->moduleName; if(empty($appName)) $appName = $this->appName; + $objectName = $type == 'model' ? $moduleName : $moduleName . ucfirst($type); + global $loadedModels; - if(isset($loadedModels[$appName][$moduleName])) + if(isset($loadedModels[$type][$appName][$moduleName])) { - $this->$moduleName = $loadedModels[$appName][$moduleName]; - $this->dao = $this->$moduleName->dao; - return $this->$moduleName; + $this->$objectName = $loadedModels[$type][$appName][$moduleName]; + $this->dao = $this->$objectName->dao; + return $this->$objectName; } - $modelFile = $this->app->setModelFile($moduleName, $appName); + $modelFile = $this->app->setModelFile($moduleName, $appName, $type); /** * 如果没有model文件,尝试加载config配置信息。 @@ -298,24 +300,24 @@ class baseControl } /** - * 如果没有扩展文件,model类名是$moduleName + 'model',如果有扩展,还需要增加ext前缀。 - * If no extension file, model class name is $moduleName + 'model', else with 'ext' as the prefix. + * 如果没有扩展文件,model类名是$moduleName + $type,如果有扩展,还需要增加ext前缀。 + * If no extension file, model class name is $moduleName + $type, else with 'ext' as the prefix. */ - $modelClass = class_exists('ext' . $appName . $moduleName . 'model') ? 'ext' . $appName . $moduleName . 'model' : $appName . $moduleName . 'model'; + $modelClass = class_exists('ext' . $appName . $moduleName . $type) ? 'ext' . $appName . $moduleName . $type : $appName . $moduleName . $type; if(!class_exists($modelClass)) { - $modelClass = class_exists('ext' . $moduleName . 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model'; - if(!class_exists($modelClass)) $this->app->triggerError(" The model $modelClass not found", __FILE__, __LINE__, $exit = true); + $modelClass = class_exists('ext' . $moduleName . $type) ? 'ext' . $moduleName . $type : $moduleName . $type; + if(!class_exists($modelClass)) $this->app->triggerError(" The $type $modelClass not found", __FILE__, __LINE__, $exit = true); } /** - * 初始化model对象,在control对象中可以通过$this->$moduleName来引用。同时将dao对象赋为control对象的成员变量,方便引用。 - * Init the model object thus you can try $this->$moduleName to access it. Also assign the $dao object as a member of control object. + * 初始化model对象,在control对象中可以通过$this->$objectName来引用。同时将dao对象赋为control对象的成员变量,方便引用。 + * Init the model object thus you can try $this->$objectName to access it. Also assign the $dao object as a member of control object. */ $loadedModels[$appName][$moduleName] = new $modelClass($appName); - $this->$moduleName = $loadedModels[$appName][$moduleName]; - $this->dao = $this->$moduleName->dao; - return $this->$moduleName; + $this->$objectName = $loadedModels[$appName][$moduleName]; + $this->dao = $this->$objectName->dao; + return $this->$objectName; } /** diff --git a/framework/base/model.class.php b/framework/base/model.class.php index 37f53b06e5..116b9e15b3 100644 --- a/framework/base/model.class.php +++ b/framework/base/model.class.php @@ -203,32 +203,34 @@ class baseModel * @access public * @return object|bool the model object or false if model file not exists. */ - public function loadModel($moduleName, $appName = '') + public function loadModel($moduleName, $appName = '', $type = 'model') { if(empty($moduleName)) return false; if(empty($appName)) $appName = $this->appName; $moduleName = strtolower($moduleName); + $objectName = $type == 'model' ? $moduleName : $moduleName . ucfirst($type); + global $loadedModels; - if(isset($loadedModels[$appName][$moduleName])) + if(isset($loadedModels[$type][$appName][$moduleName])) { - $this->$moduleName = $loadedModels[$appName][$moduleName]; - return $this->$moduleName; + $this->$objectName = $loadedModels[$type][$appName][$moduleName]; + return $this->$objectName; } - $modelFile = $this->app->setModelFile($moduleName, $appName); + $modelFile = $this->app->setModelFile($moduleName, $appName, $type); if(!helper::import($modelFile)) return false; - $modelClass = class_exists('ext' . $appName . $moduleName. 'model') ? 'ext' . $appName . $moduleName . 'model' : $appName . $moduleName . 'model'; + $modelClass = class_exists('ext' . $appName . $moduleName. $type) ? 'ext' . $appName . $moduleName . $type : $appName . $moduleName . $type; if(!class_exists($modelClass)) { - $modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model'; - if(!class_exists($modelClass)) $this->app->triggerError(" The model $modelClass not found", __FILE__, __LINE__, $exit = true); + $modelClass = class_exists('ext' . $moduleName. $type) ? 'ext' . $moduleName . $type : $moduleName . $type; + if(!class_exists($modelClass)) $this->app->triggerError(" The $type $modelClass not found", __FILE__, __LINE__, $exit = true); } - $loadedModels[$appName][$moduleName] = new $modelClass($appName); - $this->$moduleName = $loadedModels[$appName][$moduleName]; - return $this->$moduleName; + $loadedModels[$type][$appName][$moduleName] = new $modelClass($appName); + $this->$objectName = $loadedModels[$type][$appName][$moduleName]; + return $this->$objectName; } /** diff --git a/framework/base/router.class.php b/framework/base/router.class.php index 84df7b4d85..23525391b7 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -1781,12 +1781,12 @@ class baseRouter * @access public * @return string the model file */ - public function setModelFile($moduleName, $appName = '') + public function setModelFile($moduleName, $appName = '', $type = 'model') { if($appName == '') $appName = $this->getAppName(); /* 设置主model文件。 Set the main model file. */ - $mainModelFile = $this->getModulePath($appName, $moduleName) . 'model.php'; + $mainModelFile = $this->getModulePath($appName, $moduleName) . "{$type}.php"; if($this->config->framework->extensionLevel == 0) return $mainModelFile; /* 计算扩展的文件和hook文件。Compute the extension files and hook files. */ @@ -1795,7 +1795,7 @@ class baseRouter $apiFiles = array(); $siteExtended = false; - $modelExtPaths = $this->getModuleExtPath($appName, $moduleName, 'model'); + $modelExtPaths = $this->getModuleExtPath($appName, $moduleName, $type); foreach($modelExtPaths as $extType => $modelExtPath) { if(empty($modelExtPath)) continue; @@ -1817,7 +1817,7 @@ class baseRouter $extModelPrefix = $this->config->edition . DS . $this->config->vision . DS; if($siteExtended and !empty($this->siteCode)) $extModelPrefix .= $this->siteCode[0] . DS . $this->siteCode; - $mergedModelDir = $this->getTmpRoot() . 'model' . DS . $extModelPrefix; + $mergedModelDir = $this->getTmpRoot() . $type . DS . $extModelPrefix; $mergedModelFile = $mergedModelDir . $moduleName . '.php'; if(!is_dir($mergedModelDir)) mkdir($mergedModelDir, 0755, true); @@ -1825,8 +1825,8 @@ class baseRouter if(!$this->needModelFileUpdate($mergedModelFile, $extFiles, $hookFiles, $apiFiles, $modelExtPaths, $mainModelFile)) return $mergedModelFile; /* 合并扩展和hook文件。Merge the extension and hook files. */ - $modelLines = $this->mergeModelExtFiles($moduleName, $mainModelFile, $extFiles, $mergedModelDir); - $this->mergeModelHookFiles($moduleName, $mainModelFile, $modelLines, $hookFiles, $mergedModelDir, $mergedModelFile, $apiFiles); + $modelLines = $this->mergeModelExtFiles($moduleName, $extFiles, $mergedModelDir, $type); + $this->mergeModelHookFiles($moduleName, $mainModelFile, $modelLines, $hookFiles, $mergedModelDir, $mergedModelFile, $apiFiles, $type); return $mergedModelFile; } @@ -1873,22 +1873,22 @@ class baseRouter * 将model的扩展文件合并在一起。Merge model ext files. * * @param string $moduleName - * @param string $mainModelFile * @param array $extFiles * @param string $mergedModelDir + * @param string $type * @access public * @return void */ - public function mergeModelExtFiles($moduleName, $mainModelFile, $extFiles, $mergedModelDir) + public function mergeModelExtFiles($moduleName, $extFiles, $mergedModelDir, $type = 'model') { /* 设置类名。Set the class names. */ - $modelClass = "{$moduleName}Model"; + $modelClass = $moduleName . ucfirst($type); $tmpModelClass = "tmpExt$modelClass"; /* 开始拼装代码。Prepare the codes. */ $modelLines = "getModulePath('', '$moduleName') . " . "'model.php');\n"; + $modelLines .= "helper::import(\$app->getModulePath('', '$moduleName') . " . "'$type.php');\n"; $modelLines .= "class $tmpModelClass extends $modelClass \n{\n"; /* 将扩展文件的代码合并到代码中。Cycle all the extension files and merge them into model lines. */ @@ -1917,10 +1917,10 @@ class baseRouter * @access public * @return void */ - public function mergeModelHookFiles($moduleName, $mainModelFile, $modelLines, $hookFiles, $mergedModelDir, $mergedModelFile, $apiFiles) + public function mergeModelHookFiles($moduleName, $mainModelFile, $modelLines, $hookFiles, $mergedModelDir, $mergedModelFile, $apiFiles, $type = 'model') { /* 定义相关变量。Init vars. */ - $modelClass = $moduleName . 'Model'; + $modelClass = $moduleName . ucfirst($type); $extModelClass = 'ext' . $modelClass; $tmpModelClass = 'tmpExt' . $modelClass; $tmpModelFile = $mergedModelDir . "tmp$moduleName.php"; From 8dce21799fa32ac1b6921ead5e75e90f698eefe4 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Tue, 18 Oct 2022 16:28:10 +0800 Subject: [PATCH 008/608] * Optimize the codes of loadModel function. --- framework/base/control.class.php | 8 ++++---- framework/base/model.class.php | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/framework/base/control.class.php b/framework/base/control.class.php index 7ea4882f38..0a74fdc745 100644 --- a/framework/base/control.class.php +++ b/framework/base/control.class.php @@ -281,7 +281,7 @@ class baseControl if(isset($loadedModels[$type][$appName][$moduleName])) { $this->$objectName = $loadedModels[$type][$appName][$moduleName]; - $this->dao = $this->$objectName->dao; + if($type == 'model') $this->dao = $this->$objectName->dao; return $this->$objectName; } @@ -314,9 +314,9 @@ class baseControl * 初始化model对象,在control对象中可以通过$this->$objectName来引用。同时将dao对象赋为control对象的成员变量,方便引用。 * Init the model object thus you can try $this->$objectName to access it. Also assign the $dao object as a member of control object. */ - $loadedModels[$appName][$moduleName] = new $modelClass($appName); - $this->$objectName = $loadedModels[$appName][$moduleName]; - $this->dao = $this->$objectName->dao; + $this->$objectName = new $modelClass($appName); + if($type == 'model') $this->dao = $this->$objectName->dao; + $loadedModels[$type][$appName][$moduleName] = $this->$objectName; return $this->$objectName; } diff --git a/framework/base/model.class.php b/framework/base/model.class.php index 116b9e15b3..6529dcdf0a 100644 --- a/framework/base/model.class.php +++ b/framework/base/model.class.php @@ -221,6 +221,7 @@ class baseModel $modelFile = $this->app->setModelFile($moduleName, $appName, $type); if(!helper::import($modelFile)) return false; + $modelClass = class_exists('ext' . $appName . $moduleName. $type) ? 'ext' . $appName . $moduleName . $type : $appName . $moduleName . $type; if(!class_exists($modelClass)) { @@ -228,8 +229,8 @@ class baseModel if(!class_exists($modelClass)) $this->app->triggerError(" The $type $modelClass not found", __FILE__, __LINE__, $exit = true); } - $loadedModels[$type][$appName][$moduleName] = new $modelClass($appName); - $this->$objectName = $loadedModels[$type][$appName][$moduleName]; + $this->$objectName = new $modelClass($appName); + $loadedModels[$type][$appName][$moduleName] = $this->$objectName; return $this->$objectName; } From 30080999766866e38d483366c426e9f44f80ba7e Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Tue, 18 Oct 2022 16:31:24 +0800 Subject: [PATCH 009/608] * Load the zen file and the tao file. --- framework/control.class.php | 8 +++++--- framework/model.class.php | 23 +++++++++++++++++++++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/framework/control.class.php b/framework/control.class.php index e2c6d700d1..4f4d20df4a 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -33,6 +33,9 @@ class control extends baseControl { parent::__construct($moduleName, $methodName, $appName); + $className = get_class($this); + if(strtolower(substr($className, -6)) == 'control') $this->loadModel($moduleName, $appName, 'zen'); + $this->app->setOpenApp(); if(defined('IN_USE') or (defined('RUN_MODE') and RUN_MODE != 'api')) $this->setPreference(); @@ -179,9 +182,9 @@ class control extends baseControl * @access public * @return object|bool 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object. */ - public function loadModel($moduleName = '', $appName = '') + public function loadModel($moduleName = '', $appName = '', $type = 'model') { - return parent::loadModel($moduleName); + return parent::loadModel($moduleName, '', $type); } /** @@ -575,5 +578,4 @@ class control extends baseControl } if($message) $this->send(array('result' => 'fail', 'message' => $message)); } - } diff --git a/framework/model.class.php b/framework/model.class.php index 45c14dba1e..c9f7604d77 100644 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -20,6 +20,25 @@ include dirname(__FILE__) . '/base/model.class.php'; class model extends baseModel { + /** + * Load the tao file. + * + * @param string $appName + * @access public + * @return void + */ + public function __construct($appName = '') + { + parent::__construct($appName); + + $className = get_class($this); + if(strtolower(substr($className, -5)) == 'model') + { + $moduleName = $this->app->getModuleName(); + $this->loadModel($moduleName, $appName, 'tao'); + } + } + /** * 企业版部分功能是从然之合并过来的。然之代码中调用loadModel方法时传递了一个非空的appName,在禅道中会导致错误。 * 调用父类的loadModel方法来避免这个错误。 @@ -30,9 +49,9 @@ class model extends baseModel * @access public * @return object|bool the model object or false if model file not exists. */ - public function loadModel($moduleName, $appName = '') + public function loadModel($moduleName, $appName = '', $type = 'model') { - return parent::loadModel($moduleName); + return parent::loadModel($moduleName, '', $type); } /** From b9b8b6e584c53354bccd6e0d263a961d45e347a0 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Tue, 18 Oct 2022 16:32:26 +0800 Subject: [PATCH 010/608] * Add functions to call the methods declared in the zen files and the tao files. --- framework/control.class.php | 37 +++++++++++++++++++++++++++++++++++++ framework/model.class.php | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/framework/control.class.php b/framework/control.class.php index 4f4d20df4a..c97478b09d 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -578,4 +578,41 @@ class control extends baseControl } if($message) $this->send(array('result' => 'fail', 'message' => $message)); } + + /** + * Call the functions declared in the tao files. + * + * @param string $method + * @param array $arguments + * @access public + * @return mixed + */ + public function __call($method, $arguments) + { + $moduleName = $this->app->getModuleName(); + $taoClass = $moduleName . 'Tao'; + + if(!is_callable(array($this->{$taoClass}, $method))) $this->app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); + + return call_user_func_array(array($this->{$taoClass}, $method), $arguments); + } + + /** + * Call the static functions declared in the tao files. + * + * @param string $method + * @param array $arguments + * @access public + * @return mixed + */ + public static function __callStatic($method, $arguments) + { + global $app; + $moduleName = $app->getModuleName(); + $taoClass = $moduleName . 'Tao'; + + if(!is_callable("{$taoClass}::{$method}")) $app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); + + return call_user_func_array("{$taoClass}::{$method}", $arguments); + } } diff --git a/framework/model.class.php b/framework/model.class.php index c9f7604d77..c4d606f08a 100644 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -339,4 +339,41 @@ class model extends baseModel $flow = $this->loadModel('workflow')->getByModule($moduleName); if($flow && $action) return $this->loadModel('workflowhook')->execute($flow, $action, $objectID); } + + /** + * Call the functions declared in the tao files. + * + * @param string $method + * @param array $arguments + * @access public + * @return mixed + */ + public function __call($method, $arguments) + { + $moduleName = $this->app->getModuleName(); + $taoClass = $moduleName . 'Tao'; + + if(!is_callable(array($this->{$taoClass}, $method))) $this->app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); + + return call_user_func_array(array($this->{$taoClass}, $method), $arguments); + } + + /** + * Call the static functions declared in the tao files. + * + * @param string $method + * @param array $arguments + * @access public + * @return mixed + */ + public static function __callStatic($method, $arguments) + { + global $app; + $moduleName = $app->getModuleName(); + $taoClass = $moduleName . 'Tao'; + + if(!is_callable("{$taoClass}::{$method}")) $app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); + + return call_user_func_array("{$taoClass}::{$method}", $arguments); + } } From 8d961926a4798cc7699583ec2249887eebb1b852 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Tue, 18 Oct 2022 16:45:52 +0800 Subject: [PATCH 011/608] * Adjust the comments. --- framework/base/control.class.php | 7 ++++--- framework/base/model.class.php | 8 +++++--- framework/base/router.class.php | 12 ++++++------ framework/control.class.php | 13 +++++++------ framework/model.class.php | 12 +++++++----- 5 files changed, 29 insertions(+), 23 deletions(-) diff --git a/framework/base/control.class.php b/framework/base/control.class.php index 0a74fdc745..af56e1572c 100644 --- a/framework/base/control.class.php +++ b/framework/base/control.class.php @@ -266,9 +266,10 @@ class baseControl * Load the model file of one module. * * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. - * @param string $appName The app name, if empty, use current app's name. - * @access public - * @return object|bool 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object. + * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. + * @param string $type 对象的类型,可选值 model、zen、tao,默认为 model。The type of the object, optional values model, zen, tao, the default is model. + * @access public + * @return object|bool 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object. */ public function loadModel($moduleName = '', $appName = '', $type = 'model') { diff --git a/framework/base/model.class.php b/framework/base/model.class.php index 6529dcdf0a..716da9c3dd 100644 --- a/framework/base/model.class.php +++ b/framework/base/model.class.php @@ -199,9 +199,11 @@ class baseModel * * Load the model of one module. After loaded, can use $this->$moduleName to visit the model object. * - * @param string $moduleName - * @access public - * @return object|bool the model object or false if model file not exists. + * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. + * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. + * @param string $type 对象的类型,可选值 model、zen、tao,默认为 model。The type of the object, optional values model, zen, tao, the default is model. + * @access public + * @return object|bool the model object or false if model file not exists. */ public function loadModel($moduleName, $appName = '', $type = 'model') { diff --git a/framework/base/router.class.php b/framework/base/router.class.php index 23525391b7..d991bdc01f 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -1623,7 +1623,7 @@ class baseRouter * * @param string $appName the app name * @param string $moduleName the module name - * @param string $ext the extension type, can be control|model|view|lang|config + * @param string $ext the extension type, can be control|model|view|lang|config|zen|tao * @access public * @return string the extension path. */ @@ -1775,11 +1775,11 @@ class baseRouter * 设置一个模块的model文件,如果存在model扩展,一起合并。 * Set the model file of one module. If there's an extension file, merge it with the main model file. * - * @param string $moduleName the module name - * @param string $appName the app name - * @static - * @access public - * @return string the model file + * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. + * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. + * @param string $type 对象的类型,可选值 model、zen、tao,默认为 model。The type of the object, optional values model, zen, tao, the default is model. + * @access public + * @return string the model file */ public function setModelFile($moduleName, $appName = '', $type = 'model') { diff --git a/framework/control.class.php b/framework/control.class.php index c97478b09d..d10c16c270 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -172,15 +172,16 @@ class control extends baseControl } /** - * 企业版部分功能是从然之合并过来的。然之代码中调用loadModel方法时传递了一个非空的appName,在禅道中会导致错误。 + * 企业版部分功能是从然之合并过来的。ZDOO代码中调用loadModel方法时传递了一个非空的appName,在禅道中会导致错误。 * 调用父类的loadModel方法来避免这个错误。 - * Some codes merged from ranzhi called the function loadModel with a non-empty appName which causes an error in zentao. + * Some codes merged from ZDOO called the function loadModel with a non-empty appName which causes an error in zentao. * Call the parent function with empty appName to avoid this error. * - * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. - * @param string $appName The app name, if empty, use current app's name. - * @access public - * @return object|bool 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object. + * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. + * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. + * @param string $type 对象的类型,可选值 model、zen、tao,默认为 model。The type of the object, optional values model, zen, tao, the default is model. + * @access public + * @return object|bool 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object. */ public function loadModel($moduleName = '', $appName = '', $type = 'model') { diff --git a/framework/model.class.php b/framework/model.class.php index c4d606f08a..80a7c5a450 100644 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -40,14 +40,16 @@ class model extends baseModel } /** - * 企业版部分功能是从然之合并过来的。然之代码中调用loadModel方法时传递了一个非空的appName,在禅道中会导致错误。 + * 企业版部分功能是从然之合并过来的。ZDOO代码中调用loadModel方法时传递了一个非空的appName,在禅道中会导致错误。 * 调用父类的loadModel方法来避免这个错误。 - * Some codes merged from ranzhi called the function loadModel with a non-empty appName which causes an error in zentao. + * Some codes merged from ZDOO called the function loadModel with a non-empty appName which causes an error in zentao. * Call the parent function with empty appName to avoid this error. * - * @param string $moduleName - * @access public - * @return object|bool the model object or false if model file not exists. + * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. + * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. + * @param string $type 对象的类型,可选值 model、zen、tao,默认为 model。The type of the object, optional values model, zen, tao, the default is model. + * @access public + * @return object|bool the model object or false if model file not exists. */ public function loadModel($moduleName, $appName = '', $type = 'model') { From 01ac19f6e50910e1ad2d78e908f602114347219f Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Tue, 18 Oct 2022 17:19:18 +0800 Subject: [PATCH 012/608] * Fix bug of load zen and tao. --- framework/control.class.php | 10 ++++++---- framework/model.class.php | 9 +++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/framework/control.class.php b/framework/control.class.php index d10c16c270..a766bb21b7 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -33,8 +33,10 @@ class control extends baseControl { parent::__construct($moduleName, $methodName, $appName); - $className = get_class($this); - if(strtolower(substr($className, -6)) == 'control') $this->loadModel($moduleName, $appName, 'zen'); + if(!$moduleName) $moduleName = $this->moduleName; + + $className = strtolower(get_class($this)); + if($className == $moduleName || $className == 'my' . $moduleName) $this->loadModel($moduleName, $appName, 'zen'); $this->app->setOpenApp(); @@ -591,7 +593,7 @@ class control extends baseControl public function __call($method, $arguments) { $moduleName = $this->app->getModuleName(); - $taoClass = $moduleName . 'Tao'; + $taoClass = $moduleName . 'Zen'; if(!is_callable(array($this->{$taoClass}, $method))) $this->app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); @@ -610,7 +612,7 @@ class control extends baseControl { global $app; $moduleName = $app->getModuleName(); - $taoClass = $moduleName . 'Tao'; + $taoClass = $moduleName . 'Zen'; if(!is_callable("{$taoClass}::{$method}")) $app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); diff --git a/framework/model.class.php b/framework/model.class.php index 80a7c5a450..8401f940f7 100644 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -31,12 +31,9 @@ class model extends baseModel { parent::__construct($appName); - $className = get_class($this); - if(strtolower(substr($className, -5)) == 'model') - { - $moduleName = $this->app->getModuleName(); - $this->loadModel($moduleName, $appName, 'tao'); - } + $className = strtolower(get_class($this)); + $moduleName = $this->app->getModuleName(); + if($className == $moduleName . 'model' || $className == 'ext' . $moduleName . 'model') $this->loadModel($moduleName, $appName, 'tao'); } /** From b0be2cd295c536b285ac9e678da41eda3a50f21f Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 19 Oct 2022 10:10:15 +0800 Subject: [PATCH 013/608] * Remove useless variable. --- framework/base/control.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/base/control.class.php b/framework/base/control.class.php index af56e1572c..34a6592f74 100644 --- a/framework/base/control.class.php +++ b/framework/base/control.class.php @@ -753,7 +753,6 @@ class baseControl $currentModuleName = $this->moduleName; $currentMethodName = $this->methodName; - $currentAppName = $this->appName; $currentParams = $this->app->getParams(); /** From 66d76e5d65d0c3ad2a30cee38c12a760db7a2649 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 19 Oct 2022 10:15:59 +0800 Subject: [PATCH 014/608] * Fix error if the zen file doesn't exist. --- framework/control.class.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/framework/control.class.php b/framework/control.class.php index a766bb21b7..9f66e76a7c 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -36,7 +36,12 @@ class control extends baseControl if(!$moduleName) $moduleName = $this->moduleName; $className = strtolower(get_class($this)); - if($className == $moduleName || $className == 'my' . $moduleName) $this->loadModel($moduleName, $appName, 'zen'); + if($className == $moduleName || $className == 'my' . $moduleName) + { + $this->loadModel($moduleName, $appName, 'zen'); + $zenClass = $moduleName . 'Zen'; + if(isset($this->{$zenClass})) $this->{$zenClass}->view = $this->view; + } $this->app->setOpenApp(); From 50c2fd653cb9444df4dd67b9d06641a8c0a63bea Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 19 Oct 2022 16:36:22 +0800 Subject: [PATCH 015/608] * Simplify the codes to load the tao file by the loadModel function. --- framework/model.class.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/model.class.php b/framework/model.class.php index 8401f940f7..b0f1205b23 100644 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -31,9 +31,8 @@ class model extends baseModel { parent::__construct($appName); - $className = strtolower(get_class($this)); $moduleName = $this->app->getModuleName(); - if($className == $moduleName . 'model' || $className == 'ext' . $moduleName . 'model') $this->loadModel($moduleName, $appName, 'tao'); + $this->loadModel($moduleName, $appName, 'tao'); } /** From f84694aa7c2f624e3766499a5b5fe8382449380d Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 19 Oct 2022 16:39:54 +0800 Subject: [PATCH 016/608] Simplify the codes to load the zen file by the loadModel function. --- framework/control.class.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/framework/control.class.php b/framework/control.class.php index 9f66e76a7c..1ce9f030ac 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -33,15 +33,7 @@ class control extends baseControl { parent::__construct($moduleName, $methodName, $appName); - if(!$moduleName) $moduleName = $this->moduleName; - - $className = strtolower(get_class($this)); - if($className == $moduleName || $className == 'my' . $moduleName) - { - $this->loadModel($moduleName, $appName, 'zen'); - $zenClass = $moduleName . 'Zen'; - if(isset($this->{$zenClass})) $this->{$zenClass}->view = $this->view; - } + $this->loadModel($moduleName, $appName, 'zen'); $this->app->setOpenApp(); From 12ad262e1de8595581959b2cd98a2917a24f25c2 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 19 Oct 2022 16:40:22 +0800 Subject: [PATCH 017/608] * Rename the $taoClass to the $zenClass. --- framework/control.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/framework/control.class.php b/framework/control.class.php index 1ce9f030ac..e939a56bb9 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -590,11 +590,11 @@ class control extends baseControl public function __call($method, $arguments) { $moduleName = $this->app->getModuleName(); - $taoClass = $moduleName . 'Zen'; + $zenClass = $moduleName . 'Zen'; - if(!is_callable(array($this->{$taoClass}, $method))) $this->app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); + if(!is_callable(array($this->{$zenClass}, $method))) $this->app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); - return call_user_func_array(array($this->{$taoClass}, $method), $arguments); + return call_user_func_array(array($this->{$zenClass}, $method), $arguments); } /** @@ -609,10 +609,10 @@ class control extends baseControl { global $app; $moduleName = $app->getModuleName(); - $taoClass = $moduleName . 'Zen'; + $zenClass = $moduleName . 'Zen'; - if(!is_callable("{$taoClass}::{$method}")) $app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); + if(!is_callable("{$zenClass}::{$method}")) $app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); - return call_user_func_array("{$taoClass}::{$method}", $arguments); + return call_user_func_array("{$zenClass}::{$method}", $arguments); } } From 0ec0e38a297b3fbe73e6e6bc3e26855ad9edbd2b Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 19 Oct 2022 16:40:58 +0800 Subject: [PATCH 018/608] * Refactor the loadModel function to support loading zen files and return zen object. --- framework/base/control.class.php | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/framework/base/control.class.php b/framework/base/control.class.php index 34a6592f74..149e9ed108 100644 --- a/framework/base/control.class.php +++ b/framework/base/control.class.php @@ -281,9 +281,9 @@ class baseControl global $loadedModels; if(isset($loadedModels[$type][$appName][$moduleName])) { - $this->$objectName = $loadedModels[$type][$appName][$moduleName]; - if($type == 'model') $this->dao = $this->$objectName->dao; - return $this->$objectName; + $this->{$objectName} = $loadedModels[$type][$appName][$moduleName]; + if($type == 'model') $this->dao = $this->{$objectName}->dao; + return $this->{$objectName}; } $modelFile = $this->app->setModelFile($moduleName, $appName, $type); @@ -312,12 +312,18 @@ class baseControl } /** - * 初始化model对象,在control对象中可以通过$this->$objectName来引用。同时将dao对象赋为control对象的成员变量,方便引用。 - * Init the model object thus you can try $this->$objectName to access it. Also assign the $dao object as a member of control object. + * 因为zen继承control,构造函数里会调用loadModel方法,赋默认值值防止递归调用。 */ - $this->$objectName = new $modelClass($appName); - if($type == 'model') $this->dao = $this->$objectName->dao; - $loadedModels[$type][$appName][$moduleName] = $this->$objectName; + if($type == 'zen') $loadedModels[$type][$appName][$moduleName] = false; + + /** + * 初始化model对象,在control对象中可以通过$this->$objectName来引用。同时将dao对象赋为control对象的成员变量,将view对象赋为zen对象的成员变量,方便引用。 + * Init the model object thus you can try $this->$objectName to access it. Also assign the $dao object as a member of control object, assign the $view object as a member of zen object. + */ + $this->{$objectName} = new $modelClass($appName); + if($type == 'model') $this->dao = $this->{$objectName}->dao; + if($type == 'zen') $this->{$objectName}->view = $this->view; + $loadedModels[$type][$appName][$moduleName] = $this->{$objectName}; return $this->$objectName; } From 7d305bd7f70770bcfe7893892e5086b11a478b56 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 19 Oct 2022 16:43:49 +0800 Subject: [PATCH 019/608] * Refactor the loadModel function to support loading tao files and return tao object. --- framework/base/model.class.php | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/framework/base/model.class.php b/framework/base/model.class.php index 716da9c3dd..b4e3a199de 100644 --- a/framework/base/model.class.php +++ b/framework/base/model.class.php @@ -207,23 +207,30 @@ class baseModel */ public function loadModel($moduleName, $appName = '', $type = 'model') { - if(empty($moduleName)) return false; + if(empty($moduleName)) $moduleName = $this->moduleName; if(empty($appName)) $appName = $this->appName; - $moduleName = strtolower($moduleName); $objectName = $type == 'model' ? $moduleName : $moduleName . ucfirst($type); global $loadedModels; if(isset($loadedModels[$type][$appName][$moduleName])) { - $this->$objectName = $loadedModels[$type][$appName][$moduleName]; - return $this->$objectName; + $this->{$objectName} = $loadedModels[$type][$appName][$moduleName]; + return $this->{$objectName}; } $modelFile = $this->app->setModelFile($moduleName, $appName, $type); + /** + * 如果没有model文件,返回。 + * If no model file, return. + */ if(!helper::import($modelFile)) return false; + /** + * 如果没有扩展文件,model类名是$moduleName + $type,如果有扩展,还需要增加ext前缀。 + * If no extension file, model class name is $moduleName + $type, else with 'ext' as the prefix. + */ $modelClass = class_exists('ext' . $appName . $moduleName. $type) ? 'ext' . $appName . $moduleName . $type : $appName . $moduleName . $type; if(!class_exists($modelClass)) { @@ -231,9 +238,18 @@ class baseModel if(!class_exists($modelClass)) $this->app->triggerError(" The $type $modelClass not found", __FILE__, __LINE__, $exit = true); } - $this->$objectName = new $modelClass($appName); - $loadedModels[$type][$appName][$moduleName] = $this->$objectName; - return $this->$objectName; + /** + * 因为tao继承model,构造函数里会调用loadModel方法,赋默认值值防止递归调用。 + */ + if($type == 'tao') $loadedModels[$type][$appName][$moduleName] = false; + + /** + * 初始化model对象,在model对象中可以通过$this->$objectName来引用。 + * Init the model object thus you can try $this->$objectName to access it. + */ + $this->{$objectName} = new $modelClass($appName); + $loadedModels[$type][$appName][$moduleName] = $this->{$objectName}; + return $this->{$objectName}; } /** From d9883bd382cf87bbf19e091f58dc84472b80ea07 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 19 Oct 2022 16:45:18 +0800 Subject: [PATCH 020/608] * Refactor to avoid errors when class names contain ext or model. --- framework/base/model.class.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/framework/base/model.class.php b/framework/base/model.class.php index b4e3a199de..0f30083ed2 100644 --- a/framework/base/model.class.php +++ b/framework/base/model.class.php @@ -170,11 +170,11 @@ class baseModel */ public function getModuleName() { - $parentClass = get_parent_class($this); - $selfClass = get_class($this); - $className = $parentClass == 'model' ? $selfClass : $parentClass; - if($className == 'extensionModel') return 'extension'; - return strtolower(str_ireplace(array('ext', 'Model'), '', $className)); + $className = get_class($this); + $parentClasses = class_parents($this); + if(count($parentClasses) > 2) $className = current(array_slice($parentClasses, -3, 1)); + if(strtolower(substr($className, -5)) == 'model') $className = strtolower(substr($className, 0, strlen($className) - 5)); + return $className; } /** From c43f14c7b00fa67c73cc3cada968c58d8b8089e1 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 19 Oct 2022 16:48:04 +0800 Subject: [PATCH 021/608] * Refactor to support load extensions of tao. --- framework/base/model.class.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/framework/base/model.class.php b/framework/base/model.class.php index 0f30083ed2..43c04a5b3d 100644 --- a/framework/base/model.class.php +++ b/framework/base/model.class.php @@ -273,17 +273,22 @@ class baseModel public function loadExtension($extensionName, $moduleName = '') { if(empty($extensionName)) return false; + if(empty($moduleName)) $moduleName = $this->getModuleName(); - $moduleName = $moduleName ? $moduleName : $this->getModuleName(); $moduleName = strtolower($moduleName); $extensionName = strtolower($extensionName); + $type = 'model'; + $className = strtolower(get_class($this)); + if($className == $moduleName . 'tao' || $className == 'ext' . $moduleName . 'tao') $type = 'tao'; + /* 设置扩展类的名字。Set the extension class name. */ $extensionClass = $extensionName . ucfirst($moduleName); + if($type != 'model') $extensionClass .= ucfirst($type); if(isset($this->$extensionClass)) return $this->$extensionClass; /* 设置扩展的名字和相应的文件。Set extenson name and extension file. */ - $moduleExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'model'); + $moduleExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, $type); if(!empty($moduleExtPath['site'])) $extensionFile = $moduleExtPath['site'] . 'class/' . $extensionName . '.class.php'; if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['custom'] . 'class/' . $extensionName . '.class.php'; if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['saas'] . 'class/' . $extensionName . '.class.php'; @@ -292,13 +297,13 @@ class baseModel if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['common'] . 'class/' . $extensionName . '.class.php'; /* 载入父类。Try to import parent model file auto and then import the extension file. */ - if(!class_exists($moduleName . 'Model')) helper::import($this->app->getModulePath($this->appName, $moduleName) . 'model.php'); + if(!class_exists($moduleName . ucfirst($type))) helper::import($this->app->getModulePath($this->appName, $moduleName) . $type . '.php'); if(!helper::import($extensionFile)) return false; if(!class_exists($extensionClass)) return false; /* 实例化扩展类。Create an instance of the extension class and return it. */ $extensionObject = new $extensionClass; - $extensionClass = str_replace('Model', '', $extensionClass); + if($type == 'model') $extensionClass = str_replace(ucfirst($type), '', $extensionClass); $this->$extensionClass = $extensionObject; return $extensionObject; } From dc874101dab67cef6427501c84c142e29d49078d Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 19 Oct 2022 17:16:51 +0800 Subject: [PATCH 022/608] * Remove blank. --- framework/base/model.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/base/model.class.php b/framework/base/model.class.php index 43c04a5b3d..f370fd5248 100644 --- a/framework/base/model.class.php +++ b/framework/base/model.class.php @@ -303,7 +303,7 @@ class baseModel /* 实例化扩展类。Create an instance of the extension class and return it. */ $extensionObject = new $extensionClass; - if($type == 'model') $extensionClass = str_replace(ucfirst($type), '', $extensionClass); + if($type == 'model') $extensionClass = str_replace(ucfirst($type), '', $extensionClass); $this->$extensionClass = $extensionObject; return $extensionObject; } From eb43521900daac3aed06f0f035e31661c298acf2 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Thu, 20 Oct 2022 10:18:48 +0800 Subject: [PATCH 023/608] * Add the loadExtension function to load the extension of zen. --- framework/control.class.php | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/framework/control.class.php b/framework/control.class.php index e939a56bb9..fc50a4cd27 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -187,6 +187,63 @@ class control extends baseControl return parent::loadModel($moduleName, '', $type); } + /** + * 加载model的class扩展,主要是为了开发加密代码使用。 + * 可以将主要的逻辑存放到$moduleName/ext/model/class/$extensionName.class.php中。 + * 然后在ext/model/$extension.php的扩展里面使用$this->loadExtension()来调用相应的方法。 + * ext/model/class/*.class.php代码可以加密。而ext/model/*.php可以不用加密。 + * 因为框架对model的扩展是采取合并文件的方式,ext/model/*.php文件不能加密。 + * + * Load extension class of a model thus user can encrypt the code. + * You can put the main extension logic codes in $moduleName/ext/model/class/$extensionName.class.php. + * And call them by the ext/model/$extension.php like this: $this->loadExtension('myextension')->method(). + * You can encrypt the code in ext/model/class/*.class.php. + * Because the framework will merge the extension files in ext/model/*.php to the module/model.php. + * + * @param string $extensionName + * @param string $moduleName + * @access public + * @return void + */ + public function loadExtension($extensionName, $moduleName = '') + { + if(empty($extensionName)) return false; + if(empty($moduleName)) $moduleName = $this->moduleName; + + $moduleName = strtolower($moduleName); + $extensionName = strtolower($extensionName); + + $type = 'model'; + $className = strtolower(get_class($this)); + if($className == $moduleName . 'zen' || $className == 'ext' . $moduleName . 'zen') $type = 'zen'; + + /* 设置扩展类的名字。Set the extension class name. */ + $extensionClass = $extensionName . ucfirst($moduleName); + if($type != 'model') $extensionClass .= ucfirst($type); + if(isset($this->$extensionClass)) return $this->$extensionClass; + + /* 设置扩展的名字和相应的文件。Set extenson name and extension file. */ + $moduleExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, $type); + if(!empty($moduleExtPath['site'])) $extensionFile = $moduleExtPath['site'] . 'class/' . $extensionName . '.class.php'; + if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['custom'] . 'class/' . $extensionName . '.class.php'; + if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['saas'] . 'class/' . $extensionName . '.class.php'; + if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['vision'] . 'class/' . $extensionName . '.class.php'; + if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['xuan'] . 'class/' . $extensionName . '.class.php'; + if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['common'] . 'class/' . $extensionName . '.class.php'; + + /* 载入父类。Try to import parent model file auto and then import the extension file. */ + if(!class_exists($moduleName . ucfirst($type))) helper::import($this->app->getModulePath($this->appName, $moduleName) . $type . '.php'); + if(!helper::import($extensionFile)) return false; + if(!class_exists($extensionClass)) return false; + + /* 实例化扩展类。Create an instance of the extension class and return it. */ + $extensionObject = new $extensionClass; + if($type == 'model') $extensionClass = str_replace(ucfirst($type), '', $extensionClass); + $this->$extensionClass = $extensionObject; + $this->$extensionClass->view = $this->view; + return $extensionObject; + } + /** * 设置视图文件:主视图文件,扩展视图文件, 站点扩展视图文件,以及钩子脚本。 * Set view files: the main file, extension view file, site extension view file and hook files. From 83cf9f8aa5dd25944ce77283e4fb0880e8d36547 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Thu, 20 Oct 2022 10:21:13 +0800 Subject: [PATCH 024/608] * Fix bug called a object by the loadModel function in another module. --- framework/model.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/model.class.php b/framework/model.class.php index b0f1205b23..8b967734f5 100644 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -31,7 +31,7 @@ class model extends baseModel { parent::__construct($appName); - $moduleName = $this->app->getModuleName(); + $moduleName = $this->getModuleName(); $this->loadModel($moduleName, $appName, 'tao'); } @@ -348,7 +348,7 @@ class model extends baseModel */ public function __call($method, $arguments) { - $moduleName = $this->app->getModuleName(); + $moduleName = $this->getModuleName(); $taoClass = $moduleName . 'Tao'; if(!is_callable(array($this->{$taoClass}, $method))) $this->app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); From 1cbb4546fda807357d085bfdc3a0be30b32b362b Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Thu, 20 Oct 2022 10:25:46 +0800 Subject: [PATCH 025/608] * If the method is callable return its result else trigger error. --- framework/control.class.php | 10 +++++----- framework/model.class.php | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/framework/control.class.php b/framework/control.class.php index fc50a4cd27..747a1e12f6 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -646,12 +646,12 @@ class control extends baseControl */ public function __call($method, $arguments) { - $moduleName = $this->app->getModuleName(); + $moduleName = $this->moduleName(); $zenClass = $moduleName . 'Zen'; - if(!is_callable(array($this->{$zenClass}, $method))) $this->app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); + if(is_callable(array($this->{$zenClass}, $method))) return call_user_func_array(array($this->{$zenClass}, $method), $arguments); - return call_user_func_array(array($this->{$zenClass}, $method), $arguments); + $this->app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); } /** @@ -668,8 +668,8 @@ class control extends baseControl $moduleName = $app->getModuleName(); $zenClass = $moduleName . 'Zen'; - if(!is_callable("{$zenClass}::{$method}")) $app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); + if(is_callable("{$zenClass}::{$method}")) return call_user_func_array("{$zenClass}::{$method}", $arguments); - return call_user_func_array("{$zenClass}::{$method}", $arguments); + $app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); } } diff --git a/framework/model.class.php b/framework/model.class.php index 8b967734f5..d120e4b7c1 100644 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -351,9 +351,9 @@ class model extends baseModel $moduleName = $this->getModuleName(); $taoClass = $moduleName . 'Tao'; - if(!is_callable(array($this->{$taoClass}, $method))) $this->app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); + if(is_callable(array($this->{$taoClass}, $method))) return call_user_func_array(array($this->{$taoClass}, $method), $arguments); - return call_user_func_array(array($this->{$taoClass}, $method), $arguments); + $this->app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); } /** @@ -370,8 +370,8 @@ class model extends baseModel $moduleName = $app->getModuleName(); $taoClass = $moduleName . 'Tao'; - if(!is_callable("{$taoClass}::{$method}")) $app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); + if(is_callable("{$taoClass}::{$method}")) return call_user_func_array("{$taoClass}::{$method}", $arguments); - return call_user_func_array("{$taoClass}::{$method}", $arguments); + $app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); } } From 86df3868fb32711dc30cbfc9d46a82873d2054ad Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Thu, 20 Oct 2022 10:28:35 +0800 Subject: [PATCH 026/608] * Refactor the magic method to support call static method. Only static methods of classes declared in a zen file or an ext zen file or a tao file or an ext tao file can be called. --- framework/control.class.php | 4 +++- framework/model.class.php | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/framework/control.class.php b/framework/control.class.php index 747a1e12f6..ae729ac382 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -666,8 +666,10 @@ class control extends baseControl { global $app; $moduleName = $app->getModuleName(); - $zenClass = $moduleName . 'Zen'; + $zenClass = 'ext' . $moduleName . 'Zen'; + if(is_callable("{$zenClass}::{$method}")) return call_user_func_array("{$zenClass}::{$method}", $arguments); + $zenClass = $moduleName . 'Zen'; if(is_callable("{$zenClass}::{$method}")) return call_user_func_array("{$zenClass}::{$method}", $arguments); $app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); diff --git a/framework/model.class.php b/framework/model.class.php index d120e4b7c1..062cf998c9 100644 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -367,9 +367,11 @@ class model extends baseModel public static function __callStatic($method, $arguments) { global $app; - $moduleName = $app->getModuleName(); - $taoClass = $moduleName . 'Tao'; + $moduleName = get_called_class(); + $taoClass = 'ext' . $moduleName . 'Tao'; + if(is_callable("{$taoClass}::{$method}")) return call_user_func_array("{$taoClass}::{$method}", $arguments); + $taoClass = $moduleName . 'Tao'; if(is_callable("{$taoClass}::{$method}")) return call_user_func_array("{$taoClass}::{$method}", $arguments); $app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); From 5498c0872b16e538b005d04504bbf8f322c7f3b8 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Thu, 20 Oct 2022 11:00:11 +0800 Subject: [PATCH 027/608] * Cann't call the member variables of a class in the magic method. --- framework/control.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/control.class.php b/framework/control.class.php index ae729ac382..428a8ff520 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -646,7 +646,7 @@ class control extends baseControl */ public function __call($method, $arguments) { - $moduleName = $this->moduleName(); + $moduleName = $this->app->getModuleName(); $zenClass = $moduleName . 'Zen'; if(is_callable(array($this->{$zenClass}, $method))) return call_user_func_array(array($this->{$zenClass}, $method), $arguments); From a769caa8c57b7e5c4b4b246736f4089552116876 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Thu, 20 Oct 2022 14:24:30 +0800 Subject: [PATCH 028/608] * Get module name by preg_match. --- framework/model.class.php | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/framework/model.class.php b/framework/model.class.php index 062cf998c9..977e69c42b 100644 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -367,12 +367,28 @@ class model extends baseModel public static function __callStatic($method, $arguments) { global $app; - $moduleName = get_called_class(); - $taoClass = 'ext' . $moduleName . 'Tao'; - if(is_callable("{$taoClass}::{$method}")) return call_user_func_array("{$taoClass}::{$method}", $arguments); - $taoClass = $moduleName . 'Tao'; - if(is_callable("{$taoClass}::{$method}")) return call_user_func_array("{$taoClass}::{$method}", $arguments); + $moduleName = strtolower(get_called_class()); + + preg_match_all('/^(ext)?(\w+)model/', $moduleName, $matches); + if(isset($matches[2][0])) + { + $moduleName = $matches[2][0]; + } + else + { + preg_match_all('/^(ext)?(\w+)tao/', $moduleName, $matches); + if(isset($matches[2][0])) $moduleName = $matches[2][0]; + } + + $modelClass = 'ext' . $moduleName . 'Model'; + if(method_exists($modelClass, $method)) return call_user_func_array("{$modelClass}::{$method}", $arguments); + + $taoClass = 'ext' . $moduleName . 'Tao'; + if(method_exists($taoClass, $method)) return call_user_func_array("{$taoClass}::{$method}", $arguments); + + $taoClass = $moduleName . 'Tao'; + if(method_exists($taoClass, $method)) return call_user_func_array("{$taoClass}::{$method}", $arguments); $app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true); } From c232ec7c7de2fc88ba3f1bc2de0278ecd31e3827 Mon Sep 17 00:00:00 2001 From: Yagami Date: Mon, 24 Oct 2022 15:43:36 +0800 Subject: [PATCH 029/608] * Code for task #73233. --- db/update18.0.sql | 1 + module/programplan/model.php | 8 +++++--- module/programplan/view/create.html.php | 2 +- module/project/control.php | 9 +++++++++ module/project/js/create.js | 4 ++++ module/project/lang/de.php | 4 ++++ module/project/lang/en.php | 4 ++++ module/project/lang/fr.php | 4 ++++ module/project/lang/vi.php | 1 + module/project/lang/zh-cn.php | 4 ++++ module/project/view/create.html.php | 4 ++++ module/project/view/edit.html.php | 6 ++++++ module/stage/model.php | 27 +++++++++++++++---------- 13 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 db/update18.0.sql diff --git a/db/update18.0.sql b/db/update18.0.sql new file mode 100644 index 0000000000..61c3416fb5 --- /dev/null +++ b/db/update18.0.sql @@ -0,0 +1 @@ +ALTER TABLE `zt_project` ADD `division` enum('0','1') COLLATE 'utf8_general_ci' NOT NULL DEFAULT '1'; diff --git a/module/programplan/model.php b/module/programplan/model.php index a3d20ecfad..da8c42342c 100755 --- a/module/programplan/model.php +++ b/module/programplan/model.php @@ -727,7 +727,8 @@ class programplanModel extends model $datas[] = $plan; } - $project = $this->loadModel('project')->getByID($projectID); + $project = $this->loadModel('project')->getByID($projectID); + $productList = $this->loadModel('product')->getProductPairsByProject($projectID); $totalPercent = 0; $totalDevType = 0; @@ -928,8 +929,9 @@ class programplanModel extends model $this->setTreePath($stageID); if($data->acl != 'open') $this->user->updateUserView($stageID, 'sprint'); - - $this->post->set('products', array(0 => $productID)); + + $linkProducts = $project->division ? array(0 => $productID) : array_keys($productList); + $this->post->set('products', $linkProducts); $this->execution->updateProducts($stageID); /* Record version change information. */ diff --git a/module/programplan/view/create.html.php b/module/programplan/view/create.html.php index 9779a0db69..783ff44094 100644 --- a/module/programplan/view/create.html.php +++ b/module/programplan/view/create.html.php @@ -22,7 +22,7 @@ echo "{$title}"; ?> - + division):?>
diff --git a/module/project/control.php b/module/project/control.php index cd216bd8cf..f2a9437eee 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -2042,6 +2042,7 @@ class project extends control { $this->loadModel('product'); $this->loadModel('program'); + $this->loadModel('execution'); if(!empty($_POST)) { @@ -2058,6 +2059,14 @@ class project extends control $oldProducts = array_keys($oldProducts); $newProducts = $this->product->getProducts($projectID); $newProducts = array_keys($newProducts); + + if(!$project->division and $newProducts) + { + $stages = $this->execution->getPairs($projectID); + $this->post->set('products', $newProducts); + foreach($stages as $stageID => $name) $this->execution->updateProducts($stageID); + } + $diffProducts = array_merge(array_diff($oldProducts, $newProducts), array_diff($newProducts, $oldProducts)); if($diffProducts) $this->loadModel('action')->create('project', $projectID, 'Managed', '', !empty($_POST['products']) ? join(',', $_POST['products']) : ''); diff --git a/module/project/js/create.js b/module/project/js/create.js index fe2a8db61c..4ae6217d3e 100644 --- a/module/project/js/create.js +++ b/module/project/js/create.js @@ -253,9 +253,11 @@ function setAclList(programID) */ function loadBranches(product) { + var chosenProducts = 0; $("#productsBox select[name^='products']").each(function() { var $product = $(product); + if($(this).val() > 0) chosenProducts ++; if($product.val() != 0 && $product.val() == $(this).val() && $product.attr('id') != $(this).attr('id') && !multiBranchProducts[$product.val()]) { bootbox.alert(errorSameProducts); @@ -265,6 +267,8 @@ function loadBranches(product) } }); + chosenProducts > 1 ? $('.division').removeClass('hide') : $('.division').addClass('hide'); + if($('#productsBox .row .input-group:last select:first').val() != 0) { var length = $('#productsBox .row .input-group').size(); diff --git a/module/project/lang/de.php b/module/project/lang/de.php index b00209d457..b59dea8fb2 100644 --- a/module/project/lang/de.php +++ b/module/project/lang/de.php @@ -127,6 +127,7 @@ $lang->project->realBeganAB = 'Actual Begin'; $lang->project->realEndAB = 'Actual End'; $lang->project->realBegan = 'Actual Began'; $lang->project->realEnd = 'Actual End'; +$lang->project->division = 'Create Stages by Product'; $lang->project->bygrid = 'Kanban'; $lang->project->bylist = 'List'; $lang->project->bycard = 'Card'; @@ -177,6 +178,9 @@ $lang->project->typeList = array(); $lang->project->typeList['my'] = 'Projects Ownedbyme'; $lang->project->typeList['other'] = 'Other Projects'; +$lang->project->divisionList['0'] = 'Disable'; +$lang->project->divisionList['1'] = 'Enable'; + $lang->project->waitProjects = 'Waiting Projects'; $lang->project->doingProjects = 'Ongoing Projects'; $lang->project->doingExecutions = 'Ongoing Executions'; diff --git a/module/project/lang/en.php b/module/project/lang/en.php index 544f00918f..e2e896ec13 100644 --- a/module/project/lang/en.php +++ b/module/project/lang/en.php @@ -127,6 +127,7 @@ $lang->project->realBeganAB = 'Actual Begin'; $lang->project->realEndAB = 'Actual End'; $lang->project->realBegan = 'Actual Begin'; $lang->project->realEnd = 'Actual End'; +$lang->project->division = 'Create Stages by Product'; $lang->project->bygrid = 'Kanban'; $lang->project->bylist = 'List'; $lang->project->bycard = 'Card'; @@ -177,6 +178,9 @@ $lang->project->typeList = array(); $lang->project->typeList['my'] = 'Projects Ownedbyme'; $lang->project->typeList['other'] = 'Other Projects'; +$lang->project->divisionList['0'] = 'Disable'; +$lang->project->divisionList['1'] = 'Enable'; + $lang->project->waitProjects = 'Waiting Projects'; $lang->project->doingProjects = 'Ongoing Projects'; $lang->project->doingExecutions = 'Ongoing Executions'; diff --git a/module/project/lang/fr.php b/module/project/lang/fr.php index 7168356f4d..0f5591b24d 100644 --- a/module/project/lang/fr.php +++ b/module/project/lang/fr.php @@ -127,6 +127,7 @@ $lang->project->realBeganAB = 'Actual Begin'; $lang->project->realEndAB = 'Actual End'; $lang->project->realBegan = 'Actual Began'; $lang->project->realEnd = 'Actual End'; +$lang->project->division = 'Create Stages by Product'; $lang->project->bygrid = 'Kanban'; $lang->project->bylist = 'List'; $lang->project->bycard = 'Card'; @@ -177,6 +178,9 @@ $lang->project->typeList = array(); $lang->project->typeList['my'] = 'Projects Ownedbyme'; $lang->project->typeList['other'] = 'Other Projects'; +$lang->project->divisionList['0'] = 'Disable'; +$lang->project->divisionList['1'] = 'Enable'; + $lang->project->waitProjects = 'Waiting Projects'; $lang->project->doingProjects = 'Ongoing Projects'; $lang->project->doingExecutions = 'Ongoing Executions'; diff --git a/module/project/lang/vi.php b/module/project/lang/vi.php index 7c3bd62dcd..8b3fec9d3a 100644 --- a/module/project/lang/vi.php +++ b/module/project/lang/vi.php @@ -75,6 +75,7 @@ $lang->project->dateRange = 'Duration'; $lang->project->to = ' to '; $lang->project->realEnd = 'Actual End'; $lang->project->realBegan = 'Actual Began'; +$lang->project->division = 'Create Stages by Product'; $lang->project->bygrid = 'Kanban'; $lang->project->bylist = 'List'; $lang->project->bycard = 'Card'; diff --git a/module/project/lang/zh-cn.php b/module/project/lang/zh-cn.php index 1d0e642dd1..5965287bd9 100644 --- a/module/project/lang/zh-cn.php +++ b/module/project/lang/zh-cn.php @@ -127,6 +127,7 @@ $lang->project->realBeganAB = '实际开始'; $lang->project->realEndAB = '实际完成'; $lang->project->realBegan = '实际开始日期'; $lang->project->realEnd = '实际完成日期'; +$lang->project->division = '按产品创建阶段'; $lang->project->bygrid = '看板'; $lang->project->bylist = '列表'; $lang->project->bycard = '卡片'; @@ -177,6 +178,9 @@ $lang->project->typeList = array(); $lang->project->typeList['my'] = '我负责的项目'; $lang->project->typeList['other'] = '其他项目'; +$lang->project->divisionList['0'] = '关闭'; +$lang->project->divisionList['1'] = '开启'; + $lang->project->waitProjects = '未开始的项目'; $lang->project->doingProjects = '进行中的项目'; $lang->project->doingExecutions = '进行中的执行(最近1个)'; diff --git a/module/project/view/create.html.php b/module/project/view/create.html.php index d994c4f549..5c9a32a140 100755 --- a/module/project/view/create.html.php +++ b/module/project/view/create.html.php @@ -175,6 +175,10 @@
+ + project->division;?> + project->divisionList, '0');?> + execution->team;?> diff --git a/module/project/view/edit.html.php b/module/project/view/edit.html.php index d787c89338..00ece4458c 100755 --- a/module/project/view/edit.html.php +++ b/module/project/view/edit.html.php @@ -175,6 +175,12 @@ + division):?> + + project->division;?> + project->divisionList, $project->division);?> + + model == 'kanban'):?> execution->team;?> diff --git a/module/stage/model.php b/module/stage/model.php index 86c3fb0b88..92fca02779 100644 --- a/module/stage/model.php +++ b/module/stage/model.php @@ -123,17 +123,22 @@ class stageModel extends model */ public function getStages($orderBy = 'id_desc', $projectID = 0) { - $stages = $this->dao->select('id,name,type,percent,openedBy as createdBy,begin as createdDate,lastEditedBy as editedBy,end as editedDate,deleted') - ->from(TABLE_EXECUTION) - ->where('type')->in('sprint,stage,kanban') - ->andWhere('deleted')->eq('0') - ->andWhere('vision')->eq($this->config->vision) - ->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->sprints)->fi() - ->beginIF($projectID)->andWhere('project')->eq($projectID)->fi() - ->orderBy($orderBy) - ->fetchAll('id'); - $stages = !empty($stages) ? $stages : $this->dao->select('*')->from(TABLE_STAGE)->where('deleted')->eq(0)->orderBy($orderBy)->fetchAll('id'); - return $stages; + if($projectID) + { + return $this->dao->select('id,name,type,percent,openedBy as createdBy,begin as createdDate,lastEditedBy as editedBy,end as editedDate,deleted') + ->from(TABLE_EXECUTION) + ->where('type')->in('sprint,stage,kanban') + ->andWhere('deleted')->eq('0') + ->andWhere('vision')->eq($this->config->vision) + ->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->sprints)->fi() + ->andWhere('project')->eq($projectID) + ->orderBy($orderBy) + ->fetchAll('id'); + } + else + { + return $this->dao->select('*')->from(TABLE_STAGE)->where('deleted')->eq(0)->orderBy($orderBy)->fetchAll('id'); + } } /** From 1875b5be0ee32980a8db145414776c774c80dbbd Mon Sep 17 00:00:00 2001 From: Yagami Date: Tue, 25 Oct 2022 09:25:07 +0800 Subject: [PATCH 030/608] * Fix bug #73233. --- module/project/control.php | 4 +++- module/project/lang/de.php | 1 + module/project/lang/en.php | 1 + module/project/lang/fr.php | 1 + module/project/lang/vi.php | 1 + module/project/lang/zh-cn.php | 1 + module/project/model.php | 2 ++ module/project/view/manageproducts.html.php | 16 ++++++++++++++++ 8 files changed, 26 insertions(+), 1 deletion(-) diff --git a/module/project/control.php b/module/project/control.php index f2a9437eee..64c64facf5 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -2044,6 +2044,8 @@ class project extends control $this->loadModel('program'); $this->loadModel('execution'); + $project = $this->project->getById($projectID); + if(!empty($_POST)) { if(!isset($_POST['products'])) @@ -2075,7 +2077,6 @@ class project extends control return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $locateLink)); } - $project = $this->project->getById($projectID); if($this->app->tab == 'program') { $this->program->setMenu($project->parent); @@ -2120,6 +2121,7 @@ class project extends control $this->view->linkedProducts = $linkedProducts; $this->view->linkedBranches = $linkedBranches; $this->view->branches = $branches; + $this->view->project = $project; $this->view->unmodifiableProducts = $unmodifiableProducts; $this->view->unmodifiableBranches = $unmodifiableBranches; $this->view->unmodifiableMainBranches = $unmodifiableMainBranches; diff --git a/module/project/lang/de.php b/module/project/lang/de.php index b59dea8fb2..c51d365559 100644 --- a/module/project/lang/de.php +++ b/module/project/lang/de.php @@ -196,6 +196,7 @@ $lang->project->changeProgram = '%s > Change project'; $lang->project->changeProgramTip = 'After modifying the project set, the products linked with the project will also modify the project set to which it belongs. Please confirm whether to modify it.'; $lang->project->linkedProjectsTip = 'Linked projects are as follows'; $lang->project->multiLinkedProductsTip = 'The following products linked to this project are also linked to other projects, please unlink before proceeding.'; +$lang->project->noticeDivsion = "The current project is associated with multiple products, you can click Confirm to open the mode by {$lang->productCommon} creation stage, click Cancel to keep the status quo."; $lang->project->linkStoryByPlanTips = "This action will associate all {$lang->SRCommon} under the selected plan to this project"; $lang->project->createExecution = "There is no {$lang->executionCommon} under this project, please create {$lang->executionCommon} first"; $lang->project->unlinkExecutionMember = "The user participated in %s executions such as %s%s. Do you want to remove the user from those executions as well? (The data related to this user will not be deleted.)"; diff --git a/module/project/lang/en.php b/module/project/lang/en.php index e2e896ec13..ebc9540e26 100644 --- a/module/project/lang/en.php +++ b/module/project/lang/en.php @@ -196,6 +196,7 @@ $lang->project->changeProgram = '%s > Change project'; $lang->project->changeProgramTip = 'Once the program is edited, the product that is linked to this program will be changed. Do you want to edit it?'; $lang->project->linkedProjectsTip = 'Linked projects are as follows'; $lang->project->multiLinkedProductsTip = 'The following products linked to this project are also linked to other projects, please unlink before proceeding.'; +$lang->project->noticeDivsion = "The current project is associated with multiple products, you can click Confirm to open the mode by {$lang->productCommon} creation stage, click Cancel to keep the status quo."; $lang->project->linkStoryByPlanTips = "This action will associate all {$lang->SRCommon} under the selected plan to this project"; $lang->project->createExecution = "There is no {$lang->executionCommon} under this project, please create {$lang->executionCommon} first"; $lang->project->unlinkExecutionMember = "The user participated in %s executions such as %s%s. Do you want to remove the user from those executions as well? (The data related to this user will not be deleted.)"; diff --git a/module/project/lang/fr.php b/module/project/lang/fr.php index 0f5591b24d..3e86cd7cc7 100644 --- a/module/project/lang/fr.php +++ b/module/project/lang/fr.php @@ -196,6 +196,7 @@ $lang->project->changeProgram = '%s > Change project'; $lang->project->changeProgramTip = 'After modifying the project set, the products linked with the project will also modify the project set to which it belongs. Please confirm whether to modify it.'; $lang->project->linkedProjectsTip = 'Linked projects are as follows'; $lang->project->multiLinkedProductsTip = 'The following products linked to this project are also linked to other projects, please unlink before proceeding.'; +$lang->project->noticeDivsion = "The current project is associated with multiple products, you can click Confirm to open the mode by {$lang->productCommon} creation stage, click Cancel to keep the status quo."; $lang->project->linkStoryByPlanTips = "This action will associate all {$lang->SRCommon} under the selected plan to this project"; $lang->project->createExecution = "There is no {$lang->executionCommon} under this project, please create {$lang->executionCommon} first"; $lang->project->unlinkExecutionMember = "The user participated in %s executions such as %s%s. Do you want to remove the user from those executions as well? (The data related to this user will not be deleted.)"; diff --git a/module/project/lang/vi.php b/module/project/lang/vi.php index 8b3fec9d3a..2aed7d8d15 100644 --- a/module/project/lang/vi.php +++ b/module/project/lang/vi.php @@ -116,6 +116,7 @@ $lang->project->changeProgram = '%s > Change project'; $lang->project->changeProgramTip = 'After modifying the project set, the products linked with the project will also modify the project set to which it belongs. Please confirm whether to modify it.'; $lang->project->linkedProjectsTip = 'Linked projects are as follows'; $lang->project->multiLinkedProductsTip = 'The following products linked to this project are also linked to other projects, please unlink before proceeding.'; +$lang->project->noticeDivsion = "The current project is associated with multiple products, you can click Confirm to open the mode by {$lang->productCommon} creation stage, click Cancel to keep the status quo."; $lang->project->linkStoryByPlanTips = "This action will associate all {$lang->SRCommon} under the selected plan to this project"; $lang->project->createExecution = "There is no {$lang->executionCommon} under this project, please create {$lang->executionCommon} first"; $lang->project->noDevStage = 'There is no R&D stage under this project, or you do not have access permissions. The creation of builds is not supported at the moment.'; diff --git a/module/project/lang/zh-cn.php b/module/project/lang/zh-cn.php index 5965287bd9..8d691dc9f8 100644 --- a/module/project/lang/zh-cn.php +++ b/module/project/lang/zh-cn.php @@ -196,6 +196,7 @@ $lang->project->changeProgram = '%s > 修改项目集'; $lang->project->changeProgramTip = '修改项目集后,该项目关联产品的项目集也会被修改,请确认是否修改。'; $lang->project->linkedProjectsTip = '关联的项目如下'; $lang->project->multiLinkedProductsTip = '该项目关联的如下产品还关联了其他项目,请取消关联后再操作'; +$lang->project->noticeDivsion = '当前项目关联多个产品,可以点击确认开启按产品创建阶段的模式,点击取消则保持现状。'; $lang->project->linkStoryByPlanTips = "此操作会将所选计划下面的{$lang->SRCommon}全部关联到此项目中"; $lang->project->createExecution = "该项目下没有{$lang->executionCommon},请先创建{$lang->executionCommon}"; $lang->project->unlinkExecutionMember = "该用户参与了%s%s%s个{$lang->execution->common},是否同时将其移除?(该用户所产生的数据不会受影响。)"; diff --git a/module/project/model.php b/module/project/model.php index 94c8d58ae7..84be5de600 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -2164,6 +2164,8 @@ class projectModel extends model { $executions = $this->dao->select('id')->from(TABLE_EXECUTION)->where('project')->eq((int)$projectID)->fetchPairs('id'); $this->dao->delete()->from(TABLE_PROJECTPRODUCT)->where('project')->in($executions)->andWhere('product')->notin($products)->exec(); + + if(isset($_POST['division'])) $this->dao->update(TABLE_PROJECT)->set('division')->eq('1')->where('id')->eq((int)$projectID)->exec(); } $oldProductKeys = array_keys($oldProjectProducts); diff --git a/module/project/view/manageproducts.html.php b/module/project/view/manageproducts.html.php index 1a214f23ff..8059e09759 100644 --- a/module/project/view/manageproducts.html.php +++ b/module/project/view/manageproducts.html.php @@ -75,4 +75,20 @@ +division and count($linkedProducts) == 1):?> +project->noticeDivsion);?> + + From e06a98bd09eb59bdd888d4db5843c0f08875d796 Mon Sep 17 00:00:00 2001 From: tanghucheng Date: Tue, 25 Oct 2022 16:26:10 +0800 Subject: [PATCH 031/608] * Code for task #73235. --- module/programplan/control.php | 46 +++++++++++----- module/programplan/lang/de.php | 2 + module/programplan/lang/en.php | 2 + module/programplan/lang/fr.php | 2 + module/programplan/lang/zh-cn.php | 2 + module/programplan/view/gantt.html.php | 72 +++++++++++++++----------- module/project/view/execution.html.php | 4 ++ 7 files changed, 88 insertions(+), 42 deletions(-) diff --git a/module/programplan/control.php b/module/programplan/control.php index 2c66ab4dfa..d607021d95 100644 --- a/module/programplan/control.php +++ b/module/programplan/control.php @@ -119,6 +119,7 @@ class programplan extends control $this->view->position[] = $this->lang->programplan->browse; $this->view->projectID = $projectID; $this->view->productID = $this->productID; + $this->view->productList = $this->loadModel('product')->getProductPairsByProject($projectID); $this->view->type = $type; $this->view->plans = $plans; $this->view->orderBy = $orderBy; @@ -245,19 +246,40 @@ class programplan extends control */ public function ajaxCustom() { - $data = fixer::input('post')->get(); - $owner = $this->app->user->account; - $module = 'programplan'; - $section = 'browse'; - $object = 'stageCustom'; - $setting = $this->loadModel('setting'); - $custom = empty($data->stageCustom) ? '' : implode(',', $data->stageCustom); - $setting->setItem("$owner.$module.$section.$object", $custom); + $owner = $this->app->user->account; + $module = 'programplan'; + $this->app->loadLang('execution'); + $this->loadModel('datatable'); + $this->loadModel('setting'); - $response = array(); - $response['result'] = 'success'; - $response['message'] = ''; - return $this->send($response); + $stageCustom = $this->setting->getItem("owner=$owner&module=$module§ion=browse&key=stageCustom"); + $ganttFields = $this->setting->getItem("owner=$owner&module=$module§ion=ganttCustom&key=ganttFields"); + $zooming = $this->setting->getItem("owner=$owner&module=$module§ion=ganttCustom&key=zooming"); + + if($_POST) + { + $data = fixer::input('post')->get(); + $zooming = empty($data->zooming) ? '' : $data->zooming; + $stageCustom = empty($data->stageCustom) ? '' : implode(',', $data->stageCustom); + $ganttFields = empty($data->ganttFields) ? '' : implode(',', $data->ganttFields); + + $this->setting->setItem("$owner.$module.browse.stageCustom", $stageCustom); + $this->setting->setItem("$owner.$module.ganttCustom.ganttFields", $ganttFields); + $this->setting->setItem("$owner.$module.ganttCustom.zooming", $zooming); + + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent')); + } + + /* Set Custom. */ + foreach(explode(',', $this->config->programplan->custom->customGanttFields) as $field) $customFields[$field] = $this->lang->programplan->ganttCustom[$field]; + + $this->view->zooming = $zooming; + $this->view->customFields = $customFields; + $this->view->showFields = $this->config->programplan->ganttCustom->ganttFields; + $this->view->ganttFields = $ganttFields; + $this->view->stageCustom = $stageCustom; + + $this->display(); } /** diff --git a/module/programplan/lang/de.php b/module/programplan/lang/de.php index 889b03bcaa..a186daf4c5 100644 --- a/module/programplan/lang/de.php +++ b/module/programplan/lang/de.php @@ -62,6 +62,8 @@ $lang->programplan->hideCriticalPath = 'Hide Critical Path'; $lang->programplan->showCriticalPath = 'Show Critical Path'; $lang->programplan->delay = 'Delay'; $lang->programplan->delayDays = 'Delay days'; +$lang->programplan->settingGantt = 'Gantt Setting'; +$lang->programplan->viewSetting = 'Setting'; $lang->programplan->errorBegin = "Project begin date: %s, begin date should be >= project begin date."; $lang->programplan->errorEnd = "Project end date: %s, end date should be <= project end date."; diff --git a/module/programplan/lang/en.php b/module/programplan/lang/en.php index 6ed9867b61..b2084c75f4 100644 --- a/module/programplan/lang/en.php +++ b/module/programplan/lang/en.php @@ -62,6 +62,8 @@ $lang->programplan->hideCriticalPath = 'Hide Critical Path'; $lang->programplan->showCriticalPath = 'Show Critical Path'; $lang->programplan->delay = 'Delay'; $lang->programplan->delayDays = 'Delay days'; +$lang->programplan->settingGantt = 'Gantt Setting'; +$lang->programplan->viewSetting = 'Setting'; $lang->programplan->errorBegin = "Project begin date: %s, begin date should be >= project begin date."; $lang->programplan->errorEnd = "Project end date: %s, end date should be <= project end date."; diff --git a/module/programplan/lang/fr.php b/module/programplan/lang/fr.php index 889b03bcaa..a186daf4c5 100644 --- a/module/programplan/lang/fr.php +++ b/module/programplan/lang/fr.php @@ -62,6 +62,8 @@ $lang->programplan->hideCriticalPath = 'Hide Critical Path'; $lang->programplan->showCriticalPath = 'Show Critical Path'; $lang->programplan->delay = 'Delay'; $lang->programplan->delayDays = 'Delay days'; +$lang->programplan->settingGantt = 'Gantt Setting'; +$lang->programplan->viewSetting = 'Setting'; $lang->programplan->errorBegin = "Project begin date: %s, begin date should be >= project begin date."; $lang->programplan->errorEnd = "Project end date: %s, end date should be <= project end date."; diff --git a/module/programplan/lang/zh-cn.php b/module/programplan/lang/zh-cn.php index 1e4fdfbacd..b3f4b04429 100644 --- a/module/programplan/lang/zh-cn.php +++ b/module/programplan/lang/zh-cn.php @@ -62,6 +62,8 @@ $lang->programplan->hideCriticalPath = '隐藏关键路径'; $lang->programplan->showCriticalPath = '显示关键路径'; $lang->programplan->delay = '是否延期'; $lang->programplan->delayDays = '延期天数'; +$lang->programplan->settingGantt = '设置甘特图'; +$lang->programplan->viewSetting = '显示设置'; $lang->programplan->errorBegin = '阶段的开始时间不能小于所属项目的开始时间%s'; $lang->programplan->errorEnd = '阶段的结束时间不能大于所属项目的结束时间%s'; diff --git a/module/programplan/view/gantt.html.php b/module/programplan/view/gantt.html.php index 6b1f88c074..e68b128d0e 100644 --- a/module/programplan/view/gantt.html.php +++ b/module/programplan/view/gantt.html.php @@ -45,7 +45,7 @@ form {display: block; margin-top: 0em; margin-block-end: 1em;} .gantt_row.task-item{cursor: pointer;} #ganttDownload, #ganttHeader {display: none;} -#ganttContainer {margin-top: 10px;} +#ganttContainer {margin-top: 40px;} #mainContent:before {background: #fff;} #mainContent.loading {overflow: hidden} #mainContent.loading #ganttView {overflow: hidden} @@ -65,6 +65,9 @@ form {display: block; margin-top: 0em; margin-block-end: 1em;} .gantt_task_line.gantt_task_inline_color{border:0px;} .gantt_grid_scale, .gantt_task_scale, .gantt_task_vscroll{background-color: #F2F7FF;} #myCover {display:none;left:12px!important;z-index:10!important;top:9px!important;height:unset!important;} +.button-group{position: relative;} +.flax{display: flex; margin-bottom: 10px;} +.switchBtn > i {padding-left: 7px;} createLink('programplan', 'ajaxCustom'));?> @@ -74,34 +77,43 @@ form {display: block; margin-top: 0em; margin-block-end: 1em;} config->programplan->ganttCustom->ganttFields);?>
-
- app->getModuleName() == 'programplan') - { - $customLink = $this->createLink('custom', 'ajaxSaveCustomFields', 'module=programplan§ion=ganttCustom&key=ganttFields'); - include '../../common/view/customfield.html.php'; - } - ?> -
-
-
- programplan->full, 'id="fullScreenBtn"', 'btn btn-primary btn-sm')?> - rawModule == 'review' and $app->rawMethod == 'assess') unset($lang->programplan->stageCustom->date); ?> - programplan->stageCustom, $selectCustom);?> - - + app->getModuleName() == 'programplan'):?> +
+
+ product->allProduct;?> + +
- +
+
+
+ createLink('project', 'execution', "status=all&projectID=$projectID"),"  ", '', "class='btn btn-icon switchBtn' title='{$lang->project->bylist}'");?> +  ", '', "class='btn btn-icon text-primary switchBtn' title='{$lang->programplan->gantt}'");?> +
+ programplan->full;?> + + ' . $lang->settings, '', "class='iframe btn btn-link' data-width='30%'"); + if(common::hasPriv('programplan', 'create')) echo html::a($this->createLink('programplan', 'create', "projectID=$projectID"), " " . $this->lang->programplan->create, '', "class='btn btn-primary'"); + ?> +
+
@@ -145,7 +157,7 @@ gantt.init("gantt_here"); gantt.attachEvent("onBeforeExpand",function(){ $('#myCover').css('display', 'unset'); $('#mainContent .pull-right').css('opacity', '0'); - $('.example').css('display', 'none'); + $('.btn-toolbar').css('display', 'none'); return true; }); @@ -153,7 +165,7 @@ gantt.attachEvent("onBeforeExpand",function(){ gantt.attachEvent("onCollapse", function (){ $('#myCover').css('display', 'none'); $('#mainContent .pull-right').css('opacity', '1'); - $('.example').css('display', 'block'); + $('.btn-toolbar').css('display', 'flex'); }); /** diff --git a/module/project/view/execution.html.php b/module/project/view/execution.html.php index 0c47eaabf2..d349c0629b 100644 --- a/module/project/view/execution.html.php +++ b/module/project/view/execution.html.php @@ -40,6 +40,10 @@ $lang->programplan->stageCustom->task), '', $this->cookie->showTask ? 'checked=checked' : '');?>
+
+  ", '', "class='btn btn-icon text-primary switchBtn' title='{$lang->project->bylist}'");?> + createLink('programplan', 'browse', "projectID=$projectID&productID=$productID&type=gantt"), "  ", '', "class='btn btn-icon switchBtn' title='{$lang->programplan->gantt}'");?> +
" . $lang->export, '', "class='btn btn-link export'")?> createLink('programplan', 'create', "projectID=$projectID&productID=$productID"), " " . $lang->programplan->create, '', "class='btn btn-primary'");?> From dc2745f5ba086b72e1830d97f353e6e495234fc8 Mon Sep 17 00:00:00 2001 From: tanghucheng Date: Tue, 25 Oct 2022 16:35:26 +0800 Subject: [PATCH 032/608] * Add view.html.php for gantt setting. --- module/programplan/control.php | 8 ---- module/programplan/view/ajaxcustom.html.php | 44 +++++++++++++++++++++ 2 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 module/programplan/view/ajaxcustom.html.php diff --git a/module/programplan/control.php b/module/programplan/control.php index d607021d95..efb2988be9 100644 --- a/module/programplan/control.php +++ b/module/programplan/control.php @@ -64,14 +64,6 @@ class programplan extends control $products = $this->loadModel('product')->getProducts($projectID); $this->lang->modulePageNav = $this->product->select($products, $this->productID, 'programplan', 'browse', $type, 0, 0, '', false); - $this->lang->TRActions = ""; - $this->lang->TRActions .= ""; - - if(common::hasPriv('programplan', 'create')) $this->lang->TRActions .= html::a($this->createLink('programplan', 'create', "projectID=$projectID"), " " . $this->lang->programplan->create, '', "class='btn btn-primary'"); - $selectCustom = 0; // Display date and task settings. $dateDetails = 1; // Gantt chart detail date display. if($type == 'gantt') diff --git a/module/programplan/view/ajaxcustom.html.php b/module/programplan/view/ajaxcustom.html.php new file mode 100644 index 0000000000..dd0e8c015c --- /dev/null +++ b/module/programplan/view/ajaxcustom.html.php @@ -0,0 +1,44 @@ + + * @package programplan + * @version $Id: ajaxcustom.html.php 935 2022-10-25 16:15:24Z $ + * @link https://www.zentao.net + */ +?> + + + +
+
+

programplan->settingGantt;?>

+
+
+ + + + + + + + + + + + + + + + +
execution->gantt->format;?>execution->gantt->zooming, $zooming ? $zooming : 'day');?>
programplan->viewSetting;?>programplan->stageCustom, $stageCustom);?>
customField;?>
+ +
+
+
+ From 0df7b3ec6d5a2de78d7ee299c6f4333e5542d6b2 Mon Sep 17 00:00:00 2001 From: lanzongjun Date: Tue, 25 Oct 2022 17:19:47 +0800 Subject: [PATCH 033/608] * task #73243 --- module/port/model.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/module/port/model.php b/module/port/model.php index 0f30d9aa1a..8e71df1d80 100644 --- a/module/port/model.php +++ b/module/port/model.php @@ -808,10 +808,25 @@ class portModel extends model */ public function getQueryDatas($model = '') { - $queryCondition = $this->session->{$model . 'QueryCondition'}; - $onlyCondition = $this->session->{$model . 'OnlyCondition'}; + $queryCondition = $this->session->{$model . 'QueryCondition'}; + $onlyCondition = $this->session->{$model . 'OnlyCondition'}; + $transferCondition = $this->session->{$model . 'TransferCondition'}; $modelDatas = array(); + + if($transferCondition) + { + $selectKey = 'id'; + $stmt = $this->dbh->query($transferCondition); + while($row = $stmt->fetch()) + { + if($selectKey !== 't1.id' and isset($row->$model) and isset($row->id)) $row->id = $row->$model; + $modelDatas[$row->id] = $row; + } + + return $modelDatas; + } + if($onlyCondition and $queryCondition) { $table = zget($this->config->objectTables, $model); From cf00a736a1cc72146302f5ea4ac520a42d468fb4 Mon Sep 17 00:00:00 2001 From: tanghucheng Date: Wed, 26 Oct 2022 09:03:24 +0800 Subject: [PATCH 034/608] * Finish task #73241. --- module/execution/model.php | 3 +++ module/execution/view/edit.html.php | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/module/execution/model.php b/module/execution/model.php index c72f62c2a5..d60d43d29a 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -64,6 +64,9 @@ class executionModel extends model public function setMenu($executionID, $buildID = 0, $extra = '') { $execution = $this->getByID($executionID); + + if($execution->type == 'stage') unset($this->lang->execution->menu->settings['subMenu']->products); + if($execution and $execution->type == 'kanban') { global $lang; diff --git a/module/execution/view/edit.html.php b/module/execution/view/edit.html.php index 27a7b10be2..1e6bb50aaa 100644 --- a/module/execution/view/edit.html.php +++ b/module/execution/view/edit.html.php @@ -142,7 +142,7 @@ execution->manageProducts;?> - grade == 2 ? "readonly='readonly'" : '';?> + grade == 2 or $execution->type == 'stage') ? "disabled" : '';?>
@@ -165,12 +165,14 @@ ?> + type != 'stage'):?>
+
From e24e771dee07db0e5781e15d6f6b888288adaeba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Wed, 26 Oct 2022 09:27:04 +0800 Subject: [PATCH 035/608] * Code for task #73233. --- module/project/js/common.js | 4 ++++ module/project/model.php | 2 +- module/project/view/edit.html.php | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/module/project/js/common.js b/module/project/js/common.js index a0c7b3c6fc..11023d7c65 100644 --- a/module/project/js/common.js +++ b/module/project/js/common.js @@ -150,9 +150,11 @@ function loadBranches(product) /* When selecting a product, delete a plan that is empty by default. */ $("#planDefault").remove(); + var chosenProducts = 0; $("#productsBox select[name^='products']").each(function() { var $product = $(product); + if($(this).val() > 0) chosenProducts ++; if($product.val() != 0 && $product.val() == $(this).val() && $product.attr('id') != $(this).attr('id') && !multiBranchProducts[$product.val()]) { bootbox.alert(errorSameProducts); @@ -162,6 +164,8 @@ function loadBranches(product) } }); + chosenProducts > 1 ? $('.division').removeClass('hide') : $('.division').addClass('hide'); + if($('#productsBox .input-group:last select:first').val() != 0) { var length = $('#productsBox .input-group').size(); diff --git a/module/project/model.php b/module/project/model.php index 84be5de600..9e1f45844c 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -2165,7 +2165,7 @@ class projectModel extends model $executions = $this->dao->select('id')->from(TABLE_EXECUTION)->where('project')->eq((int)$projectID)->fetchPairs('id'); $this->dao->delete()->from(TABLE_PROJECTPRODUCT)->where('project')->in($executions)->andWhere('product')->notin($products)->exec(); - if(isset($_POST['division'])) $this->dao->update(TABLE_PROJECT)->set('division')->eq('1')->where('id')->eq((int)$projectID)->exec(); + if(!empty($_POST['division'])) $this->dao->update(TABLE_PROJECT)->set('division')->eq('1')->where('id')->eq((int)$projectID)->exec(); } $oldProductKeys = array_keys($oldProjectProducts); diff --git a/module/project/view/edit.html.php b/module/project/view/edit.html.php index 00ece4458c..79bc96f872 100755 --- a/module/project/view/edit.html.php +++ b/module/project/view/edit.html.php @@ -175,8 +175,8 @@
- division):?> - + model == 'waterfall'):?> + project->division;?> project->divisionList, $project->division);?> From 23f17a3812aa5039d294c69915b582eb0f5ea273 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 26 Oct 2022 10:57:27 +0800 Subject: [PATCH 036/608] * Add function to load the object of a class. --- framework/base/router.class.php | 51 +++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/framework/base/router.class.php b/framework/base/router.class.php index d991bdc01f..13bc9579ac 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -2181,6 +2181,57 @@ class baseRouter return isset($module) ? $module : false; } + /** + * 加载指定模块下的某种对象。 + * Load the target object of one module. + * + * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. + * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. + * @param string $class 对象的类型,可选值 model、zen、tao,默认为 model。The type of the object, optional values model, zen, tao, the default is model. + * @access public + * @return object|bool 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object. + */ + public function loadTarget($moduleName = '', $appName = '', $class = 'model') + { + if(empty($moduleName)) $moduleName = $this->moduleName; + if(empty($appName)) $appName = $this->appName; + + global $loadedTargets; + if(isset($loadedTargets[$class][$appName][$moduleName])) return $loadedTargets[$class][$appName][$moduleName]; + + $targetFile = $this->setModelFile($moduleName, $appName, $class); + + /** + * 如果没有target文件,返回false。 + * If no target file, return false. + */ + if(!helper::import($targetFile)) return false; + + /** + * 如果没有扩展文件,target类名是$moduleName + $class,如果有扩展,还需要增加ext前缀。 + * If no extension file, target class name is $moduleName + $class, else with 'ext' as the prefix. + */ + $targetClass = class_exists('ext' . $appName . $moduleName. $class) ? 'ext' . $appName . $moduleName . $class : $appName . $moduleName . $class; + if(!class_exists($targetClass)) + { + $targetClass = class_exists('ext' . $moduleName. $class) ? 'ext' . $moduleName . $class : $moduleName . $class; + if(!class_exists($targetClass)) $this->triggerError(" The $class $targetClass not found", __FILE__, __LINE__, $exit = true); + } + + /** + * 因为zen继承自control,tao继承自model,构造函数里会调用loadTarget方法,赋默认值值防止递归调用。 + */ + if($class == 'zen' || $class == 'tao') $loadedTargets[$class][$appName][$moduleName] = false; + + /** + * 初始化target 对象并返回。 + * Init the target object and return it. + */ + $target = new $targetClass($appName); + $loadedTargets[$class][$appName][$moduleName] = $target; + return $target; + } + /** * 设置请求的参数(PATH_INFO 方式)。 * Set the params by PATH_INFO. From b47999a32e637b232fbb69731a7581d296b1888e Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 26 Oct 2022 10:59:44 +0800 Subject: [PATCH 037/608] * Call the loadTarget function to load the model object of a module. --- framework/base/control.class.php | 56 ++++++-------------------------- 1 file changed, 10 insertions(+), 46 deletions(-) diff --git a/framework/base/control.class.php b/framework/base/control.class.php index 149e9ed108..c26bf22c56 100644 --- a/framework/base/control.class.php +++ b/framework/base/control.class.php @@ -262,37 +262,23 @@ class baseControl } /** - * 加载指定模块的model文件。 - * Load the model file of one module. + * 加载指定模块的model对象。 + * Load the model object of one module. * * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. - * @param string $type 对象的类型,可选值 model、zen、tao,默认为 model。The type of the object, optional values model, zen, tao, the default is model. * @access public * @return object|bool 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object. */ - public function loadModel($moduleName = '', $appName = '', $type = 'model') + public function loadModel($moduleName = '', $appName = '') { - if(empty($moduleName)) $moduleName = $this->moduleName; - if(empty($appName)) $appName = $this->appName; - - $objectName = $type == 'model' ? $moduleName : $moduleName . ucfirst($type); - - global $loadedModels; - if(isset($loadedModels[$type][$appName][$moduleName])) - { - $this->{$objectName} = $loadedModels[$type][$appName][$moduleName]; - if($type == 'model') $this->dao = $this->{$objectName}->dao; - return $this->{$objectName}; - } - - $modelFile = $this->app->setModelFile($moduleName, $appName, $type); + $model = $this->app->loadTarget($moduleName, $appName); /** - * 如果没有model文件,尝试加载config配置信息。 - * If no model file, try load config. + * 如果加载model失败,尝试加载config, lang配置信息。 + * If model is not loaded, try load config and lang. */ - if(!helper::import($modelFile)) + if(!$model) { $this->app->loadModuleConfig($moduleName, $appName); $this->app->loadLang($moduleName, $appName); @@ -300,31 +286,9 @@ class baseControl return false; } - /** - * 如果没有扩展文件,model类名是$moduleName + $type,如果有扩展,还需要增加ext前缀。 - * If no extension file, model class name is $moduleName + $type, else with 'ext' as the prefix. - */ - $modelClass = class_exists('ext' . $appName . $moduleName . $type) ? 'ext' . $appName . $moduleName . $type : $appName . $moduleName . $type; - if(!class_exists($modelClass)) - { - $modelClass = class_exists('ext' . $moduleName . $type) ? 'ext' . $moduleName . $type : $moduleName . $type; - if(!class_exists($modelClass)) $this->app->triggerError(" The $type $modelClass not found", __FILE__, __LINE__, $exit = true); - } - - /** - * 因为zen继承control,构造函数里会调用loadModel方法,赋默认值值防止递归调用。 - */ - if($type == 'zen') $loadedModels[$type][$appName][$moduleName] = false; - - /** - * 初始化model对象,在control对象中可以通过$this->$objectName来引用。同时将dao对象赋为control对象的成员变量,将view对象赋为zen对象的成员变量,方便引用。 - * Init the model object thus you can try $this->$objectName to access it. Also assign the $dao object as a member of control object, assign the $view object as a member of zen object. - */ - $this->{$objectName} = new $modelClass($appName); - if($type == 'model') $this->dao = $this->{$objectName}->dao; - if($type == 'zen') $this->{$objectName}->view = $this->view; - $loadedModels[$type][$appName][$moduleName] = $this->{$objectName}; - return $this->$objectName; + $this->{$moduleName} = $model; + $this->dao = $model->dao; + return $model; } /** From 8c185e925c4b09f5e3f76cb7ffb7bffd7529cbe1 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 26 Oct 2022 11:00:27 +0800 Subject: [PATCH 038/608] * Add function to load the zen object of a module. --- framework/base/control.class.php | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/framework/base/control.class.php b/framework/base/control.class.php index c26bf22c56..f902c426e1 100644 --- a/framework/base/control.class.php +++ b/framework/base/control.class.php @@ -231,6 +231,8 @@ class baseControl * Set super vars. */ $this->setSuperVars(); + + $this->loadZen($moduleName, $appName); } //-------------------- Model相关方法(Model related methods) --------------------// @@ -291,6 +293,38 @@ class baseControl return $model; } + /** + * 加载指定模块的zen对象。 + * Load the zen object of one module. + * + * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. + * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. + * @access public + * @return object|bool 如果没有zen文件,返回false,否则返回zen对象。If no zen file, return false, else return the zen object. + */ + public function loadZen($moduleName = '', $appName = '') + { + $zen = $this->app->loadTarget($moduleName, $appName, 'zen'); + + /** + * 如果加载zen失败,尝试加载config, lang配置信息。 + * If zen is not loaded, try load config and lang. + */ + if(!$zen) + { + $this->app->loadModuleConfig($moduleName, $appName); + $this->app->loadLang($moduleName, $appName); + $this->dao = new dao(); + return false; + } + + $zen->view = $this->view; + + $zenObjectName = $moduleName . 'Zen'; + $this->{$zenObjectName} = $zen; + return $zen; + } + /** * 设置超级全局变量,方便直接引用。 * Set the super vars. From 08ce854f4185ce34cdd88959e6ea8ed13ffe8f8d Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 26 Oct 2022 11:00:49 +0800 Subject: [PATCH 039/608] * Call the loadTarget function to load the model object of a module. --- framework/base/model.class.php | 47 ++-------------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/framework/base/model.class.php b/framework/base/model.class.php index f370fd5248..d03f32e385 100644 --- a/framework/base/model.class.php +++ b/framework/base/model.class.php @@ -201,55 +201,12 @@ class baseModel * * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. - * @param string $type 对象的类型,可选值 model、zen、tao,默认为 model。The type of the object, optional values model, zen, tao, the default is model. * @access public * @return object|bool the model object or false if model file not exists. */ - public function loadModel($moduleName, $appName = '', $type = 'model') + public function loadModel($moduleName, $appName = '') { - if(empty($moduleName)) $moduleName = $this->moduleName; - if(empty($appName)) $appName = $this->appName; - - $objectName = $type == 'model' ? $moduleName : $moduleName . ucfirst($type); - - global $loadedModels; - if(isset($loadedModels[$type][$appName][$moduleName])) - { - $this->{$objectName} = $loadedModels[$type][$appName][$moduleName]; - return $this->{$objectName}; - } - - $modelFile = $this->app->setModelFile($moduleName, $appName, $type); - - /** - * 如果没有model文件,返回。 - * If no model file, return. - */ - if(!helper::import($modelFile)) return false; - - /** - * 如果没有扩展文件,model类名是$moduleName + $type,如果有扩展,还需要增加ext前缀。 - * If no extension file, model class name is $moduleName + $type, else with 'ext' as the prefix. - */ - $modelClass = class_exists('ext' . $appName . $moduleName. $type) ? 'ext' . $appName . $moduleName . $type : $appName . $moduleName . $type; - if(!class_exists($modelClass)) - { - $modelClass = class_exists('ext' . $moduleName. $type) ? 'ext' . $moduleName . $type : $moduleName . $type; - if(!class_exists($modelClass)) $this->app->triggerError(" The $type $modelClass not found", __FILE__, __LINE__, $exit = true); - } - - /** - * 因为tao继承model,构造函数里会调用loadModel方法,赋默认值值防止递归调用。 - */ - if($type == 'tao') $loadedModels[$type][$appName][$moduleName] = false; - - /** - * 初始化model对象,在model对象中可以通过$this->$objectName来引用。 - * Init the model object thus you can try $this->$objectName to access it. - */ - $this->{$objectName} = new $modelClass($appName); - $loadedModels[$type][$appName][$moduleName] = $this->{$objectName}; - return $this->{$objectName}; + return $this->app->loadTarget($moduleName, $appName); } /** From 59ff8af5e62838650d2ab6141184c0cc6a87a022 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 26 Oct 2022 11:05:37 +0800 Subject: [PATCH 040/608] * Add the loadTao function to load the tao object of a module. --- framework/base/model.class.php | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/framework/base/model.class.php b/framework/base/model.class.php index d03f32e385..3b4eba3e61 100644 --- a/framework/base/model.class.php +++ b/framework/base/model.class.php @@ -150,6 +150,8 @@ class baseModel $this->loadDAO(); $this->setSuperVars(); + + $this->loadTao($moduleName, $this->appName); } /** @@ -194,10 +196,10 @@ class baseModel } /** - * 加载一个模块的model。加载完成后,使用$this->$moduleName来访问这个model对象。 + * 加载一个模块的model对象。加载完成后,使用$this->$moduleName来访问这个model对象。 * 比如:loadModel('user')引入user模块的model实例对象,可以通过$this->user来访问它。 * - * Load the model of one module. After loaded, can use $this->$moduleName to visit the model object. + * Load the model object of one module. After loaded, can use $this->$moduleName to visit the model object. * * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. @@ -209,6 +211,22 @@ class baseModel return $this->app->loadTarget($moduleName, $appName); } + /** + * 加载一个模块的tao对象。加载完成后,使用$this->$moduleName来访问这个tao对象。 + * 比如:loadModel('user')引入user模块的tao实例对象,可以通过$this->user来访问它。 + * + * Load the tao object of one module. After loaded, can use $this->$moduleName to visit the tao object. + * + * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. + * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. + * @access public + * @return object|bool the tao object or false if tao file not exists. + */ + public function loadTao($moduleName, $appName = '') + { + return $this->app->loadTarget($moduleName, $appName, 'tao'); + } + /** * 加载model的class扩展,主要是为了开发加密代码使用。 * 可以将主要的逻辑存放到$moduleName/ext/model/class/$extensionName.class.php中。 From 646e61e3db077edc62f55e7d3260bdb5352c1965 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 26 Oct 2022 11:07:19 +0800 Subject: [PATCH 041/608] * Revert the loadModel function. --- framework/control.class.php | 7 ++----- framework/model.class.php | 20 ++------------------ 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/framework/control.class.php b/framework/control.class.php index 428a8ff520..55edf6a042 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -33,8 +33,6 @@ class control extends baseControl { parent::__construct($moduleName, $methodName, $appName); - $this->loadModel($moduleName, $appName, 'zen'); - $this->app->setOpenApp(); if(defined('IN_USE') or (defined('RUN_MODE') and RUN_MODE != 'api')) $this->setPreference(); @@ -178,13 +176,12 @@ class control extends baseControl * * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. - * @param string $type 对象的类型,可选值 model、zen、tao,默认为 model。The type of the object, optional values model, zen, tao, the default is model. * @access public * @return object|bool 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object. */ - public function loadModel($moduleName = '', $appName = '', $type = 'model') + public function loadModel($moduleName = '', $appName = '') { - return parent::loadModel($moduleName, '', $type); + return parent::loadModel($moduleName); } /** diff --git a/framework/model.class.php b/framework/model.class.php index 977e69c42b..0c83223166 100644 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -20,21 +20,6 @@ include dirname(__FILE__) . '/base/model.class.php'; class model extends baseModel { - /** - * Load the tao file. - * - * @param string $appName - * @access public - * @return void - */ - public function __construct($appName = '') - { - parent::__construct($appName); - - $moduleName = $this->getModuleName(); - $this->loadModel($moduleName, $appName, 'tao'); - } - /** * 企业版部分功能是从然之合并过来的。ZDOO代码中调用loadModel方法时传递了一个非空的appName,在禅道中会导致错误。 * 调用父类的loadModel方法来避免这个错误。 @@ -43,13 +28,12 @@ class model extends baseModel * * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. - * @param string $type 对象的类型,可选值 model、zen、tao,默认为 model。The type of the object, optional values model, zen, tao, the default is model. * @access public * @return object|bool the model object or false if model file not exists. */ - public function loadModel($moduleName, $appName = '', $type = 'model') + public function loadModel($moduleName, $appName = '') { - return parent::loadModel($moduleName, '', $type); + return parent::loadModel($moduleName); } /** From ec23b692dfb3a12aca84eae745465a1eec99543f Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 26 Oct 2022 11:19:50 +0800 Subject: [PATCH 042/608] * Extend the loadZen function to be compatible with the codes merged from ZDOO. --- framework/control.class.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/framework/control.class.php b/framework/control.class.php index 55edf6a042..765fa342ba 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -184,6 +184,22 @@ class control extends baseControl return parent::loadModel($moduleName); } + /** + * 企业版部分功能是从然之合并过来的。ZDOO代码中调用loadZen方法时传递了一个非空的appName,在禅道中会导致错误。 + * 调用父类的loadZen方法来避免这个错误。 + * Some codes merged from ZDOO called the function loadZen with a non-empty appName which causes an error in zentao. + * Call the parent function with empty appName to avoid this error. + * + * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. + * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. + * @access public + * @return object|bool 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object. + */ + public function loadZen($moduleName = '', $appName = '') + { + return parent::loadZen($moduleName); + } + /** * 加载model的class扩展,主要是为了开发加密代码使用。 * 可以将主要的逻辑存放到$moduleName/ext/model/class/$extensionName.class.php中。 From c220eda19e70aa1fe492484d6d55aec0e769b620 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 26 Oct 2022 11:21:06 +0800 Subject: [PATCH 043/608] * Extend the loadTao function to be compatible with the codes merged from ZDOO. --- framework/model.class.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/framework/model.class.php b/framework/model.class.php index 0c83223166..2287fb1103 100644 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -36,6 +36,22 @@ class model extends baseModel return parent::loadModel($moduleName); } + /** + * 企业版部分功能是从然之合并过来的。ZDOO代码中调用loadTao方法时传递了一个非空的appName,在禅道中会导致错误。 + * 调用父类的loadTao方法来避免这个错误。 + * Some codes merged from ZDOO called the function loadTao with a non-empty appName which causes an error in zentao. + * Call the parent function with empty appName to avoid this error. + * + * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. + * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. + * @access public + * @return object|bool the model object or false if model file not exists. + */ + public function loadTao($moduleName, $appName = '') + { + return parent::loadTao($moduleName); + } + /** * 删除记录 * Delete one record. From 57c0dcbb8403611f0c6db3c0f106c90c57162281 Mon Sep 17 00:00:00 2001 From: Chenjianyu Date: Wed, 26 Oct 2022 13:13:50 +0800 Subject: [PATCH 044/608] Revert "* add an exception for approval flow notifications." This reverts commit 9637c6d3030461983922fb08f2ddbbaba5004d52. --- .../extension/xuan/im/ext/model/class/xuanxuan.class.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/xuanxuan/extension/xuan/im/ext/model/class/xuanxuan.class.php b/xuanxuan/extension/xuan/im/ext/model/class/xuanxuan.class.php index d1074e6e53..8391277656 100644 --- a/xuanxuan/extension/xuan/im/ext/model/class/xuanxuan.class.php +++ b/xuanxuan/extension/xuan/im/ext/model/class/xuanxuan.class.php @@ -214,16 +214,11 @@ class xuanxuanIm extends imModel $messageGroups[$contentData->contentType][] = $message; continue; } - if($contentData->objectType == 'story' && $contentData->action == 'reviewed') + if ($contentData->objectType == 'story' && $contentData->action == 'reviewed') { $extra = explode(',', $contentDataOuter->extra)[0]; $messageGroups["$contentData->objectType-$contentData->parentType-$contentData->action-$contentData->actor-$extra"][] = $message; } - if($message->contentType == 'text') - { - $messageGroups['text'][] = $message; - continue; - } else { $messageGroups["$contentData->objectType-$contentData->parentType-$contentData->action-$contentData->actor"][] = $message; From c761197f0a63b1dbe07a70d2885805ac63031b1b Mon Sep 17 00:00:00 2001 From: Chenjianyu Date: Wed, 26 Oct 2022 13:14:09 +0800 Subject: [PATCH 045/608] Revert "* add xuanxuan notification send feedback and review" This reverts commit 2eb3300ca6314f720a3e235bd462e80f9f7697e8. --- .../ext/model/class/xuanxuan.class.php | 72 ++----------------- 1 file changed, 6 insertions(+), 66 deletions(-) diff --git a/xuanxuan/extension/xuan/message/ext/model/class/xuanxuan.class.php b/xuanxuan/extension/xuan/message/ext/model/class/xuanxuan.class.php index 9ea25f0734..8a33333ac8 100644 --- a/xuanxuan/extension/xuan/message/ext/model/class/xuanxuan.class.php +++ b/xuanxuan/extension/xuan/message/ext/model/class/xuanxuan.class.php @@ -23,19 +23,10 @@ class xuanxuanMessage extends messageModel { $field = 'obj.*,project.name as projectName,product.name as productName,execu.name as execuName'; } - else if($objectType == 'feedback') - { - $field = 'obj.*,product.name as productName'; - } - else if($objectType == 'review') - { - $field = 'obj.*,project.name as projectName'; - } else { $field = 'obj.*'; } - $object = $this->dao->select($field)->from($this->config->objectTables[$objectType])->alias('obj') ->beginIF($objectType == 'task') ->leftJoin($this->config->objectTables['project'])->alias('project')->on('project.id = obj.project') @@ -49,12 +40,6 @@ class xuanxuanMessage extends messageModel ->leftJoin($this->config->objectTables['execution'])->alias('execu')->on('execu.id = obj.execution') ->leftJoin($this->config->objectTables['product'])->alias('product')->on('product.id = obj.product') ->fi() - ->beginIF($objectType == 'feedback') - ->leftJoin($this->config->objectTables['product'])->alias('product')->on('product.id = obj.product') - ->fi() - ->beginIF($objectType == 'review') - ->leftJoin($this->config->objectTables['project'])->alias('project')->on('project.id = obj.project') - ->fi() ->where('obj.id')->eq($objectID) ->fetch(); $field = $this->config->action->objectNameFields[$objectType]; @@ -64,43 +49,18 @@ class xuanxuanMessage extends messageModel $notifyType = strtolower(explode(',', $extra)[0]); if ($notifyType == 'pass') { - $title = sprintf($this->lang->message->notifyPassTitle, $this->app->user->realname, 1); + $title = $objectType == 'mr' ? '' : sprintf($this->lang->message->notifyPassTitle, $this->app->user->realname, 1); } else if($notifyType == 'clarify') { - $title = sprintf($this->lang->message->notifyClarifyTitle, $this->app->user->realname, 1); + $title = $objectType == 'mr' ? '' : sprintf($this->lang->message->notifyClarifyTitle, $this->app->user->realname, 1); } else if($notifyType == 'reject') { - $title = sprintf($this->lang->message->notifyRejectTitle, $this->app->user->realname, 1); + $title = $objectType == 'mr' ? '' : sprintf($this->lang->message->notifyRejectTitle, $this->app->user->realname, 1); } } - if ($objectType == 'feedback' && ($actionType == 'tobug' || $actionType == 'tostory' || $actionType == 'totask' || $actionType == 'todo')) - { - if ($actionType == 'tobug') - { - $title = sprintf($this->lang->message->feedbackToBugTitle, $this->app->user->realname, 1); - } - else if($actionType == 'tostory') - { - $title = sprintf($this->lang->message->feedbackToStoryTitle, $this->app->user->realname, 1); - } - else if($actionType == 'totask') - { - $title = sprintf($this->lang->message->feedbackToTaskTitle, $this->app->user->realname, 1); - } - else if($actionType == 'todo') - { - $title = sprintf($this->lang->message->feedbackToDoTitle, $this->app->user->realname, 1); - } - } - - if ($objectType == 'review' && $actionType == 'toaudit') - { - $title = sprintf($this->lang->message->reviewToauditTitle, $this->app->user->realname, 1); - } - $server = $this->loadModel('im')->getServer('zentao'); $onlybody = isset($_GET['onlybody']) ? $_GET['onlybody'] : ''; unset($_GET['onlybody']); @@ -111,12 +71,10 @@ class xuanxuanMessage extends messageModel if(!empty($object->assignedTo)) $target .= $object->assignedTo == 'closed' ? $object->openedBy : $object->assignedTo; if(!empty($object->mailto)) $target .= ",{$object->mailto}"; if(($objectType == 'mr' or $objectType == 'kanbancard') and !empty($object->createdBy)) $target .= ",{$object->createdBy}"; - if($objectType == 'review') $target .= ",{$object->auditedBy}"; $target = trim($target, ','); - $target = explode(',', $target); $target = $this->dao->select('id')->from(TABLE_USER) ->where('account')->in($target) - ->beginIF($objectType != 'mr' && $objectType != 'review')->andWhere('account')->ne($this->app->user->account)->fi() + ->beginIF($objectType != 'mr')->andWhere('account')->ne($this->app->user->account)->fi() ->fetchAll('id'); $target = array_keys($target); @@ -152,24 +110,6 @@ class xuanxuanMessage extends messageModel $subcontent->parentURL = "xxc:openInApp/zentao-integrated/" . urlencode($server . helper::createLink($parentType, 'browse', "id=$subcontent->parent", 'html')); $subcontent->cardURL = $url; } - elseif($objectType == 'feedback') - { - $subcontent->headTitle = $object->productName; - $subcontent->headSubTitle = $object->execuName; - $subcontent->parentType = 'product'; - $subcontent->parent = $object->product; - $subcontent->parentURL = "xxc:openInApp/zentao-integrated/" . urlencode($server . helper::createLink('feedback', 'browse', "id=$object->product", 'html')); - $subcontent->cardURL = $url; - } - elseif($objectType == 'review') - { - $subcontent->headTitle = $object->projectName; - $subcontent->headSubTitle = $object->execuName; - $subcontent->parentType = 'product'; - $subcontent->parent = $object->product; - $subcontent->parentURL = "xxc:openInApp/zentao-integrated/" . urlencode($server . helper::createLink('review', 'browse', "id=$object->product", 'html')); - $subcontent->cardURL = $url; - } else { $subcontent->parentType = $objectType; @@ -206,11 +146,11 @@ class xuanxuanMessage extends messageModel $contentData->actions = array(); $contentData->url = "xxc:openInApp/zentao-integrated/" . urlencode($url); } - $contentData->extra = is_array($extra) ? $extra : ''; + $contentData->extra = $extra; $content = json_encode($contentData); $avatarUrl = $server . $this->app->getWebRoot() . 'favicon.ico'; - if($target && ($objectType == 'bug' || $objectType == 'task' || $objectType == 'story' || $objectType == 'feedback' || $objectType == 'review')) $this->loadModel('im')->messageCreateNotify($target, $title, $subtitle = '', $content, $contentType = 'object', $url, $actions = array(), $sender = array('id' => 'zentao', 'realname' => $this->lang->message->sender, 'name' => $this->lang->message->sender, 'avatar' => $avatarUrl)); + if($target && ($objectType == 'bug' || $objectType == 'task' || $objectType == 'story')) $this->loadModel('im')->messageCreateNotify($target, $title, $subtitle = '', $content, $contentType = 'object', $url, $actions = array(), $sender = array('id' => 'zentao', 'realname' => $this->lang->message->sender, 'name' => $this->lang->message->sender, 'avatar' => $avatarUrl)); if($objectType == 'mr' and is_array($this->lang->message->mr->$actionType) and !empty($object->assignee)) { From 5a84b1669ea417ed9e3360dafcc47fcc9abb5782 Mon Sep 17 00:00:00 2001 From: Chenjianyu Date: Wed, 26 Oct 2022 13:29:20 +0800 Subject: [PATCH 046/608] * add xuanxuan feedback notifications. --- .../xuan/message/ext/lang/de/xuanxuan.php | 2 - .../xuan/message/ext/lang/en/xuanxuan.php | 2 - .../xuan/message/ext/lang/fr/xuanxuan.php | 2 - .../xuan/message/ext/lang/zh-cn/xuanxuan.php | 2 - .../ext/model/class/xuanxuan.class.php | 46 +++++++++++++++++-- 5 files changed, 41 insertions(+), 13 deletions(-) diff --git a/xuanxuan/extension/xuan/message/ext/lang/de/xuanxuan.php b/xuanxuan/extension/xuan/message/ext/lang/de/xuanxuan.php index 73807b5a85..f81d6076f2 100644 --- a/xuanxuan/extension/xuan/message/ext/lang/de/xuanxuan.php +++ b/xuanxuan/extension/xuan/message/ext/lang/de/xuanxuan.php @@ -13,8 +13,6 @@ $lang->message->feedbackToTaskTitle = '%s have forwarded %d feedback to task'; $lang->message->feedbackToDoTitle = '%s have forwarded %d feedback to todo'; $lang->message->feedbackToStoryTitle = '%s have forwarded %d feedback to story'; -$lang->message->reviewToauditTitle = '%s have submit %d audits'; - $lang->message->mr = new stdClass(); $lang->message->mr->logTitle = 'Build log'; $lang->message->mr->compilefail = 'Your submitted merge request: %s, build failed'; diff --git a/xuanxuan/extension/xuan/message/ext/lang/en/xuanxuan.php b/xuanxuan/extension/xuan/message/ext/lang/en/xuanxuan.php index 73807b5a85..f81d6076f2 100644 --- a/xuanxuan/extension/xuan/message/ext/lang/en/xuanxuan.php +++ b/xuanxuan/extension/xuan/message/ext/lang/en/xuanxuan.php @@ -13,8 +13,6 @@ $lang->message->feedbackToTaskTitle = '%s have forwarded %d feedback to task'; $lang->message->feedbackToDoTitle = '%s have forwarded %d feedback to todo'; $lang->message->feedbackToStoryTitle = '%s have forwarded %d feedback to story'; -$lang->message->reviewToauditTitle = '%s have submit %d audits'; - $lang->message->mr = new stdClass(); $lang->message->mr->logTitle = 'Build log'; $lang->message->mr->compilefail = 'Your submitted merge request: %s, build failed'; diff --git a/xuanxuan/extension/xuan/message/ext/lang/fr/xuanxuan.php b/xuanxuan/extension/xuan/message/ext/lang/fr/xuanxuan.php index 73807b5a85..f81d6076f2 100644 --- a/xuanxuan/extension/xuan/message/ext/lang/fr/xuanxuan.php +++ b/xuanxuan/extension/xuan/message/ext/lang/fr/xuanxuan.php @@ -13,8 +13,6 @@ $lang->message->feedbackToTaskTitle = '%s have forwarded %d feedback to task'; $lang->message->feedbackToDoTitle = '%s have forwarded %d feedback to todo'; $lang->message->feedbackToStoryTitle = '%s have forwarded %d feedback to story'; -$lang->message->reviewToauditTitle = '%s have submit %d audits'; - $lang->message->mr = new stdClass(); $lang->message->mr->logTitle = 'Build log'; $lang->message->mr->compilefail = 'Your submitted merge request: %s, build failed'; diff --git a/xuanxuan/extension/xuan/message/ext/lang/zh-cn/xuanxuan.php b/xuanxuan/extension/xuan/message/ext/lang/zh-cn/xuanxuan.php index 2d71146eab..ab4bfdae20 100644 --- a/xuanxuan/extension/xuan/message/ext/lang/zh-cn/xuanxuan.php +++ b/xuanxuan/extension/xuan/message/ext/lang/zh-cn/xuanxuan.php @@ -13,8 +13,6 @@ $lang->message->feedbackToTaskTitle = '%s 已将%d个反馈转至任务'; $lang->message->feedbackToDoTitle = '%s 已将%d个反馈转至待办'; $lang->message->feedbackToStoryTitle = '%s 已将%d个反馈转至研发需求'; -$lang->message->reviewToauditTitle = '%s 已经提交了%d个审计'; - $lang->message->mr = new stdClass(); $lang->message->mr->logTitle = '构建日志'; $lang->message->mr->compilefail = '您提交的合并请求:%s,构建任务执行失败'; diff --git a/xuanxuan/extension/xuan/message/ext/model/class/xuanxuan.class.php b/xuanxuan/extension/xuan/message/ext/model/class/xuanxuan.class.php index 8a33333ac8..b5cfc3ba77 100644 --- a/xuanxuan/extension/xuan/message/ext/model/class/xuanxuan.class.php +++ b/xuanxuan/extension/xuan/message/ext/model/class/xuanxuan.class.php @@ -23,6 +23,10 @@ class xuanxuanMessage extends messageModel { $field = 'obj.*,project.name as projectName,product.name as productName,execu.name as execuName'; } + else if($objectType == 'feedback') + { + $field = 'obj.*,product.name as productName'; + } else { $field = 'obj.*'; @@ -40,6 +44,9 @@ class xuanxuanMessage extends messageModel ->leftJoin($this->config->objectTables['execution'])->alias('execu')->on('execu.id = obj.execution') ->leftJoin($this->config->objectTables['product'])->alias('product')->on('product.id = obj.product') ->fi() + ->beginIF($objectType == 'feedback') + ->leftJoin($this->config->objectTables['product'])->alias('product')->on('product.id = obj.product') + ->fi() ->where('obj.id')->eq($objectID) ->fetch(); $field = $this->config->action->objectNameFields[$objectType]; @@ -49,15 +56,35 @@ class xuanxuanMessage extends messageModel $notifyType = strtolower(explode(',', $extra)[0]); if ($notifyType == 'pass') { - $title = $objectType == 'mr' ? '' : sprintf($this->lang->message->notifyPassTitle, $this->app->user->realname, 1); + $title = sprintf($this->lang->message->notifyPassTitle, $this->app->user->realname, 1); } else if($notifyType == 'clarify') { - $title = $objectType == 'mr' ? '' : sprintf($this->lang->message->notifyClarifyTitle, $this->app->user->realname, 1); + $title = sprintf($this->lang->message->notifyClarifyTitle, $this->app->user->realname, 1); } else if($notifyType == 'reject') { - $title = $objectType == 'mr' ? '' : sprintf($this->lang->message->notifyRejectTitle, $this->app->user->realname, 1); + $title = sprintf($this->lang->message->notifyRejectTitle, $this->app->user->realname, 1); + } + } + + if ($objectType == 'feedback' && ($actionType == 'tobug' || $actionType == 'tostory' || $actionType == 'totask' || $actionType == 'todo')) + { + if ($actionType == 'tobug') + { + $title = sprintf($this->lang->message->feedbackToBugTitle, $this->app->user->realname, 1); + } + else if($actionType == 'tostory') + { + $title = sprintf($this->lang->message->feedbackToStoryTitle, $this->app->user->realname, 1); + } + else if($actionType == 'totask') + { + $title = sprintf($this->lang->message->feedbackToTaskTitle, $this->app->user->realname, 1); + } + else if($actionType == 'todo') + { + $title = sprintf($this->lang->message->feedbackToDoTitle, $this->app->user->realname, 1); } } @@ -110,6 +137,15 @@ class xuanxuanMessage extends messageModel $subcontent->parentURL = "xxc:openInApp/zentao-integrated/" . urlencode($server . helper::createLink($parentType, 'browse', "id=$subcontent->parent", 'html')); $subcontent->cardURL = $url; } + elseif($objectType == 'feedback') + { + $subcontent->headTitle = $object->productName; + $subcontent->headSubTitle = $object->execuName; + $subcontent->parentType = 'product'; + $subcontent->parent = $object->product; + $subcontent->parentURL = "xxc:openInApp/zentao-integrated/" . urlencode($server . helper::createLink('feedback', 'browse', "id=$object->product", 'html')); + $subcontent->cardURL = $url; + } else { $subcontent->parentType = $objectType; @@ -146,11 +182,11 @@ class xuanxuanMessage extends messageModel $contentData->actions = array(); $contentData->url = "xxc:openInApp/zentao-integrated/" . urlencode($url); } - $contentData->extra = $extra; + $contentData->extra = is_array($extra) ? $extra : ''; $content = json_encode($contentData); $avatarUrl = $server . $this->app->getWebRoot() . 'favicon.ico'; - if($target && ($objectType == 'bug' || $objectType == 'task' || $objectType == 'story')) $this->loadModel('im')->messageCreateNotify($target, $title, $subtitle = '', $content, $contentType = 'object', $url, $actions = array(), $sender = array('id' => 'zentao', 'realname' => $this->lang->message->sender, 'name' => $this->lang->message->sender, 'avatar' => $avatarUrl)); + if($target && ($objectType == 'bug' || $objectType == 'task' || $objectType == 'story' || $objectType == 'feedback')) $this->loadModel('im')->messageCreateNotify($target, $title, $subtitle = '', $content, $contentType = 'object', $url, $actions = array(), $sender = array('id' => 'zentao', 'realname' => $this->lang->message->sender, 'name' => $this->lang->message->sender, 'avatar' => $avatarUrl)); if($objectType == 'mr' and is_array($this->lang->message->mr->$actionType) and !empty($object->assignee)) { From 9b7ccef03476cd7f8bd1347a438e9a0aca72863c Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 26 Oct 2022 13:56:11 +0800 Subject: [PATCH 047/608] * Optimize the comment. --- framework/base/control.class.php | 12 ++++++++---- framework/base/model.class.php | 10 +++++----- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/framework/base/control.class.php b/framework/base/control.class.php index f902c426e1..a1a4c28c07 100644 --- a/framework/base/control.class.php +++ b/framework/base/control.class.php @@ -264,8 +264,10 @@ class baseControl } /** - * 加载指定模块的model对象。 - * Load the model object of one module. + * 加载一个模块的model对象。加载完成后,使用$this->$moduleName来访问这个model对象。 + * 比如:loadModel('user')引入user模块的model实例对象,可以通过$this->user来访问它。 + * + * Load the model object of one module. After loaded, can use $this->$moduleName to visit the model object. * * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. @@ -294,8 +296,10 @@ class baseControl } /** - * 加载指定模块的zen对象。 - * Load the zen object of one module. + * 加载一个模块的zen对象。加载完成后,使用$this->{$moduleName}Zen来访问这个zen对象。 + * 比如:loadZen('user')引入user模块的zen实例对象,可以通过$this->userZen来访问它。 + * + * Load the zen object of one module. After loaded, can use $this->{$moduleName}Zen to visit the zen object. * * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. diff --git a/framework/base/model.class.php b/framework/base/model.class.php index 3b4eba3e61..84437a42f8 100644 --- a/framework/base/model.class.php +++ b/framework/base/model.class.php @@ -204,7 +204,7 @@ class baseModel * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. * @access public - * @return object|bool the model object or false if model file not exists. + * @return object|bool 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object. */ public function loadModel($moduleName, $appName = '') { @@ -212,15 +212,15 @@ class baseModel } /** - * 加载一个模块的tao对象。加载完成后,使用$this->$moduleName来访问这个tao对象。 - * 比如:loadModel('user')引入user模块的tao实例对象,可以通过$this->user来访问它。 + * 加载一个模块的tao对象。加载完成后,使用$this->{$moduleName}Tao来访问这个tao对象。 + * 比如:loadTao('user')引入user模块的tao实例对象,可以通过$this->userTao来访问它。 * - * Load the tao object of one module. After loaded, can use $this->$moduleName to visit the tao object. + * Load the tao object of one module. After loaded, can use $this->{$moduleName}Tao to visit the tao object. * * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name. * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name. * @access public - * @return object|bool the tao object or false if tao file not exists. + * @return object|bool 如果没有tao文件,返回false,否则返回tao对象。If no tao file, return false, else return the tao object. */ public function loadTao($moduleName, $appName = '') { From a3da6393be56d0e4f7f157e882a342bc470098d8 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 26 Oct 2022 13:57:38 +0800 Subject: [PATCH 048/608] * Don't need load config and lang when load the zen object. --- framework/base/control.class.php | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/framework/base/control.class.php b/framework/base/control.class.php index a1a4c28c07..824ad69458 100644 --- a/framework/base/control.class.php +++ b/framework/base/control.class.php @@ -309,18 +309,7 @@ class baseControl public function loadZen($moduleName = '', $appName = '') { $zen = $this->app->loadTarget($moduleName, $appName, 'zen'); - - /** - * 如果加载zen失败,尝试加载config, lang配置信息。 - * If zen is not loaded, try load config and lang. - */ - if(!$zen) - { - $this->app->loadModuleConfig($moduleName, $appName); - $this->app->loadLang($moduleName, $appName); - $this->dao = new dao(); - return false; - } + if(!$zen) return false; $zen->view = $this->view; From 3c46850e0ed65081b97957bbfbd7d99821c38554 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 26 Oct 2022 13:58:18 +0800 Subject: [PATCH 049/608] * Return false when the target object is empty to avoid assigning property to a null object. --- framework/base/model.class.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/framework/base/model.class.php b/framework/base/model.class.php index 84437a42f8..21f00298e8 100644 --- a/framework/base/model.class.php +++ b/framework/base/model.class.php @@ -208,7 +208,11 @@ class baseModel */ public function loadModel($moduleName, $appName = '') { - return $this->app->loadTarget($moduleName, $appName); + $model = $this->app->loadTarget($moduleName, $appName); + if(!$model) return false; + + $this->{$moduleName} = $model; + return $model; } /** @@ -224,7 +228,12 @@ class baseModel */ public function loadTao($moduleName, $appName = '') { - return $this->app->loadTarget($moduleName, $appName, 'tao'); + $tao = $this->app->loadTarget($moduleName, $appName, 'tao'); + if(!$tao) return false; + + $taoObjectName = $moduleName . 'Tao'; + $this->{$taoObjectName} = $tao; + return $tao; } /** From 3848e7312d2547f023027d055b6ac0b61a0f0121 Mon Sep 17 00:00:00 2001 From: Guan Xiying Date: Wed, 26 Oct 2022 14:00:12 +0800 Subject: [PATCH 050/608] * Use $this->moduleName instead of $moduleName for it might be empty sometimes. --- framework/base/control.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/base/control.class.php b/framework/base/control.class.php index 824ad69458..6883700bbb 100644 --- a/framework/base/control.class.php +++ b/framework/base/control.class.php @@ -232,7 +232,7 @@ class baseControl */ $this->setSuperVars(); - $this->loadZen($moduleName, $appName); + $this->loadZen($this->moduleName, $appName); } //-------------------- Model相关方法(Model related methods) --------------------// From 2f0471084314e99926a0b54455eadbd6b3f05ef9 Mon Sep 17 00:00:00 2001 From: Yagami Date: Wed, 26 Oct 2022 15:41:53 +0800 Subject: [PATCH 051/608] * Finish task #73233. --- module/project/control.php | 11 +++++++++++ module/project/js/create.js | 2 +- module/project/model.php | 7 +++++++ module/project/view/create.html.php | 2 ++ module/project/view/edit.html.php | 6 ++++-- 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/module/project/control.php b/module/project/control.php index 64c64facf5..db36c579eb 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -704,6 +704,16 @@ class project extends control if($project->model != 'kanban') $canChangeModel = $this->project->checkCanChangeModel($projectID, $project->model); + /* Get stages group by project's product. */ + $productStages = $this->dao->select('t1.product,t1.project')->from(TABLE_PROJECTPRODUCT)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->where('t2.deleted')->eq('0') + ->andWhere('t2.type')->ne('project') + ->andWhere('t2.project')->eq($projectID) + ->andWhere('t1.product')->in($linkedProductIdList) + ->groupBy('t1.product') + ->fetchGroup('product'); + $this->view->title = $this->lang->project->edit; $this->view->position[] = $this->lang->project->edit; @@ -719,6 +729,7 @@ class project extends control $this->view->linkedProducts = $linkedProducts; $this->view->linkedBranches = $linkedBranches; $this->view->branches = $branches; + $this->view->multiProductStages = ($project->division and count($linkedProducts) > 1 and count($productStages) > 1); $this->view->unmodifiableProducts = $unmodifiableProducts; $this->view->unmodifiableBranches = $unmodifiableBranches; $this->view->unmodifiableMainBranches = $unmodifiableMainBranches; diff --git a/module/project/js/create.js b/module/project/js/create.js index 4ae6217d3e..947f2257bb 100644 --- a/module/project/js/create.js +++ b/module/project/js/create.js @@ -267,7 +267,7 @@ function loadBranches(product) } }); - chosenProducts > 1 ? $('.division').removeClass('hide') : $('.division').addClass('hide'); + (chosenProducts > 1 && model == 'waterfall') ? $('.division').removeClass('hide') : $('.division').addClass('hide'); if($('#productsBox .row .input-group:last select:first').val() != 0) { diff --git a/module/project/model.php b/module/project/model.php index 9e1f45844c..afc399e1dd 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -1469,6 +1469,13 @@ class projectModel extends model $this->updateProducts($projectID, $_POST['products']); $this->file->updateObjectID($this->post->uid, $projectID, 'project'); + /* Link project's products to project's stages when project's division is closed and products has changed. */ + if(!$project->division and $_POST['products'] != $linkedProducts and $oldProject->model == 'waterfall') + { + $stages = $this->loadModel('execution')->getPairs($projectID); + foreach($stages as $stageID => $name) $this->execution->updateProducts($stageID); + } + $whitelist = explode(',', $project->whitelist); $this->loadModel('personnel')->updateWhitelist($whitelist, 'project', $projectID); if($project->acl != 'open') diff --git a/module/project/view/create.html.php b/module/project/view/create.html.php index 5c9a32a140..fd2f8b7424 100755 --- a/module/project/view/create.html.php +++ b/module/project/view/create.html.php @@ -175,10 +175,12 @@
+ project->division;?> project->divisionList, '0');?> + execution->team;?> diff --git a/module/project/view/edit.html.php b/module/project/view/edit.html.php index 79bc96f872..d937e56c53 100755 --- a/module/project/view/edit.html.php +++ b/module/project/view/edit.html.php @@ -176,9 +176,11 @@ model == 'waterfall'):?> - + division and count($linkedProducts) < 2) ? 'hide' : '';?> + + project->division;?> - project->divisionList, $project->division);?> + project->divisionList, $project->division, $disabled);?> model == 'kanban'):?> From 7299a84a973cb0aed7b7f355a6a9558b06b24313 Mon Sep 17 00:00:00 2001 From: Yagami Date: Wed, 26 Oct 2022 16:53:01 +0800 Subject: [PATCH 052/608] * Finish task #73238. --- module/execution/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 module/execution/model.php diff --git a/module/execution/model.php b/module/execution/model.php old mode 100644 new mode 100755 index dfebc4e9be..1c3810d128 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -1635,7 +1635,7 @@ class executionModel extends model ->beginIF($limit)->limit($limit)->fi() ->fetchAll('id'); - if(isset($project->model) and $project->model == 'waterfall') + if(isset($project->model) and $project->model == 'waterfall' and $project->division) { $executionList = array(); $executionProducts = $this->dao->select('t1.project,t1.product')->from(TABLE_PROJECTPRODUCT)->alias('t1') From d96d6bb803a5ffdda5ac9efff6c898789f753929 Mon Sep 17 00:00:00 2001 From: tanghucheng Date: Thu, 27 Oct 2022 08:09:26 +0800 Subject: [PATCH 053/608] * Finish task #73234,73242. --- module/execution/control.php | 20 ++++++++++++++++++++ module/execution/js/common.js | 16 +++++++++------- module/execution/model.php | 9 ++++++++- module/execution/view/create.html.php | 7 ++++++- module/programplan/control.php | 1 + module/programplan/view/gantt.html.php | 4 ++++ module/project/control.php | 13 +++++++++++-- module/project/css/execution.css | 1 + module/project/view/execution.html.php | 4 ++++ 9 files changed, 64 insertions(+), 11 deletions(-) diff --git a/module/execution/control.php b/module/execution/control.php index 5068b485e1..4bd148740c 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1646,6 +1646,26 @@ class execution extends control $this->view->linkedBranches = $linkedBranches; } + if(!$project->division) + { + $products = $this->loadModel('product')->getProducts($projectID); + $branches = $this->project->getBranchesByProject($projectID); + $plans = $this->loadModel('productplan')->getGroupByProduct(array_keys($products), 'skipParent|unexpired'); + + $linkedBranches = array(); + foreach($products as $productID => $product) + { + foreach($branches[$productID] as $branchID => $branch) + { + $linkedBranches[$productID][$branchID] = $branchID; + $productPlans[$productID][$branchID] = isset($plans[$productID][$branchID]) ? $plans[$productID][$branchID] : array(); + } + } + + $this->view->branches = $branches; + $this->view->linkedBranches = $linkedBranches; + } + if(!empty($_POST)) { $executionID = $this->execution->create($copyExecutionID); diff --git a/module/execution/js/common.js b/module/execution/js/common.js index 1ede120620..499bff5775 100644 --- a/module/execution/js/common.js +++ b/module/execution/js/common.js @@ -124,13 +124,15 @@ function loadBranches(product) { if($('#productsBox .input-group:last select:first').val() != 0) { - var length = $('#productsBox .input-group').size(); - $('#productsBox .row').append('
' + $('#productsBox .col-sm-4:last').html().replace('required', '') + '
'); - if($('#productsBox .input-group:last select').size() >= 2) $('#productsBox .input-group:last select:last').remove(); - $('#productsBox .input-group:last .chosen-container').remove(); - $('#productsBox .input-group:last select:first').attr('name', 'products[' + length + ']').attr('id', 'products' + length); - $('#productsBox .input-group:last .chosen').chosen(); - + if(model !== 'waterfall') + { + var length = $('#productsBox .input-group').size(); + $('#productsBox .row').append('
' + $('#productsBox .col-sm-4:last').html().replace('required', '') + '
'); + if($('#productsBox .input-group:last select').size() >= 2) $('#productsBox .input-group:last select:last').remove(); + $('#productsBox .input-group:last .chosen-container').remove(); + $('#productsBox .input-group:last select:first').attr('name', 'products[' + length + ']').attr('id', 'products' + length); + $('#productsBox .input-group:last .chosen').chosen(); + } adjustProductBoxMargin(); } diff --git a/module/execution/model.php b/module/execution/model.php index d60d43d29a..eefd118e6f 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -339,6 +339,12 @@ class executionModel extends model $type = 'sprint'; if($project) $type = zget($this->config->execution->modelList, $project->model, 'sprint'); + if($project->model == 'waterfall') + { + $this->checkWorkload('create', $_POST['percent'], $project); + if(dao::isError()) return false; + } + $this->config->execution->create->requiredFields .= ',project'; } @@ -1175,7 +1181,7 @@ class executionModel extends model } /* The total workload of the first stage should not exceed 100%. */ - if($type == 'create' or (empty($oldExecution) and $oldExecution->grade == 1)) + if($type == 'create' or (!empty($oldExecution) and $oldExecution->grade == 1)) { $oldPercentTotal = $this->dao->select('SUM(t2.percent) as total')->from(TABLE_PROJECTPRODUCT)->alias('t1') ->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.project=t2.id') @@ -4616,6 +4622,7 @@ class executionModel extends model $burns = join(',', $execution->burns); echo ""; + if(!empty($execution->division)) echo "{$execution->productName}"; echo ""; if(common::hasPriv('execution', 'batchEdit')) echo "id class='table-nest-icon icon table-nest-toggle'>"; if($this->config->systemMode == 'new') diff --git a/module/execution/view/create.html.php b/module/execution/view/create.html.php index 4da8c28962..25bc3cdfe3 100644 --- a/module/execution/view/create.html.php +++ b/module/execution/view/create.html.php @@ -48,6 +48,7 @@ execution->cancelCopy);?> execution->copyNoExecution);?> +model);?>
@@ -137,12 +138,14 @@
+ division ? '' : 'disabled';?> type != 'normal' and isset($branchGroups[$product->id]));?> id] as $branchID => $branch):?>
- id, "class='form-control chosen' onchange='loadBranches(this)' data-last='" . $product->id . "'");?> + id, "class='form-control chosen' $class onchange='loadBranches(this)' data-last='" . $product->id . "'");?> + id);?> id], $branchID, "class='form-control chosen' onchange=\"loadPlans('#products{$i}', this.value)\"");?>
@@ -150,12 +153,14 @@ + division):?>
+
diff --git a/module/programplan/control.php b/module/programplan/control.php index efb2988be9..e0414d396e 100644 --- a/module/programplan/control.php +++ b/module/programplan/control.php @@ -110,6 +110,7 @@ class programplan extends control $this->view->title = $this->lang->programplan->browse; $this->view->position[] = $this->lang->programplan->browse; $this->view->projectID = $projectID; + $this->view->project = $this->project->getByID($projectID); $this->view->productID = $this->productID; $this->view->productList = $this->loadModel('product')->getProductPairsByProject($projectID); $this->view->type = $type; diff --git a/module/programplan/view/gantt.html.php b/module/programplan/view/gantt.html.php index e68b128d0e..f766ce1705 100644 --- a/module/programplan/view/gantt.html.php +++ b/module/programplan/view/gantt.html.php @@ -80,6 +80,7 @@ form {display: block; margin-top: 0em; margin-block-end: 1em;} app->getModuleName() == 'programplan'):?>
+ division) or !empty($project->hasProduct)):?> product->allProduct;?> + + programplan->gantt;?> +
diff --git a/module/project/control.php b/module/project/control.php index 64c64facf5..656ab48760 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -1035,10 +1035,19 @@ class project extends control $this->view->title = $this->lang->execution->allExecutions; $this->view->position[] = $this->lang->execution->allExecutions; - $executionStats = $this->execution->getStatData($projectID, $status, $productID, 0, $this->cookie->showTask, '', $orderBy, $pager); - $showToggleIcon = false; + $executionStats = $this->execution->getStatData($projectID, $status, $productID, 0, $this->cookie->showTask, '', $orderBy, $pager); + $showToggleIcon = false; + $productNameList = $this->dao->select('t1.id,GROUP_CONCAT(t3.`name`) as productName')->from(TABLE_EXECUTION)->alias('t1') + ->leftjoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id=t2.project') + ->leftjoin(TABLE_PRODUCT)->alias('t3')->on('t2.product=t3.id') + ->where('t1.project')->eq($projectID) + ->andWhere('t1.type')->eq('stage') + ->groupBy('t1.id') + ->fetchPairs(); + foreach($executionStats as $execution) { + $execution->productName = isset($productNameList[$execution->id]) ? $productNameList[$execution->id] : ''; if(!empty($execution->tasks) or !empty($execution->children)) { $showToggleIcon = true; diff --git a/module/project/css/execution.css b/module/project/css/execution.css index 71939a8e6b..4c3cddba23 100644 --- a/module/project/css/execution.css +++ b/module/project/css/execution.css @@ -13,6 +13,7 @@ th.table-nest-title .check-all {position: absolute; left: 15px; top: 7px;} #executionTableList > tr:not(.has-nest-child) .project-type-label {margin-left: 22px;} .table-statistic {padding-left: 10px;} td.flex {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center; margin-bottom: 0px;} +th.c-name {width: 80px;} td.c-name > .project-type-label {flex: 0 0 36px; padding-right: 2px;} .c-name > a, .table-children .text-left > a, .c-name > span.text-ellipsis { padding-left: 5px; text-overflow: clip;} span.table-nest-icon.table-nest-toggle {min-width: 22px; max-width: 22px;} diff --git a/module/project/view/execution.html.php b/module/project/view/execution.html.php index d349c0629b..af18757430 100644 --- a/module/project/view/execution.html.php +++ b/module/project/view/execution.html.php @@ -14,6 +14,7 @@ execution->checkedExecutions);?>