From 402bda75794d87a64d274bb36cf4b79fea0a0740 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Thu, 4 Jul 2019 13:40:37 +0800 Subject: [PATCH] * finish task #6055. --- module/common/lang/en.php | 6 +- module/common/lang/menuOrder.php | 2 + module/common/lang/zh-cn.php | 6 +- module/editor/config.php | 18 + module/editor/control.php | 182 +++++++++ module/editor/css/edit.css | 2 + module/editor/css/extend.css | 5 + module/editor/css/index.css | 6 + module/editor/js/edit.js | 1 + module/editor/js/index.js | 12 + module/editor/lang/en.php | 75 ++++ module/editor/lang/zh-cn.php | 76 ++++ module/editor/lang/zh-tw.php | 75 ++++ module/editor/model.php | 572 ++++++++++++++++++++++++++++ module/editor/view/edit.html.php | 79 ++++ module/editor/view/extend.html.php | 42 ++ module/editor/view/index.html.php | 49 +++ module/editor/view/newpage.html.php | 37 ++ module/group/lang/resource.php | 16 + module/testcase/lang/en.php | 4 +- module/translate/control.php | 7 + 21 files changed, 1268 insertions(+), 4 deletions(-) create mode 100644 module/editor/config.php create mode 100644 module/editor/control.php create mode 100644 module/editor/css/edit.css create mode 100644 module/editor/css/extend.css create mode 100644 module/editor/css/index.css create mode 100644 module/editor/js/edit.js create mode 100644 module/editor/js/index.js create mode 100644 module/editor/lang/en.php create mode 100644 module/editor/lang/zh-cn.php create mode 100644 module/editor/lang/zh-tw.php create mode 100644 module/editor/model.php create mode 100644 module/editor/view/edit.html.php create mode 100644 module/editor/view/extend.html.php create mode 100644 module/editor/view/index.html.php create mode 100644 module/editor/view/newpage.html.php diff --git a/module/common/lang/en.php b/module/common/lang/en.php index ee0319db50..85d4dbb789 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -374,7 +374,7 @@ $lang->admin->menu->message = array('link' => 'Notification|message|index', 's $lang->admin->menu->custom = array('link' => 'Custom|custom|set', 'subModule' => 'custom'); $lang->admin->menu->sso = array('link' => 'Integration|admin|sso'); -$lang->admin->menu->dev = array('link' => 'Devel|dev|api', 'alias' => 'db', 'subModule' => 'dev,entry'); +$lang->admin->menu->dev = array('link' => 'CSD|dev|api', 'alias' => 'db', 'subModule' => 'dev,editor,entry'); $lang->admin->menu->translate = array('link' => 'Translate|translate|index', 'subModule' => 'translate'); $lang->admin->menu->data = array('link' => 'Data|backup|index', 'subModule' => 'backup,action'); $lang->admin->menu->safe = array('link' => 'Security|admin|safe', 'alias' => 'checkweak'); @@ -392,6 +392,7 @@ $lang->admin->subMenu->sso->ranzhi = 'Zdoo|admin|sso'; $lang->admin->subMenu->dev = new stdclass(); $lang->admin->subMenu->dev->api = array('link' => 'API|dev|api'); $lang->admin->subMenu->dev->db = array('link' => 'Database|dev|db'); +$lang->admin->subMenu->dev->editor = array('link' => 'Editor|editor|index', 'subModule' => 'editor'); $lang->admin->subMenu->dev->entry = array('link' => 'Application|entry|browse', 'subModule' => 'entry'); $lang->admin->subMenu->data = new stdclass(); @@ -416,6 +417,7 @@ $lang->webhook = new stdclass(); $lang->message = new stdclass(); $lang->search = new stdclass(); $lang->translate = new stdclass(); +$lang->editor = new stdclass(); $lang->convert->menu = $lang->admin->menu; $lang->upgrade->menu = $lang->admin->menu; @@ -430,6 +432,7 @@ $lang->entry->menu = $lang->admin->menu; $lang->webhook->menu = $lang->admin->menu; $lang->message->menu = $lang->admin->menu; $lang->translate->menu = $lang->admin->menu; +$lang->editor->menu = $lang->admin->menu; /* Menu group. */ $lang->menugroup = new stdclass(); @@ -467,6 +470,7 @@ $lang->menugroup->entry = 'admin'; $lang->menugroup->webhook = 'admin'; $lang->menugroup->message = 'admin'; $lang->menugroup->translate = 'admin'; +$lang->menugroup->editor = 'admin'; /* Error info. */ $lang->error = new stdclass(); diff --git a/module/common/lang/menuOrder.php b/module/common/lang/menuOrder.php index 012d3b8ca4..5923b7debe 100644 --- a/module/common/lang/menuOrder.php +++ b/module/common/lang/menuOrder.php @@ -120,6 +120,7 @@ $lang->admin->subMenuOrder->message[15] = 'setting'; $lang->admin->subMenuOrder->sso[5] = 'ranzhi'; $lang->admin->subMenuOrder->dev[5] = 'api'; $lang->admin->subMenuOrder->dev[10] = 'db'; +$lang->admin->subMenuOrder->dev[15] = 'editor'; $lang->admin->subMenuOrder->dev[20] = 'entry'; $lang->admin->subMenuOrder->data[5] = 'backup'; $lang->admin->subMenuOrder->data[10] = 'trash'; @@ -137,3 +138,4 @@ $lang->mail->menuOrder = $lang->admin->menuOrder; $lang->dev->menuOrder = $lang->admin->menuOrder; $lang->entry->menuOrder = $lang->admin->menuOrder; $lang->webhook->menuOrder = $lang->admin->menuOrder; +$lang->editor->menuOrder = $lang->admin->menuOrder; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 65933e239a..d9ff4d055a 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -374,7 +374,7 @@ $lang->admin->menu->message = array('link' => '通知|message|index', 'subModu $lang->admin->menu->custom = array('link' => '自定义|custom|set', 'subModule' => 'custom'); $lang->admin->menu->sso = array('link' => '集成|admin|sso'); $lang->admin->menu->extension = array('link' => '插件|extension|browse', 'subModule' => 'extension'); -$lang->admin->menu->dev = array('link' => '二次开发|dev|api', 'alias' => 'db', 'subModule' => 'dev,entry'); +$lang->admin->menu->dev = array('link' => '二次开发|dev|api', 'alias' => 'db', 'subModule' => 'dev,editor,entry'); $lang->admin->menu->translate = array('link' => '翻译|translate|index', 'subModule' => 'translate'); $lang->admin->menu->data = array('link' => '数据|backup|index', 'subModule' => 'backup,action'); $lang->admin->menu->safe = array('link' => '安全|admin|safe', 'alias' => 'checkweak'); @@ -392,6 +392,7 @@ $lang->admin->subMenu->sso->ranzhi = '然之协同|admin|sso'; $lang->admin->subMenu->dev = new stdclass(); $lang->admin->subMenu->dev->api = array('link' => 'API|dev|api'); $lang->admin->subMenu->dev->db = array('link' => '数据库|dev|db'); +$lang->admin->subMenu->dev->editor = array('link' => '编辑器|editor|index', 'subModule' => 'editor'); $lang->admin->subMenu->dev->entry = array('link' => '应用|entry|browse', 'subModule' => 'entry'); $lang->admin->subMenu->data = new stdclass(); @@ -416,6 +417,7 @@ $lang->webhook = new stdclass(); $lang->message = new stdclass(); $lang->search = new stdclass(); $lang->translate = new stdclass(); +$lang->editor = new stdclass(); $lang->convert->menu = $lang->admin->menu; $lang->upgrade->menu = $lang->admin->menu; @@ -430,6 +432,7 @@ $lang->entry->menu = $lang->admin->menu; $lang->webhook->menu = $lang->admin->menu; $lang->message->menu = $lang->admin->menu; $lang->translate->menu = $lang->admin->menu; +$lang->editor->menu = $lang->admin->menu; /* 菜单分组。*/ $lang->menugroup = new stdclass(); @@ -467,6 +470,7 @@ $lang->menugroup->entry = 'admin'; $lang->menugroup->webhook = 'admin'; $lang->menugroup->message = 'admin'; $lang->menugroup->translate = 'admin'; +$lang->menugroup->editor = 'admin'; /* 错误提示信息。*/ $lang->error = new stdclass(); diff --git a/module/editor/config.php b/module/editor/config.php new file mode 100644 index 0000000000..59e9e26969 --- /dev/null +++ b/module/editor/config.php @@ -0,0 +1,18 @@ +editor->sort[] = 'model.php'; +$config->editor->sort[] = 'control.php'; +$config->editor->sort[] = 'view'; +$config->editor->sort[] = 'lang'; +$config->editor->sort[] = 'config.php'; +$config->editor->sort[] = 'js'; +$config->editor->sort[] = 'css'; +$config->editor->sort[] = 'ext'; + +$config->editor->extSort[] = 'model'; +$config->editor->extSort[] = 'control'; +$config->editor->extSort[] = 'view'; +$config->editor->extSort[] = 'lang'; +$config->editor->extSort[] = 'js'; +$config->editor->extSort[] = 'css'; +$config->editor->extSort[] = 'config'; + diff --git a/module/editor/control.php b/module/editor/control.php new file mode 100644 index 0000000000..7b0dbb817b --- /dev/null +++ b/module/editor/control.php @@ -0,0 +1,182 @@ + + * @package editor + * @version $Id$ + * @link http://www.zentao.net + */ +class editor extends control +{ + public function __construct($moduleName = '', $methodName = '', $appName = '') + { + parent::__construct($moduleName, $methodName, $appName); + + $remoteIP = helper::getRemoteIp(); + if($remoteIP != '127.0.0.1') die("{$this->lang->editor->onlyLocalVisit}"); + } + + /** + * Show module files and edit them. + * + * @access public + * @return void + */ + public function index($type = 'editor') + { + $this->app->loadLang('dev'); + $this->view->title = $this->lang->editor->common; + $this->view->position[] = $this->lang->editor->common; + $this->view->modules = $this->loadModel('dev')->getModules(); + $this->view->tab = $type; + $this->display(); + } + + /** + * Show files and methods of the module. + * + * @param string $moduleDir + * @access public + * @return void + */ + public function extend($moduleDir = '') + { + $moduleFiles = $this->editor->getModuleFiles($moduleDir); + $this->view->module = $moduleDir; + $this->view->tree = $this->editor->printTree($moduleFiles); + $this->display(); + } + + /** + * Edit extend. + * + * @param string $filePath + * @param string $action + * @param string $isExtends + * @access public + * @return void + */ + public function edit($filePath = '', $action = '', $isExtends = '') + { + $this->view->safeFilePath = $filePath; + $fileContent = ''; + if($filePath) + { + $filePath = helper::safe64Decode($filePath); + if(strpos(strtolower($filePath), strtolower($this->app->getBasePath())) !== 0) die($this->lang->editor->editFileError); + if($action == 'extendOther' and file_exists($filePath)) + { + $this->view->showContent = htmlspecialchars(file_get_contents($filePath)); + } + if($action == 'edit' or $action == 'override') + { + if(file_exists($filePath)) + { + $fileContent = file_get_contents($filePath); + if($action == 'override') + { + $fileContent = str_replace('../../', '../../../', $fileContent); + $fileContent = str_replace(array('\'./', '"./'), array('\'../../view/', '"../../view'), $fileContent); + } + } + else + { + $filePath = ''; + } + } + elseif($action == 'extendModel') + { + $fileContent = $this->editor->extendModel($filePath); + } + elseif($action == 'extendControl') + { + $okUrl = $this->editor->getExtendLink($filePath, 'extendControl', 'yes'); + $cancelUrl = $this->editor->getExtendLink($filePath, 'extendControl', 'no'); + if(!$isExtends) die(js::confirm($this->lang->editor->extendConfirm, $okUrl, $cancelUrl)); + $fileContent = $this->editor->extendControl($filePath, $isExtends); + } + elseif($action == 'newPage') + { + $fileContent = $this->editor->newControl($filePath); + } + elseif(strrpos(basename($filePath), '.php') !== false and empty($fileContent)) + { + $fileContent = "view->fileContent = $fileContent; + $this->view->filePath = $filePath; + $this->view->action = $action; + $this->display(); + } + + /** + * Set Page name. + * + * @param string $filePath + * @access public + * @return void + */ + public function newPage($filePath) + { + $filePath = helper::safe64Decode($filePath); + if($_POST) + { + $saveFilePath = $this->editor->getSavePath($filePath, 'newMethod'); + $extendLink = $this->editor->getExtendLink($saveFilePath, 'newPage'); + if(file_exists($saveFilePath) and !$this->post->override) die(js::confirm($this->lang->editor->repeatPage, $extendLink, '', 'parent')); + die(js::locate($extendLink, 'parent')); + } + $this->view->filePath = $filePath; + $this->display(); + } + + /** + * Save file to extension. + * + * @param string $filePath + * @access public + * @return void + */ + public function save($filePath = '', $action = '') + { + $statusFile = $this->loadModel('upgrade')->checkSafeFile(); + if($statusFile) + { + die(js::alert(sprintf($this->lang->editor->noticeOkFile, $statusFile))); + } + if($filePath and $_POST) + { + $filePath = helper::safe64Decode($filePath); + if(strpos(strtolower($filePath), strtolower($this->app->getBasePath())) !== 0) die($this->lang->editor->editFileError); + if($action != 'edit' and $action != 'newPage') $filePath = $this->editor->getSavePath($filePath, $action); + if($action != 'edit' and $action != 'newPage' and file_exists($filePath) and !$this->post->override) die(js::error($this->lang->editor->repeatFile)); + $this->editor->save($filePath); + echo js::reload('parent.parent.extendWin'); + die(js::locate(inlink('edit', "filePath=" . helper::safe64Encode($filePath) . "&action=edit"), 'parent')); + } + } + + /** + * Delete extension file. + * + * @param string $filePath + * @param string $confirm + * @access public + * @return void + */ + public function delete($filePath = '', $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->editor->deleteConfirm, inlink('delete', "filePath=$filePath&confirm=yes"))); + } + $filePath = helper::safe64Decode($filePath); + if(file_exists($filePath) and unlink($filePath)) die(js::reload('parent')); + die(js::alert($this->lang->editor->notDelete)); + + } +} diff --git a/module/editor/css/edit.css b/module/editor/css/edit.css new file mode 100644 index 0000000000..b72138a1a8 --- /dev/null +++ b/module/editor/css/edit.css @@ -0,0 +1,2 @@ +body{padding-bottom:0px;background-color:#fff;} +.main-content textarea.form-control {min-height: 450px; height: auto;} diff --git a/module/editor/css/extend.css b/module/editor/css/extend.css new file mode 100644 index 0000000000..e019a90efa --- /dev/null +++ b/module/editor/css/extend.css @@ -0,0 +1,5 @@ +body{padding-bottom:0px;background-color:#fff;} +.expandable > ul {display: none!important} +.collapsable > ul {display: block!important} +.tree li:before {margin-right: 4px;} +.tree li>a{display:inline;} diff --git a/module/editor/css/index.css b/module/editor/css/index.css new file mode 100644 index 0000000000..01cd89494e --- /dev/null +++ b/module/editor/css/index.css @@ -0,0 +1,6 @@ +table td {padding: 0 10px; vertical-align: top;} +table tr > td:first-child {padding-left: 0;} +table tr > td:last-child {padding-right: 0;} +.modulegroup {font-weight:bold; padding-top:8px; border-top:1px solid #ddd;} +td.w-200px a:hover {font-weight:bold;} +.w-350px{width:350px;} diff --git a/module/editor/js/edit.js b/module/editor/js/edit.js new file mode 100644 index 0000000000..6e853d71c2 --- /dev/null +++ b/module/editor/js/edit.js @@ -0,0 +1 @@ +$(function(){ }) diff --git a/module/editor/js/index.js b/module/editor/js/index.js new file mode 100644 index 0000000000..c2b1ddc184 --- /dev/null +++ b/module/editor/js/index.js @@ -0,0 +1,12 @@ +$(function() +{ + var showHeight = $('#main').height() - $('#mainMenu').height() - 40; + $('#editWin').height(showHeight); + $('#extendWin').height(showHeight); + + $('.side-col a').click(function() + { + $('.side-col a.active').removeClass('active'); + $(this).addClass('active'); + }); +}); diff --git a/module/editor/lang/en.php b/module/editor/lang/en.php new file mode 100644 index 0000000000..8cce94f89a --- /dev/null +++ b/module/editor/lang/en.php @@ -0,0 +1,75 @@ +editor->common = 'Editor'; +$lang->editor->api = 'API'; +$lang->editor->index = 'Home'; +$lang->editor->newMethod = 'New Method'; +$lang->editor->extend = 'Extension'; +$lang->editor->api = 'API'; +$lang->editor->newLang = 'New Language'; +$lang->editor->newConfig = 'New Config'; +$lang->editor->newHook = 'New Hook'; +$lang->editor->newExtend = 'New Extension'; +$lang->editor->newPage = 'New Page'; +$lang->editor->override = 'Overwrite'; +$lang->editor->edit = 'Edit Extension'; +$lang->editor->save = 'Save Page'; +$lang->editor->delete = 'Delete Page'; + +$lang->editor->moduleList = 'Module'; +$lang->editor->filePath = "Extension:"; +$lang->editor->sourceFile = 'Source File:'; +$lang->editor->fileName = "File Name:"; +$lang->editor->isOverride = "Override Duplicated File"; +$lang->editor->exampleHook = "(e.g. ***.html.hook.php)"; +$lang->editor->exampleJs = "(e.g. ***.js)"; +$lang->editor->exampleCss = "(e.g. ***.css)"; +$lang->editor->examplePHP = "(e.g. ***.php)"; +$lang->editor->pageName = "Page Name:"; + +$lang->editor->deleteConfirm = 'Do you want to delete it?'; +$lang->editor->extendConfirm = 'Do you want to use original code?'; +$lang->editor->repeatFile = 'File Name Duplicated'; +$lang->editor->repeatPage = 'This page exists. Do you want to overwrite it?'; +$lang->editor->noticeOkFile = 'For security reasons, your Admin account has to be confirmed. \n Please login ZenTao server and create %sFile.\n Note:\n 1. File is blank.\n 2. If the file existed, delete it and then create a new one.'; +$lang->editor->editFileError = 'You can only modify ZenTao files!'; + +$lang->editor->notWritable = "Not wirtable. Permission is required. Please try chmod 777 -R "; +$lang->editor->notDelete = 'Cannot be deleted. Please check your permissions!'; +$lang->editor->emptyFileName = 'Please enter a File Name!'; + +$lang->editor->translate['config.php'] = 'config'; +$lang->editor->translate['control.php'] = 'control'; +$lang->editor->translate['model.php'] = 'model'; + +$lang->editor->modules['action'] = 'System Log'; +$lang->editor->modules['admin'] = 'Admin'; +$lang->editor->modules['api'] = 'API'; +$lang->editor->modules['bug'] = 'Bug'; +$lang->editor->modules['build'] = 'Build'; +$lang->editor->modules['common'] = 'Common Module'; +$lang->editor->modules['company'] = 'Company'; +$lang->editor->modules['convert'] = 'Convert'; +$lang->editor->modules['dept'] = 'Department'; +$lang->editor->modules['doc'] = 'Doc'; +$lang->editor->modules['extension'] = 'Extension'; +$lang->editor->modules['file'] = 'File'; +$lang->editor->modules['group'] = 'Group'; +$lang->editor->modules['index'] = 'Homepage'; +$lang->editor->modules['install'] = 'Install'; +$lang->editor->modules['misc'] = 'Misc'; +$lang->editor->modules['my'] = 'Dashboard'; +$lang->editor->modules['product'] = $lang->productCommon; +$lang->editor->modules['productplan'] = 'Plan'; +$lang->editor->modules['project'] = $lang->projectCommon; +$lang->editor->modules['qa'] = 'QA'; +$lang->editor->modules['release'] = 'Release'; +$lang->editor->modules['report'] = 'Report'; +$lang->editor->modules['search'] = 'Search'; +$lang->editor->modules['story'] = 'Story'; +$lang->editor->modules['task'] = 'Task'; +$lang->editor->modules['testcase'] = 'Case'; +$lang->editor->modules['testtask'] = 'Request'; +$lang->editor->modules['todo'] = 'Todo'; +$lang->editor->modules['tree'] = 'Module Maintenance'; +$lang->editor->modules['upgrade'] = 'Upgrade'; +$lang->editor->modules['user'] = 'User'; diff --git a/module/editor/lang/zh-cn.php b/module/editor/lang/zh-cn.php new file mode 100644 index 0000000000..5c826fafd2 --- /dev/null +++ b/module/editor/lang/zh-cn.php @@ -0,0 +1,76 @@ +editor->common = '编辑器'; +$lang->editor->api = 'API'; +$lang->editor->index = '首页'; +$lang->editor->newMethod = '新增方法'; +$lang->editor->extend = '扩展'; +$lang->editor->api = 'API'; +$lang->editor->newLang = '新增语言'; +$lang->editor->newConfig = '新增配置'; +$lang->editor->newHook = '新增钩子'; +$lang->editor->newExtend = '新增扩展'; +$lang->editor->newPage = '新增页面'; +$lang->editor->override = '覆盖'; +$lang->editor->edit = '编辑扩展'; +$lang->editor->save = '保存页面'; +$lang->editor->delete = '删除页面'; + +$lang->editor->moduleList = '模块列表'; +$lang->editor->filePath = "扩展:"; +$lang->editor->sourceFile = '源文件:'; +$lang->editor->fileName = "文件名:"; +$lang->editor->isOverride = "覆盖重复文件"; +$lang->editor->exampleHook = "(例如:***.html.hook.php)"; +$lang->editor->exampleJs = "(例如:***.js)"; +$lang->editor->exampleCss = "(例如:***.css)"; +$lang->editor->examplePHP = "(例如:***.php)"; +$lang->editor->pageName = "页面名称:"; + +$lang->editor->deleteConfirm = '是否要删除?'; +$lang->editor->extendConfirm = '是否要重用原来代码?'; +$lang->editor->repeatFile = '文件名重复'; +$lang->editor->repeatPage = '已经有此页面。是否覆盖?'; +$lang->editor->noticeOkFile = '为了安全起见,系统需要确认您的管理员身份。\n 请登录禅道所在的服务器,创建%s文件。\n 注意:\n 1. 文件内容为空。\n 2. 如果之前文件存在,删除之后重新创建。'; +$lang->editor->editFileError = '只能修改禅道文件!'; + +$lang->editor->notWritable = "无法写入,可能没有权限。请尝试执行 chmod 777 -R "; +$lang->editor->notDelete = '无法删除,请检查权限!'; +$lang->editor->emptyFileName = '请写入一个文件名!'; +$lang->editor->onlyLocalVisit = '该功能只能在IP:127.0.0.1下访问。'; + +$lang->editor->translate['config.php'] = 'config'; +$lang->editor->translate['control.php'] = 'control'; +$lang->editor->translate['model.php'] = 'model'; + +$lang->editor->modules['action'] = '系统日志'; +$lang->editor->modules['admin'] = '后台管理'; +$lang->editor->modules['api'] = 'API接口'; +$lang->editor->modules['bug'] = 'Bug管理'; +$lang->editor->modules['build'] = 'Build'; +$lang->editor->modules['common'] = '公有模块'; +$lang->editor->modules['company'] = '组织视图'; +$lang->editor->modules['convert'] = '从其他系统导入'; +$lang->editor->modules['dept'] = '部门结构'; +$lang->editor->modules['doc'] = '文档视图'; +$lang->editor->modules['extension'] = '插件管理'; +$lang->editor->modules['file'] = '附件'; +$lang->editor->modules['group'] = '权限分组'; +$lang->editor->modules['index'] = '首页'; +$lang->editor->modules['install'] = '安装'; +$lang->editor->modules['misc'] = '杂项'; +$lang->editor->modules['my'] = '我的地盘'; +$lang->editor->modules['product'] = $lang->productCommon . '视图'; +$lang->editor->modules['productplan'] = '计划'; +$lang->editor->modules['project'] = $lang->projectCommon . '视图'; +$lang->editor->modules['qa'] = '测试视图'; +$lang->editor->modules['release'] = '发布'; +$lang->editor->modules['report'] = '报表'; +$lang->editor->modules['search'] = '搜索'; +$lang->editor->modules['story'] = '需求'; +$lang->editor->modules['task'] = '任务'; +$lang->editor->modules['testcase'] = '用例管理'; +$lang->editor->modules['testtask'] = '测试任务'; +$lang->editor->modules['todo'] = '待办'; +$lang->editor->modules['tree'] = '模块维护'; +$lang->editor->modules['upgrade'] = '升级'; +$lang->editor->modules['user'] = '用户'; diff --git a/module/editor/lang/zh-tw.php b/module/editor/lang/zh-tw.php new file mode 100644 index 0000000000..692a552ef2 --- /dev/null +++ b/module/editor/lang/zh-tw.php @@ -0,0 +1,75 @@ +editor->common = '編輯器'; +$lang->editor->api = 'API'; +$lang->editor->index = '首頁'; +$lang->editor->newMethod = '新增方法'; +$lang->editor->extend = '擴展'; +$lang->editor->api = 'API'; +$lang->editor->newLang = '新增語言'; +$lang->editor->newConfig = '新增配置'; +$lang->editor->newHook = '新增鈎子'; +$lang->editor->newExtend = '新增擴展'; +$lang->editor->newPage = '新增頁面'; +$lang->editor->override = '覆蓋'; +$lang->editor->edit = '編輯擴展'; +$lang->editor->save = '保存頁面'; +$lang->editor->delete = '刪除頁面'; + +$lang->editor->moduleList = '模組列表'; +$lang->editor->filePath = "擴展:"; +$lang->editor->sourceFile = '源檔案:'; +$lang->editor->fileName = "檔案名:"; +$lang->editor->isOverride = "覆蓋重複檔案"; +$lang->editor->exampleHook = "(例如:***.html.hook.php)"; +$lang->editor->exampleJs = "(例如:***.js)"; +$lang->editor->exampleCss = "(例如:***.css)"; +$lang->editor->examplePHP = "(例如:***.php)"; +$lang->editor->pageName = "頁面名稱:"; + +$lang->editor->deleteConfirm = '是否要刪除?'; +$lang->editor->extendConfirm = '是否要重用原來代碼?'; +$lang->editor->repeatFile = '檔案名重複'; +$lang->editor->repeatPage = '已經有此頁面。是否覆蓋?'; +$lang->editor->noticeOkFile = '為了安全起見,系統需要確認您的管理員身份。\n 請登錄禪道所在的伺服器,創建%s檔案。\n 注意:\n 1. 檔案內容為空。\n 2. 如果之前檔案存在,刪除之後重新創建。'; +$lang->editor->editFileError = '只能修改禪道檔案!'; + +$lang->editor->notWritable = "無法寫入,可能沒有權限。請嘗試執行 chmod 777 -R "; +$lang->editor->notDelete = '無法刪除,請檢查權限!'; +$lang->editor->emptyFileName = '請寫入一個檔案名!'; + +$lang->editor->translate['config.php'] = 'config'; +$lang->editor->translate['control.php'] = 'control'; +$lang->editor->translate['model.php'] = 'model'; + +$lang->editor->modules['action'] = '系統日誌'; +$lang->editor->modules['admin'] = '後台管理'; +$lang->editor->modules['api'] = 'API介面'; +$lang->editor->modules['bug'] = 'Bug管理'; +$lang->editor->modules['build'] = 'Build'; +$lang->editor->modules['common'] = '公有模組'; +$lang->editor->modules['company'] = '組織視圖'; +$lang->editor->modules['convert'] = '從其他系統導入'; +$lang->editor->modules['dept'] = '部門結構'; +$lang->editor->modules['doc'] = '文檔視圖'; +$lang->editor->modules['extension'] = '插件管理'; +$lang->editor->modules['file'] = '附件'; +$lang->editor->modules['group'] = '權限分組'; +$lang->editor->modules['index'] = '首頁'; +$lang->editor->modules['install'] = '安裝'; +$lang->editor->modules['misc'] = '雜項'; +$lang->editor->modules['my'] = '我的地盤'; +$lang->editor->modules['product'] = $lang->productCommon . '視圖'; +$lang->editor->modules['productplan'] = '計劃'; +$lang->editor->modules['project'] = $lang->projectCommon . '視圖'; +$lang->editor->modules['qa'] = '測試視圖'; +$lang->editor->modules['release'] = '發佈'; +$lang->editor->modules['report'] = '報表'; +$lang->editor->modules['search'] = '搜索'; +$lang->editor->modules['story'] = '需求'; +$lang->editor->modules['task'] = '任務'; +$lang->editor->modules['testcase'] = '用例管理'; +$lang->editor->modules['testtask'] = '測試任務'; +$lang->editor->modules['todo'] = '待辦'; +$lang->editor->modules['tree'] = '模組維護'; +$lang->editor->modules['upgrade'] = '升級'; +$lang->editor->modules['user'] = '用戶'; diff --git a/module/editor/model.php b/module/editor/model.php new file mode 100644 index 0000000000..dc1b2621d1 --- /dev/null +++ b/module/editor/model.php @@ -0,0 +1,572 @@ + + * @package editor + * @version $Id$ + * @link http://www.zentao.net + */ +class editorModel extends model +{ + /** + * Get all modules + * + * @access public + * @return string + */ + public function getModules() + { + $modules = glob($this->app->getModuleRoot() . '*'); + $moduleList = "
"; + foreach($modules as $module) + { + $module = basename($module); + if($module == 'editor' or $module == 'help' or $module == 'setting') continue; + $moduleName = !empty($this->lang->editor->modules[$module]) ? $this->lang->editor->modules[$module] : $module; + $moduleList .= html::a(inlink('extend', "moduleDir=$module"), $moduleName, 'extendWin', "class='list-group-item'"); + } + $moduleList .= '
'; + return $moduleList; + } + + /** + * Get module files, contain control's methods and model's method but except ext. + * + * @access public + * @return array + */ + public function getModuleFiles($moduleDir) + { + $moduleRoot = $this->app->getModuleRoot(); + $moduleFullDir = $moduleRoot . $moduleDir; + $moduleFiles = scandir($moduleFullDir); + foreach($moduleFiles as $moduleFile) + { + if($moduleFile == '.' or $moduleFile == '..' or $moduleFile == '.svn') continue; + $moduleFullFile = $moduleFullDir . DS . $moduleFile; + if($moduleFile == 'control.php' or $moduleFile == 'model.php') + { + $allModules[$moduleFullDir][$moduleFullFile] = $this->analysis($moduleFullFile); + } + elseif($moduleFile == 'ext') + { + $allModules[$moduleFullDir][$moduleFullFile] = $this->getExtensionFiles($moduleFullFile); + } + elseif(is_dir($moduleFullFile)) + { + $ext = ($moduleFile == 'js' or $moduleFile == 'css') ? $moduleFile : 'php'; + $extFiles = glob($moduleFullFile . DS . "*.$ext"); + if(!empty($extFiles)) + { + foreach($extFiles as $fileName) $allModules[$moduleFullDir][$moduleFullFile][$fileName] = basename($fileName); + } + } + else + { + $allModules[$moduleFullDir][$moduleFullFile] = $moduleFile; + } + } + $allModules = $this->sortModule($moduleFullDir, $allModules); + return $allModules; + } + + /** + * Get extension files. + * + * @param int $extPath + * @access public + * @return void + */ + public function getExtensionFiles($extPath) + { + $extensionList = array(); + $extensionDirs = scandir($extPath); + foreach($extensionDirs as $extensionDir) + { + if($extensionDir == '.' or $extensionDir == '..' or $extensionDir == '.svn') continue; + $extensionFullDir = $extPath . DS . $extensionDir; + if(is_dir($extensionFullDir)) + { + $extensionList[$extensionFullDir] = array(); + /* extend of lang is more a grade of directroy. */ + if($extensionDir == 'lang' or $extensionDir == 'js' or $extensionDir == 'css') + { + + $extensionList[$extensionFullDir] = $this->getTwoGradeFiles($extensionFullDir); + continue; + } + $extensionFiles = scandir($extensionFullDir); + foreach($extensionFiles as $extensionFile) + { + if($extensionFile == '.' or $extensionFile == '..' or $extensionFile == '.svn') continue; + $extensionFullFile = $extensionFullDir . DS . $extensionFile; + $extensionList[$extensionFullDir][$extensionFullFile] = $extensionFile; + } + } + } + $extensionList = $this->sortModule($extPath, $extensionList, true); + return $extensionList; + } + + /** + * Sort module + * + * @param string $filePath + * @param string $moduleFiles + * @param bool $isExtension + * @access public + * @return array + */ + public function sortModule($filePath, $moduleFiles, $isExtension = false) + { + $sort = $isExtension ? 'extSort' : 'sort'; + $sortModules = array(); + if(!$isExtension) $moduleFiles = $moduleFiles[$filePath]; + foreach($this->config->editor->$sort as $sort) + { + $sortKey = empty($sort) ? $filePath : $filePath . DS . $sort; + if(array_key_exists($sortKey, $moduleFiles)) $sortModules[$sortKey] = $moduleFiles[$sortKey]; + } + return $sortModules; + } + + /** + * if a directory has two grage, this method will get files + * + * @param string $extensionFullDir + * @access public + * @return string + */ + public function getTwoGradeFiles($extensionFullDir) + { + $fileList = array(); + $langDirs = scandir($extensionFullDir); + foreach($langDirs as $langDir) + { + if($langDir == '.' or $langDir == '..' or $langDir == '.svn') continue; + $langFullDir = $extensionFullDir . DS . $langDir; + $fileList[$langFullDir] = array(); + if(is_dir($langFullDir)) + { + $langFiles = scandir($langFullDir); + foreach($langFiles as $langFile) + { + if($langFile == '.' or $langFile == '..' or $langFile == '.svn') continue; + $langFullFile = $langFullDir . DS . $langFile; + $fileList[$langFullDir][$langFullFile] = $langFile; + } + } + } + return $fileList; + } + + /** + * Analysis methods of control and model. + * + * @param string $fileName + * @access public + * @return array + */ + public function analysis($fileName) + { + $classMethod = array(); + $class = strstr($fileName, DS . 'module' . DS); + $class = substr($class, 0, strpos($class, DS, 9)); + $class = basename($class); + if(strpos($fileName, 'model.php') !== false) $class .= 'Model'; + if(!class_exists($class)) include $fileName; + $reflection = new ReflectionClass($class); + foreach($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) + { + $methodName = $method->name; + if($method->getFileName() != $fileName) continue; + if($methodName == '__construct') continue; + $classMethod[$fileName . DS . $methodName] = $methodName; + } + return $classMethod; + } + + /** + * Print tree from module files. + * + * @param int $files + * @access public + * @return void + */ + public function printTree($files, $isRoot = true) + { + if(empty($files) or !is_array($files)) return false; + $tree = $isRoot ? "